Package org.stjs.generator.name

Source Code of org.stjs.generator.name.DefaultJavaScriptNameProvider

package org.stjs.generator.name;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.lang.model.element.Element;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.WildcardType;

import org.stjs.generator.GenerationContext;
import org.stjs.generator.GeneratorConfiguration;
import org.stjs.generator.javac.ElementUtils;
import org.stjs.generator.javac.InternalUtils;
import org.stjs.generator.utils.ClassUtils;
import org.stjs.generator.utils.JavaNodes;

import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.util.TreePath;

/**
* This class implements the naming strategy transforming Java element names in JavaScript names.
* @author acraciun
*/
public class DefaultJavaScriptNameProvider implements JavaScriptNameProvider {
  private static final String JAVA_LANG_PACKAGE = "java.lang.";
  private static final int JAVA_LANG_LENGTH = JAVA_LANG_PACKAGE.length();

  private final Set<String> resolvedRootTypes = new HashSet<String>();
  private final Map<TypeMirror, String> resolvedTypes = new HashMap<TypeMirror, String>();

  @Override
  public String getTypeName(GenerationContext<?> context, TypeMirror type) {
    String fullName = resolvedTypes.get(type);
    if (fullName != null) {
      return fullName;
    }

    if (type instanceof DeclaredType) {
      DeclaredType declaredType = (DeclaredType) type;
      String name = InternalUtils.getSimpleName(declaredType.asElement());
      Element rootTypeElement = declaredType.asElement();
      for (DeclaredType enclosingType = JavaNodes.getEnclosingType(declaredType); enclosingType != null; enclosingType =
          JavaNodes.getEnclosingType(enclosingType)) {
        rootTypeElement = enclosingType.asElement();
        name = InternalUtils.getSimpleName(rootTypeElement) + "." + name;
      }

      checkAllowedType(rootTypeElement, context);
      addResolvedType(rootTypeElement);

      String namespace = JavaNodes.getNamespace(rootTypeElement);
      fullName = (namespace == null ? "" : namespace + ".") + name;
      resolvedTypes.put(type, fullName);
      return fullName;
    }
    if (type instanceof WildcardType) {
      //? extends Type1 super Type2
      //XXX what to return here !?
      return "Object";
    }
    return type.toString();
  }

  private void typeNotAllowedException(GenerationContext<?> context, String name) {
    context.addError(context.getCurrentPath().getLeaf(), "The usage of the class " + name
        + " is not allowed. If it's one of your own bridge types, "
        + "please add the annotation @STJSBridge to the class or to its package.");
  }

  private boolean isJavaLangClassAllowed(GenerationContext<?> context, String name) {
    GeneratorConfiguration configuration = context.getConfiguration();
    if (name.startsWith(JAVA_LANG_PACKAGE) && configuration.getAllowedJavaLangClasses().contains(name.substring(JAVA_LANG_LENGTH))) {
      return true;
    }

    return false;
  }

  private boolean isPackageAllowed(GenerationContext<?> context, String name) {
    if (name.startsWith(JAVA_LANG_PACKAGE)) {
      return false;
    }
    GeneratorConfiguration configuration = context.getConfiguration();
    for (String packageName : configuration.getAllowedPackages()) {
      if (name.startsWith(packageName)) {
        return true;
      }
    }
    return false;
  }

  private boolean isBridge(GenerationContext<?> context, String name) {
    if (name.startsWith(JAVA_LANG_PACKAGE)) {
      return false;
    }

    return ClassUtils.isBridge(context.getBuiltProjectClassLoader(), ClassUtils.getClazz(context.getBuiltProjectClassLoader(), name));
  }

  private void checkAllowedType(Element rootTypeElement, GenerationContext<?> context) {
    String name = ElementUtils.getQualifiedClassName(rootTypeElement).toString();
    if (name.isEmpty()) {
      return;
    }
    if (isJavaLangClassAllowed(context, name)) {
      return;
    }

    if (isImportedStjsClass(context, name)) {
      return;
    }

    if (isPackageAllowed(context, name)) {
      return;
    }

    // ClassUtils.isBridge accepts all java.lang classes, that are actually not allowed
    if (isBridge(context, name)) {
      return;
    }

    typeNotAllowedException(context, name);
  }

  private boolean isImportedStjsClass(GenerationContext<?> context, String className) {
    String stjsPropertiesName = ClassUtils.getPropertiesFileName(className);
    return context.getBuiltProjectClassLoader().getResource(stjsPropertiesName) != null;
  }

  private void addResolvedType(Element rootTypeElement) {
    String name = ElementUtils.getQualifiedClassName(rootTypeElement).toString();
    if (!name.startsWith("java.lang.")) {
      resolvedRootTypes.add(name);
    }
  }

  @Override
  public String getVariableName(GenerationContext<?> context, IdentifierTree treeNode, TreePath path) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public String getMethodName(GenerationContext<?> context, MethodTree tree, TreePath path) {
    return tree.getName().toString();
  }

  @Override
  public String getMethodName(GenerationContext<?> context, MethodInvocationTree tree, TreePath path) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public String getTypeName(GenerationContext<?> context, Element type) {
    return getTypeName(context, type.asType());
  }

  @Override
  public Collection<String> getResolvedTypes() {
    return resolvedRootTypes;
  }

}
TOP

Related Classes of org.stjs.generator.name.DefaultJavaScriptNameProvider

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.