Package my.home.dsl.utils

Source Code of my.home.dsl.utils.ReflectionUtils$ByNamePredicate

package my.home.dsl.utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import my.home.dsl.deepClone.FieldClonerType;
import my.home.dsl.deepClone.SimpleField;

import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.common.types.JvmDeclaredType;
import org.eclipse.xtext.common.types.JvmField;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.util.TypeReferences;

import com.google.common.base.Predicate;
import com.google.inject.Inject;

/**
* Utility methods for handling introspection-like tasks. Like finding all
* member fields for a given Class/JvmType.
* <p>
* Original version of my ReflectionUtils really used Java Introspection. Now I
* use xtext.common.types. Why? I had ClassLoader issues
* (ClassNotFoundException) when run in full blown Eclipse environment and
* second, Introspection gives you run-time sort of information.
* xtext.common.types framework gives you build time sort of data, including
* generics (hopefully) otherwise erased from definition.
*
* @author espinosa
*/
@SuppressWarnings("restriction")
public class ReflectionUtils {
 
  @Inject TypeReferences typeReferences;
 
  /**
   * Get all member fields (bean properties) for a given JVM Type (Java Class)
   *
   * @param jvmTypeRef
   */
  public List<String> getFieldNamesForClass(JvmTypeReference jvmTypeRef) {
    List<String> result = new ArrayList<String>();
    if (jvmTypeRef.getType() instanceof JvmDeclaredType) {
      JvmDeclaredType declaredType = (JvmDeclaredType)jvmTypeRef.getType();
      for (JvmField field : declaredType.getDeclaredFields()) {
        result.add(field.getSimpleName());
      }
    }
    return result;
  }
 
  /**
   * Check first for {@link Collection} type. If the parent class is
   * {@link Collection} then look for generic type of the collection and use
   * that instead for {@link #getFieldNamesForClass(JvmTypeReference)}
   *
   * @param clazz
   * @return list of field names, class members, bean properties
   */
  public List<String> getFieldNamesForClassTreatCollections(JvmTypeReference clazz) {
    if (typeReferences.isInstanceOf(clazz, Collection.class)) {
      clazz = typeReferences.getArgument(clazz, 0);
    }
    return getFieldNamesForClass(clazz);
  }
 
  /**
   * If given type reference is a collection, then return collection type parameter.
   * If given type reference is not a collection, return the type as it is.
   * Example:
   * For java.util.List&lt;a.b.m.Section&gt; returns a.b.m.Section
   * For a.b.m.Book it returns a.b.m.Book
   * @param clazz
   * @return
   */
  public JvmTypeReference getTypeOrCollectionTypeParameter(JvmTypeReference clazz) {
    if (clazz==null) return null;
    if (typeReferences.isInstanceOf(clazz, Collection.class)) {
      clazz = typeReferences.getArgument(clazz, 0);
    }
    return clazz;
  }
 
  /**
   * Get first type parameter for a JvmTypeReference
   * @param clazz List<a.b.m.Section>
   * @return fully qualified name, example: "a.b.m.Section"
   */
  public String getTypeParameter(JvmTypeReference clazz) {
    if (clazz==null) return null;
    JvmTypeReference paramTypeClazz = typeReferences.getArgument(clazz, 0);
    return paramTypeClazz.getQualifiedName();
  }
 
  /**
   * Return field (bean property) for the given JVM Type (Java Class) and
   * field name
   *
   * @param parentContainerType
   *            container class reference
   * @param fieldName
   *            name of a filed (bean property) within this class
   * @return full JVM Field definition
   */
  public JvmField getField(JvmType parentContainerType, String fieldName) {
    if (parentContainerType instanceof JvmDeclaredType) {
      JvmDeclaredType declaredType = (JvmDeclaredType)parentContainerType;
      for (JvmField field : declaredType.getDeclaredFields()) {
        if (field.getSimpleName().equals(fieldName)) {
          return field;
        }
      }
    }
    return null;
  }
 
  /**
   * Return field type (bean property) for the given JVM Type (Java Class) and
   * field name
   *
   * @param containerClass container class reference
   * @param fieldName name of a filed within this class
   *
   * @return field Java class type or null if field is not declared in container class
   */
  public JvmTypeReference getFieldType(JvmType containerClass, String fieldName) {
    JvmField field = getField(containerClass, fieldName);
    if (field != null) {
      return field.getType();
    } else {
      return null;
    }
  }
 
  /**
   * Handling JvmTypeReference is somewhat tricky. Some operations require to
   * use a defensive copy. Example:
   *
   * <pre>
   * JvmTypeReference typeFoo1 = A.getField123Type()
   * B.setField567Type(typeFoo1)
   * </pre>
   *
   * ..would cause (unwanted) nullification of A.field123Type! Assigning type to a new field causes
   * detachement from original place. Defensive copy fixes this, nothing is detached.
   *
   * @param typeReference
   * @return
   */
  public JvmTypeReference createDefensiveCopyOfJvmTypeReference(JvmTypeReference typeReference) {
    //return typeReferences.createTypeRef(typeReference.getType());
    return EcoreUtil.copy(typeReference);
  }
 
  public static Predicate<FieldClonerType> byName(String name) {
    return new ByNamePredicate(name);
  }

  public static class ByNamePredicate implements Predicate<FieldClonerType> {
    String name;
    public ByNamePredicate(String name) {
      this.name = name;
    }
    @Override
    public boolean apply(FieldClonerType input) {
      return name.equals(input.getFieldName());
    }
  };
}
TOP

Related Classes of my.home.dsl.utils.ReflectionUtils$ByNamePredicate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.