Package org.jboss.errai.codegen.framework.meta.impl.build

Source Code of org.jboss.errai.codegen.framework.meta.impl.build.BuildMetaClass

/*
* Copyright 2011 JBoss, by 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
*       x
* 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.codegen.framework.meta.impl.build;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.jboss.errai.codegen.framework.BlockStatement;
import org.jboss.errai.codegen.framework.Context;
import org.jboss.errai.codegen.framework.DefParameters;
import org.jboss.errai.codegen.framework.InnerClass;
import org.jboss.errai.codegen.framework.Variable;
import org.jboss.errai.codegen.framework.builder.Builder;
import org.jboss.errai.codegen.framework.builder.callstack.LoadClassReference;
import org.jboss.errai.codegen.framework.builder.impl.Scope;
import org.jboss.errai.codegen.framework.literal.AnnotationLiteral;
import org.jboss.errai.codegen.framework.meta.MetaClass;
import org.jboss.errai.codegen.framework.meta.MetaClassFactory;
import org.jboss.errai.codegen.framework.meta.MetaConstructor;
import org.jboss.errai.codegen.framework.meta.MetaField;
import org.jboss.errai.codegen.framework.meta.MetaMethod;
import org.jboss.errai.codegen.framework.meta.MetaParameterizedType;
import org.jboss.errai.codegen.framework.meta.MetaTypeVariable;
import org.jboss.errai.codegen.framework.meta.impl.AbstractMetaClass;
import org.jboss.errai.codegen.framework.util.GenUtil;
import org.jboss.errai.codegen.framework.util.PrettyPrinter;

/**
* @author Mike Brock <cbrock@redhat.com>
*/
public class BuildMetaClass extends AbstractMetaClass<Object> implements Builder {
  private Context context;

  private String className;
  private MetaClass superClass;
  private List<MetaClass> interfaces = new ArrayList<MetaClass>();

  private Scope scope;

  private boolean isArray;
  private int dimensions;
  private boolean isInterface;
  private boolean isAbstract;
  private boolean isFinal;
  private boolean isStatic;
  private boolean isInner;

  private List<Annotation> annotations = new ArrayList<Annotation>();
  private List<InnerClass> innerClasses = new ArrayList<InnerClass>();
  private List<BuildMetaMethod> methods = new ArrayList<BuildMetaMethod>();
  private List<BuildMetaField> fields = new ArrayList<BuildMetaField>();
  private List<BuildMetaConstructor> constructors = new ArrayList<BuildMetaConstructor>();
  private List<MetaTypeVariable> typeVariables = new ArrayList<MetaTypeVariable>();
  private MetaClass reifiedFormOf;

  public BuildMetaClass(Context context, String name) {
    super(null);
    this.className = name;
    this.context = Context.create(context);
    this.context.addVariable(Variable.create("this", this));
    context.attachClass(this);
  }

  private BuildMetaClass shallowCopy() {
    BuildMetaClass copy = new BuildMetaClass(context, className);

    copy.superClass = superClass;
    copy.interfaces = interfaces;

    copy.isArray = isArray;
    copy.dimensions = dimensions;
    copy.isInterface = isInterface;
    copy.isAbstract = isAbstract;
    copy.isFinal = isFinal;
    copy.isStatic = isStatic;
    copy.isInner = isInner;

    copy.methods = methods;
    copy.fields = fields;
    copy.constructors = constructors;
    copy.typeVariables = typeVariables;
    copy.reifiedFormOf = reifiedFormOf;

    return copy;
  }


  String _nameCache;

  @Override
  public String getName() {
    if (_nameCache != null) return _nameCache;

    int idx = className.lastIndexOf('.');
    if (idx != -1) {
      return _nameCache = className.substring(idx + 1);
    }
    else {
      return _nameCache = className;
    }
  }

  @Override
  public String getFullyQualifiedName() {
    return className;
  }

  @Override
  public String getCanonicalName() {
    return className;
  }

  @Override
  public String getInternalName() {
    String internalName = "L" + className.replace("\\.", "/") + ";";
    if (isArray) {
      StringBuilder buf = new StringBuilder("");
      for (int i = 0; i < dimensions; i++) {
        buf.append("[");
      }
      return buf.append(internalName).toString();
    }
    else {
      return internalName;
    }
  }

  @Override
  public String getPackageName() {
    int idx = className.lastIndexOf(".");
    if (idx != -1) {
      return className.substring(0, idx);
    }
    return "";
  }

  private MetaMethod[] _methodsCache;

  @Override
  public MetaMethod[] getMethods() {
    if (_methodsCache != null) return _methodsCache;

    MetaMethod[] methodArray = methods.toArray(new MetaMethod[methods.size()]);
    MetaMethod[] outputMethods;

    if (superClass != null) {
      List<MetaMethod> methodList = new ArrayList<MetaMethod>();
      for (MetaMethod m : superClass.getMethods()) {
        if (_getMethod(methodArray, m.getName(), GenUtil.fromParameters(m.getParameters())) == null) {
          methodList.add(m);
        }
      }

      methodList.addAll(Arrays.asList(methodArray));

      outputMethods = methodList.toArray(new MetaMethod[methodList.size()]);
    }
    else {
      outputMethods = methodArray;
    }

    return _methodsCache = outputMethods;
  }

  @Override
  public MetaMethod[] getDeclaredMethods() {
    return getMethods();
  }

  private MetaField[] _fieldsCache;

  @Override
  public MetaField[] getFields() {
    if (_fieldsCache != null) return _fieldsCache;
    return _fieldsCache = fields.toArray(new MetaField[fields.size()]);
  }

  @Override
  public MetaField[] getDeclaredFields() {
    return getFields();
  }

  @Override
  public MetaField getField(String name) {
    for (MetaField field : fields) {
      if (field.getName().equals(name)) {
        return field;
      }
    }

    return null;
  }

  @Override
  public MetaField getDeclaredField(String name) {
    return getField(name);
  }

  private MetaConstructor[] _constructorsCache;

  @Override
  public MetaConstructor[] getConstructors() {
    if (_constructorsCache != null) return _constructorsCache;

    if (constructors.isEmpty()) {
      // add an empty no-arg constructor
      BuildMetaConstructor buildMetaConstructor =
              new BuildMetaConstructor(this, new BlockStatement(), DefParameters.none());

      buildMetaConstructor.setScope(Scope.Public);
      return _constructorsCache = new MetaConstructor[]{buildMetaConstructor};
    }
    else {
      return _constructorsCache = constructors.toArray(new MetaConstructor[constructors.size()]);
    }
  }

  @Override
  public MetaConstructor[] getDeclaredConstructors() {
    return getConstructors();
  }

  @Override
  public MetaClass[] getInterfaces() {
    return interfaces.toArray(new MetaClass[interfaces.size()]);
  }

  @Override
  public MetaClass getSuperClass() {
    return superClass;
  }

  @Override
  public MetaClass getComponentType() {
    if (isArray) {
      BuildMetaClass compType = shallowCopy();
      if (dimensions > 1) {
        compType.setDimensions(dimensions - 1);
      }
      else {
        compType.setArray(false);
        compType.setDimensions(0);
      }

      return compType;
    }
    return null;
  }

  @Override
  public boolean isPrimitive() {
    return false;
  }

  @Override
  public boolean isVoid() {
    return false;
  }

  @Override
  public boolean isInterface() {
    return isInterface;
  }

  @Override
  public boolean isAbstract() {
    return isAbstract;
  }

  @Override
  public boolean isArray() {
    return false;
  }

  @Override
  public boolean isEnum() {
    return false;
  }

  @Override
  public boolean isAnnotation() {
    return false;
  }

  @Override
  public boolean isPublic() {
    return scope == Scope.Public;
  }

  @Override
  public boolean isPrivate() {
    return scope == Scope.Private;
  }

  @Override
  public boolean isProtected() {
    return scope == Scope.Protected;
  }

  @Override
  public boolean isFinal() {
    return isFinal;
  }

  @Override
  public boolean isStatic() {
    return isStatic;
  }

  @Override
  public Annotation[] getAnnotations() {
    return annotations.toArray(new Annotation[annotations.size()]);
  }

  @Override
  public MetaTypeVariable[] getTypeParameters() {
    return typeVariables.toArray(new MetaTypeVariable[typeVariables.size()]);
  }
//
//  public void setClassName(String className) {
//    this.className = className;
//  }

  public void setSuperClass(MetaClass superClass) {
    this.superClass = superClass;
  }

  public void setInterfaces(List<MetaClass> interfaces) {
    this.interfaces = interfaces;
  }

  public void setInterface(boolean anInterface) {
    isInterface = anInterface;
  }

  public void setAbstract(boolean anAbstract) {
    isAbstract = anAbstract;
  }

  public void setArray(boolean array) {
    isArray = array;
  }

  public void setDimensions(int dimensions) {
    this.dimensions = dimensions;
  }

  public int getDimensions() {
    return dimensions;
  }

  public void setFinal(boolean aFinal) {
    isFinal = aFinal;
  }

  public void setStatic(boolean aStatic) {
    isStatic = aStatic;
  }

  public void setInner(boolean aInner) {
    isInner = aInner;
  }

  public void setScope(Scope scope) {
    this.scope = scope;
  }

  public void setContext(Context context) {
    this.context = context;
  }

  public Context getContext() {
    return context;
  }
 
  public void addAnnotation(Annotation annotation) {
    annotations.add(annotation);
  }
 
  public void addInnerClass(InnerClass innerClass) {
    innerClasses.add(innerClass);
  }

  public void addInterface(MetaClass interfaceClass) {
    interfaces.add(interfaceClass);
  }

  public void addConstructor(BuildMetaConstructor constructor) {
    _constructorsCache = null;
    constructors.add(constructor);
  }

  public void addMethod(BuildMetaMethod method) {
    _methodsCache = null;
    methods.add(method);
  }

  public void addField(BuildMetaField field) {
    _fieldsCache = null;
    fields.add(field);
  }

  public void addTypeVariable(MetaTypeVariable typeVariable) {
    typeVariables.add(typeVariable);
  }

  public void setParameterizedType(MetaParameterizedType parameterizedType) {
    this.parameterizedType = parameterizedType;
  }

  public boolean isReifiedForm() {
    return reifiedFormOf != null;
  }

  public MetaClass getReifiedFormOf() {
    return reifiedFormOf;
  }

  public void setReifiedFormOf(MetaClass reifiedFormOf) {
    this.reifiedFormOf = reifiedFormOf;
  }

  @Override
  public MetaMethod getBestMatchingMethod(String name, Class... parameters) {
    return isReifiedForm() ? findReifiedVersion(reifiedFormOf.getBestMatchingMethod(name, parameters))
            : super.getBestMatchingMethod(name, parameters);
  }

  @Override
  public MetaMethod getBestMatchingMethod(String name, MetaClass... parameters) {
    return isReifiedForm() ? findReifiedVersion(reifiedFormOf.getBestMatchingMethod(name, parameters))
            : super.getBestMatchingMethod(name, parameters);
  }

  @Override
  public MetaMethod getBestMatchingStaticMethod(String name, Class... parameters) {
    return isReifiedForm() ? findReifiedVersion(reifiedFormOf.getBestMatchingStaticMethod(name, parameters))
            : super.getBestMatchingStaticMethod(name, parameters);
  }

  @Override
  public MetaMethod getBestMatchingStaticMethod(String name, MetaClass... parameters) {
    return isReifiedForm() ? findReifiedVersion(reifiedFormOf.getBestMatchingStaticMethod(name, parameters))
            : super.getBestMatchingStaticMethod(name, parameters);
  }

  @Override
  public MetaConstructor getBestMatchingConstructor(Class... parameters) {
    return isReifiedForm() ? findReifiedVersion(reifiedFormOf.getBestMatchingConstructor(parameters))
            : super.getBestMatchingConstructor(parameters);
  }

  @Override
  public MetaConstructor getBestMatchingConstructor(MetaClass... parameters) {
    return isReifiedForm() ? findReifiedVersion(reifiedFormOf.getBestMatchingConstructor(parameters))
            : super.getBestMatchingConstructor(parameters);
  }

  private MetaMethod findReifiedVersion(MetaMethod formOf) {
    for (BuildMetaMethod method : methods) {
      if (method.getReifiedFormOf().equals(formOf)) {
        return method;
      }
    }
    return null;
  }

  private MetaConstructor findReifiedVersion(MetaConstructor formOf) {
    for (BuildMetaConstructor method : constructors) {
      if (method.getReifiedFormOf().equals(formOf)) {
        return method;
      }
    }
    return null;
  }


  @Override
  public MetaClass asArrayOf(int dimensions) {
    BuildMetaClass copy = shallowCopy();
    copy.setArray(true);
    copy.setDimensions(dimensions);
    return copy;
  }

  String generatedCache;

  @Override
  public String toJavaString() {
    if (generatedCache != null) return generatedCache;

    StringBuilder buf = new StringBuilder(512);

    context.addVariable(Variable.create("this", this));

    for (Annotation a : annotations) {
      buf.append(new AnnotationLiteral(a).getCanonicalString(context));
      buf.append(" ");
    }
   
    if (!annotations.isEmpty()) buf.append("\n");
   
    buf.append("\n");

    buf.append(scope.getCanonicalName());

    if (isAbstract) {
      buf.append(" abstract");
    }

    if (isStatic) {
      buf.append(" static");
    }
   
    if (isInterface()) {
      buf.append(" interface ").append(getName());
    }
    else {
      buf.append(" class ").append(getName());
    }

    if (getSuperClass() != null) {
      buf.append(" extends ").append(LoadClassReference.getClassReference(getSuperClass(), context));
    }

    if (interfaces.size() != 0) {
      buf.append(" implements ");

      Iterator<MetaClass> iter = interfaces.iterator();
      while (iter.hasNext()) {
        buf.append(LoadClassReference.getClassReference(iter.next(), context));
        if (iter.hasNext())
          buf.append(", ");
      }
    }

    superClass = (superClass != null) ? superClass : MetaClassFactory.get(Object.class);
    context.addVariable(Variable.create("super", superClass));

    buf.append(" {\n");

    buf.append(membersToString());

    StringBuilder headerBuffer = new StringBuilder(128);

    if (!getPackageName().isEmpty() && !isInner)
      headerBuffer.append("package ").append(getPackageName()).append(";\n");

    if (!context.getRequiredImports().isEmpty())
      headerBuffer.append("\n");

    if (!isInner) {
      for (String cls : context.getRequiredImports()) {
        if (getFullyQualifiedName().equals(cls)) {
          continue;
        }
        else {
          String pkg = getPackageName();
          if (cls.startsWith(pkg)) {
            if (cls.substring(pkg.length() + 1).indexOf('.') == -1) {
              continue;
            }
          }
        }

        headerBuffer.append("import ").append(cls).append(";\n");
      }
    }

    return generatedCache = PrettyPrinter.prettyPrintJava(headerBuffer.toString() + buf.append("}\n").toString());

  }

  public String membersToString() {
    StringBuilder buf = new StringBuilder(512);
    Iterator<? extends Builder> iter = fields.iterator();
    while (iter.hasNext()) {
      buf.append(iter.next().toJavaString());
      if (iter.hasNext())
        buf.append("\n");
    }
   
    if (!fields.isEmpty())
      buf.append("\n");

    Iterator<InnerClass> innerClassIterator = innerClasses.iterator();
    while (innerClassIterator.hasNext()) {
      buf.append(innerClassIterator.next().generate(context));
      if (innerClassIterator.hasNext()) buf.append("\n");
    }
   
    if (!innerClasses.isEmpty())
      buf.append("\n");
   
    iter = constructors.iterator();
    while (iter.hasNext()) {
      buf.append(iter.next().toJavaString());
      if (iter.hasNext())
        buf.append("\n");
    }

    if (!constructors.isEmpty())
      buf.append("\n");

    iter = methods.iterator();
    while (iter.hasNext()) {
      buf.append(iter.next().toJavaString());
      if (iter.hasNext())
        buf.append("\n");
    }
    return buf.toString();
  }


  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof BuildMetaClass)) return false;
    if (!super.equals(o)) return false;

    BuildMetaClass that = (BuildMetaClass) o;

    if (dimensions != that.dimensions) return false;
    if (isAbstract != that.isAbstract) return false;
    if (isArray != that.isArray) return false;
    if (isFinal != that.isFinal) return false;
    if (isInner != that.isInner) return false;
    if (isInterface != that.isInterface) return false;
    if (isStatic != that.isStatic) return false;
    if (!Arrays.equals(_constructorsCache, that._constructorsCache)) return false;
    if (!Arrays.equals(_fieldsCache, that._fieldsCache)) return false;
    if (!Arrays.equals(_methodsCache, that._methodsCache)) return false;
    if (_nameCache != null ? !_nameCache.equals(that._nameCache) : that._nameCache != null) return false;
    if (className != null ? !className.equals(that.className) : that.className != null) return false;
    if (constructors != null ? !constructors.equals(that.constructors) : that.constructors != null) return false;
    if (context != null ? !context.equals(that.context) : that.context != null) return false;
    if (fields != null ? !fields.equals(that.fields) : that.fields != null) return false;
    if (generatedCache != null ? !generatedCache.equals(that.generatedCache) : that.generatedCache != null)
      return false;
    if (interfaces != null ? !interfaces.equals(that.interfaces) : that.interfaces != null) return false;
    if (methods != null ? !methods.equals(that.methods) : that.methods != null) return false;
    if (reifiedFormOf != null ? !reifiedFormOf.equals(that.reifiedFormOf) : that.reifiedFormOf != null) return false;
    if (scope != that.scope) return false;
    if (superClass != null ? !superClass.equals(that.superClass) : that.superClass != null) return false;
    if (typeVariables != null ? !typeVariables.equals(that.typeVariables) : that.typeVariables != null) return false;

    return true;
  }

  @Override
  public int hashCode() {
    int result = super.hashCode();
    result = 31 * result + (context != null ? context.hashCode() : 0);
    result = 31 * result + (className != null ? className.hashCode() : 0);
    result = 31 * result + (superClass != null ? superClass.hashCode() : 0);
    result = 31 * result + (interfaces != null ? interfaces.hashCode() : 0);
    result = 31 * result + (scope != null ? scope.hashCode() : 0);
    result = 31 * result + (isArray ? 1 : 0);
    result = 31 * result + dimensions;
    result = 31 * result + (isInterface ? 1 : 0);
    result = 31 * result + (isAbstract ? 1 : 0);
    result = 31 * result + (isFinal ? 1 : 0);
    result = 31 * result + (isStatic ? 1 : 0);
    result = 31 * result + (isInner ? 1 : 0);
    result = 31 * result + (methods != null ? methods.hashCode() : 0);
    result = 31 * result + (fields != null ? fields.hashCode() : 0);
    result = 31 * result + (constructors != null ? constructors.hashCode() : 0);
    result = 31 * result + (typeVariables != null ? typeVariables.hashCode() : 0);
    result = 31 * result + (reifiedFormOf != null ? reifiedFormOf.hashCode() : 0);
    result = 31 * result + (_nameCache != null ? _nameCache.hashCode() : 0);
    result = 31 * result + (_methodsCache != null ? Arrays.hashCode(_methodsCache) : 0);
    result = 31 * result + (_fieldsCache != null ? Arrays.hashCode(_fieldsCache) : 0);
    result = 31 * result + (_constructorsCache != null ? Arrays.hashCode(_constructorsCache) : 0);
    result = 31 * result + (generatedCache != null ? generatedCache.hashCode() : 0);
    return result;
  }
}
TOP

Related Classes of org.jboss.errai.codegen.framework.meta.impl.build.BuildMetaClass

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.