Package org.jboss.errai.ioc.rebind.ioc.codegen.meta.impl

Source Code of org.jboss.errai.ioc.rebind.ioc.codegen.meta.impl.AbstractMetaClass

/*
* Copyright 2011 JBoss, a divison Red Hat, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jboss.errai.ioc.rebind.ioc.codegen.meta.impl;

import static org.jboss.errai.ioc.rebind.ioc.InjectUtil.classToMeta;
import static org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaClassFactory.asClassArray;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaClass;
import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaClassFactory;
import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaConstructor;
import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaMethod;
import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaParameter;
import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaParameterizedType;
import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaType;
import org.mvel2.util.ParseTools;

import com.google.gwt.core.ext.typeinfo.JClassType;

/**
* @author Mike Brock <cbrock@redhat.com>
* @author Christian Sadilek <csadilek@redhat.com>
*/
public abstract class AbstractMetaClass<T> extends MetaClass {
  private final T enclosedMetaObject;
  protected MetaParameterizedType parameterizedType;

  protected AbstractMetaClass(T enclosedMetaObject) {
    this.enclosedMetaObject = enclosedMetaObject;
  }

  @Override
  public String getFullyQualifiedNameWithTypeParms() {
    StringBuilder buf = new StringBuilder(getFullyQualifiedName());
    buf.append(getTypeParmsString(getParameterizedType()));
    return buf.toString();
  }

  private String getTypeParmsString(MetaParameterizedType parameterizedType) {
    StringBuilder buf = new StringBuilder();

    if (parameterizedType != null && parameterizedType.getTypeParameters().length != 0) {
      buf.append("<");
      for (int i = 0; i < parameterizedType.getTypeParameters().length; i++) {

        MetaType typeParameter = parameterizedType.getTypeParameters()[i];
        if (typeParameter instanceof MetaParameterizedType) {
          MetaParameterizedType parameterizedTypeParemeter = (MetaParameterizedType) typeParameter;
          buf.append(((MetaClass) parameterizedTypeParemeter.getRawType()).getFullyQualifiedName());
          buf.append(getTypeParmsString(parameterizedTypeParemeter));
        }
        else {
          buf.append(((MetaClass) typeParameter).getFullyQualifiedName());
        }

        if (i + 1 < parameterizedType.getTypeParameters().length)
          buf.append(", ");
      }

      buf.append(">");
    }
    return buf.toString();
  }

  protected static MetaMethod _getMethod(MetaMethod[] methods, String name, MetaClass... parmTypes) {
    Outer:
    for (MetaMethod method : methods) {
      if (method.getName().equals(name) && method.getParameters().length == parmTypes.length) {
        for (int i = 0; i < parmTypes.length; i++) {
          if (!method.getParameters()[i].getType().isAssignableFrom(parmTypes[i])) {
            continue Outer;
          }
        }
        return method;
      }
    }
    return null;
  }

  protected static MetaConstructor _getConstructor(MetaConstructor[] constructors, MetaClass... parmTypes) {
    Outer:
    for (MetaConstructor constructor : constructors) {
      if (constructor.getParameters().length == parmTypes.length) {
        for (int i = 0; i < parmTypes.length; i++) {
          if (!constructor.getParameters()[i].getType().isAssignableFrom(parmTypes[i])) {
            continue Outer;
          }
        }
        return constructor;
      }
    }
    return null;
  }

  @Override
  public MetaMethod getMethod(String name, Class... parmTypes) {
    return _getMethod(getMethods(), name, classToMeta(parmTypes));
  }

  @Override
  public MetaMethod getMethod(String name, MetaClass... parameters) {
    return _getMethod(getMethods(), name, parameters);
  }

  @Override
  public MetaMethod getDeclaredMethod(String name, Class... parmTypes) {
    return _getMethod(getDeclaredMethods(), name, classToMeta(parmTypes));
  }

  @Override
  public MetaMethod getDeclaredMethod(String name, MetaClass... parmTypes) {
    return _getMethod(getDeclaredMethods(), name, parmTypes);
  }

  @Override
  public MetaMethod getBestMatchingMethod(String name, Class... parameters) {
    return getBestMatchingMethod(null, name, parameters);
  }

  @Override
  public MetaMethod getBestMatchingMethod(String name, MetaClass... parameters) {
    return getBestMatchingMethod(name, asClassArray(parameters));
  }

  @Override
  public MetaMethod getBestMatchingStaticMethod(String name, Class... parameters) {
    return getBestMatchingMethod(fromMetaMethod(getStaticMethods()), name, parameters);
  }

  @Override
  public MetaMethod getBestMatchingStaticMethod(String name, MetaClass... parameters) {
    return getBestMatchingStaticMethod(name, asClassArray(parameters));
  }

  private MetaMethod getBestMatchingMethod(Method[] methods, String name, Class... parameters) {
    Class<?> cls = asClass();

    if (cls != null) {
      methods = (methods == null) ? cls.getMethods() : methods;
      Method m = ParseTools.getBestCandidate(parameters, name, cls, methods, false);
      if (m == null) {
        if (isInterface()) {
          m = ParseTools.getBestCandidate(parameters, name, Object.class, Object.class.getMethods(), false);
        }

        if (m == null) {
          return null;
        }
      }
      m = ParseTools.getWidenedTarget(m);
      return getMethod(name, m.getParameterTypes());
    }
    else {
      return getMethod(name, parameters);
    }
  }

  private MetaMethod[] getStaticMethods() {
    List<MetaMethod> methods = new ArrayList<MetaMethod>();

    for (MetaMethod method : getMethods()) {
      if (method.isStatic()) {
        methods.add(method);
      }
    }

    return methods.toArray(new MetaMethod[methods.size()]);
  }

  private static Method[] fromMetaMethod(MetaMethod[] methods) {
    if (methods == null || methods.length == 0) {
      return new Method[0];
    }

    List<Method> staticMethods = new ArrayList<Method>();

    for (MetaMethod m : methods) {
      staticMethods.add(getJavaMethodFromMetaMethod(m));
    }

    return staticMethods.toArray(new Method[staticMethods.size()]);
  }

  private static Method getJavaMethodFromMetaMethod(MetaMethod method) {
    Class<?> declaring = method.getDeclaringClass().asClass();
    Class<?>[] parms = getParmTypes(method.getParameters());

    try {
      return declaring.getMethod(method.getName(), parms);
    }
    catch (NoSuchMethodException e) {
      return null;
    }
  }

  private static Class<?>[] getParmTypes(MetaParameter[] parameters) {
    List<Class<?>> parmTypes = new ArrayList<Class<?>>();

    for (MetaParameter parameter : parameters) {
      parmTypes.add(parameter.getType().asClass());
    }

    return parmTypes.toArray(new Class<?>[parmTypes.size()]);
  }

  @Override
  public MetaConstructor getBestMatchingConstructor(Class... parameters) {
    Class<?> cls = asClass();
    Constructor c = ParseTools.getBestConstructorCandidate(parameters, cls, false);
    if (c == null)
      return null;

    MetaClass metaClass = MetaClassFactory.get(cls);
    return metaClass.getConstructor(c.getParameterTypes());
  }

  @Override
  public MetaConstructor getBestMatchingConstructor(MetaClass... parameters) {
    return getBestMatchingConstructor(asClassArray(parameters));
  }

  @Override
  public MetaConstructor getConstructor(Class... parameters) {
    return _getConstructor(getConstructors(), classToMeta(parameters));
  }

  @Override
  public MetaConstructor getConstructor(MetaClass... parameters) {
    return _getConstructor(getConstructors(), parameters);
  }

  @Override
  public MetaConstructor getDeclaredConstructor(Class... parameters) {
    return _getConstructor(getDeclaredConstructors(), classToMeta(parameters));
  }

  @Override
  public final <A extends Annotation> A getAnnotation(Class<A> annotation) {
    for (Annotation a : getAnnotations()) {
      if (a.annotationType().equals(annotation))
        return (A) a;
    }
    return null;
  }

  @Override
  public final boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
    return getAnnotation(annotation) != null;
  }

  public T getEnclosedMetaObject() {
    return enclosedMetaObject;
  }

  private String hashString;

  private String hashString() {
    if (hashString == null) {
      hashString = MetaClass.class.getName() + ":" + getFullyQualifiedName();
      if (getParameterizedType() != null) {
        hashString += getParameterizedType().toString();
      }
    }
    return hashString;
  }

  @Override
  public boolean isAssignableFrom(MetaClass clazz) {
    if (equals(MetaClassFactory.get(Object.class)) && clazz.isInterface())
      return true;

    MetaClass cls = clazz;
    do {
      if (this.getFullyQualifiedName().equals(cls.getFullyQualifiedName()))
        return true;
    }
    while ((cls = cls.getSuperClass()) != null);

    return _hasInterface(clazz.getInterfaces(), this.getErased());
  }

  @Override
  public boolean isAssignableTo(MetaClass clazz) {
    if (isInterface() && clazz.equals(MetaClassFactory.get(Object.class)))
      return true;

    MetaClass cls = this;
    do {
      if (cls.equals(clazz))
        return true;
    }
    while ((cls = cls.getSuperClass()) != null);

    return _hasInterface(getInterfaces(), clazz.getErased());
  }

  private static boolean _hasInterface(MetaClass[] from, MetaClass to) {
    for (MetaClass iface : from) {
      if (to.getFullyQualifiedName().equals(iface.getErased().getFullyQualifiedName()))
        return true;
      else if (_hasInterface(iface.getInterfaces(), to))
        return true;
    }

    return false;
  }

  @Override
  public boolean isAssignableFrom(Class clazz) {
    return isAssignableFrom(MetaClassFactory.get(clazz));
  }

  @Override
  public boolean isAssignableTo(Class clazz) {
    return isAssignableTo(MetaClassFactory.get(clazz));
  }

  @Override
  public boolean isAssignableTo(JClassType clazz) {
    return isAssignableFrom(MetaClassFactory.get(clazz));
  }

  @Override
  public boolean isAssignableFrom(JClassType clazz) {
    return isAssignableTo(MetaClassFactory.get(clazz));
  }

  @Override
  public MetaParameterizedType getParameterizedType() {
    return parameterizedType;
  }

  @Override
  public boolean equals(Object o) {
    return o instanceof MetaClass && hashString().equals(MetaClass.class.getName()
            + ":" + ((MetaClass) o).getFullyQualifiedName());
  }

  @Override
  public int hashCode() {
    return hashString().hashCode();
  }

  @Override
  public Class<?> asClass() {
    Class<?> cls = null;

    if (isArray()) {
      try {
        String name = getInternalName().replaceAll("/", "\\.");
        cls = Class.forName(name, false,
                Thread.currentThread().getContextClassLoader());
      }
      catch (ClassNotFoundException e) {
        e.printStackTrace();
        cls = null;
      }
    }
    else if (enclosedMetaObject instanceof Class) {
      cls = (Class<?>) enclosedMetaObject;
    }
    else if (enclosedMetaObject != null) {
      try {
        cls = Class.forName(((JClassType) enclosedMetaObject).getQualifiedSourceName(), false,
                Thread.currentThread().getContextClassLoader());
      }
      catch (ClassNotFoundException e) {

      }
    }

    return cls;
  }

  @Override
  public MetaClass asBoxed() {
    return MetaClassFactory.get(ParseTools.boxPrimitive(asClass()));
  }

  @Override
  public MetaClass asUnboxed() {
    return MetaClassFactory.get(ParseTools.unboxPrimitive(asClass()));
  }

  @Override
  public MetaClass getErased() {
    try {
      return MetaClassFactory.get(getFullyQualifiedName());
    }
    catch (Exception e) {
      return this;
    }
  }

  public String getInternalName() {
    String name = getFullyQualifiedName();

    String dimString = "";
    if (isArray()) {
      MetaClass type = getComponentType();
      int dim = 1;
      while (type.isArray()) {
        dim++;
        type = type.getComponentType();
      }

      for (int i = 0; i < dim; i++) {
        dimString += "[";
      }

      name = type.getFullyQualifiedName();
    }

    if (isPrimitive()) {
      if ("int".equals(name)) {
        name = "I";
      }
      else if ("boolean".equals(name)) {
        name = "Z";
      }
      else if ("byte".equals(name)) {
        name = "B";
      }
      else if ("char".equals(name)) {
        name = "C";
      }
      else if ("short".equals(name)) {
        name = "S";
      }
      else if ("long".equals(name)) {
        name = "J";
      }
      else if ("float".equals(name)) {
        name = "F";
      }
      else if ("double".equals(name)) {
        name = "D";
      }
      else if ("void".equals(name)) {
        name = "V";
      }
    }
    else {
      name = "L" + name.replaceAll("\\.", "/") + ";";
    }


    return dimString + name;
  }
}
TOP

Related Classes of org.jboss.errai.ioc.rebind.ioc.codegen.meta.impl.AbstractMetaClass

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.