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

Source Code of org.jboss.errai.ioc.rebind.ioc.codegen.Context

/*
* 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;

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

import javax.enterprise.util.TypeLiteral;

import org.jboss.errai.ioc.rebind.ioc.codegen.control.branch.Label;
import org.jboss.errai.ioc.rebind.ioc.codegen.control.branch.LabelReference;
import org.jboss.errai.ioc.rebind.ioc.codegen.exception.OutOfScopeException;
import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaClass;

/**
* This class represents a context in which {@link Statement}s are generated.
* It references its parent context and holds a map of variables to represent
* a {@link Statement}'s scope. It further supports importing classes and packages
* to avoid the use of fully qualified class names.
*
* @author Christian Sadilek <csadilek@redhat.com>
*/
public class Context {
  private Context parent = null;

  private Map<String, Variable> variables;
  private Map<String, Label> labels;

  private Set<String> importedPackages;
  private Set<String> importedClasses;
  private boolean autoImports = false;

  private Context() {
    importedPackages = new HashSet<String>();
    importedPackages.add("java.lang");
  }

  private Context(Context parent) {
    this();
    this.parent = parent;
    this.autoImports = parent.autoImports;
    this.importedPackages = parent.importedPackages;
    this.importedClasses = parent.importedClasses;
  }

  public static Context create() {
    return new Context();
  }

  public static Context create(Context parent) {
    return new Context(parent);
  }

  public Context addVariable(String name, Class<?> type) {
    return addVariable(Variable.create(name, type));
  }

  public Context addVariable(String name, TypeLiteral<?> type) {
    return addVariable(Variable.create(name, type));
  }

  public Context addVariable(String name, Object initialization) {
    Variable v = Variable.create(name, initialization);
    return addVariable(v);
  }

  public Context addVariable(String name, Class<?> type, Object initialization) {
    Variable v = Variable.create(name, type, initialization);
    return addVariable(v);
  }

  public Context addVariable(String name, TypeLiteral<?> type, Object initialization) {
    Variable v = Variable.create(name, type, initialization);
    return addVariable(v);
  }

  public Context addVariable(Variable variable) {
    if (variables == null)
      variables = new HashMap<String, Variable>();

    variables.put(variable.getName(), variable);
    return this;
  }

  public Context addLabel(Label label) {
    if (labels == null)
      labels = new HashMap<String, Label>();

    labels.put(label.getName(), label);
    return this;
  }

  public Context addPackageImport(String packageName) {
    if (packageName == null)
      return this;

    String pkgName = packageName.trim();
    if (pkgName.length() == 0)
      return this;

    for (char c : pkgName.toCharArray()) {
      if (c != '.' && !Character.isJavaIdentifierPart(c)) {
        throw new RuntimeException("not a valid package name. " +
                "(use format: foo.bar.pkg -- do not include '.*' at the end)");
      }
    }
    importedPackages.add(pkgName);
    return this;
  }

  public boolean hasPackageImport(String packageName) {
    return importedPackages != null && importedPackages.contains(packageName);
  }

  private void initImportedClass() {
    if (importedClasses == null) {
      Context c = this;
      while (c.parent != null) {
        c = c.parent;
      }

      if (c.importedClasses == null) {
        c.importedClasses = importedClasses = new LinkedHashSet<String>();
      }
      else {
        importedClasses = c.importedClasses;
      }
    }
  }

  public Context addClassImport(MetaClass clazz) {
    initImportedClass();
    importedClasses.add(clazz.isArray() ? clazz.getComponentType().getFullyQualifiedName() : clazz
            .getFullyQualifiedName());
    return this;
  }

  public boolean hasClassImport(MetaClass clazz) {
    return importedClasses != null && importedClasses.contains(clazz.getFullyQualifiedName());
  }

  public Context autoImport() {
    this.autoImports = true;
    return this;
  }

  public VariableReference getVariable(String name) {
    return getVariable(name, false);
  }

  public VariableReference getClassMember(String name) {
    return getVariable(name, true);
  }

  private VariableReference getVariable(String name, boolean mustBeClassMember) {
    Variable found = null;
    Context ctx = this;
    do {
      if (ctx.variables != null) {
        Variable var = ctx.variables.get(name);
        found = (mustBeClassMember && var != null && !var.isClassMember()) ? null : var;
      }
    }
    while (found == null && (ctx = ctx.parent) != null);

    if (found == null)
      throw new OutOfScopeException((mustBeClassMember) ? "this." + name : name);

    return found.getReference();
  }

  public LabelReference getLabel(String name) {
    Label found = null;
    Context ctx = this;
    do {
      if (ctx.labels != null) {
        found = ctx.labels.get(name);
      }
    }
    while (found == null && (ctx = ctx.parent) != null);

    if (found == null)
      throw new OutOfScopeException("Label not found: " + name);

    return found.getReference();
  }

  public boolean isScoped(Variable variable) {
    Context ctx = this;
    do {
      if (ctx.variables != null && ctx.variables.containsValue(variable))
        return true;
    }
    while ((ctx = ctx.parent) != null);
    return false;
  }

  public Collection<Variable> getDeclaredVariables() {
    if (variables == null)
      return Collections.<Variable>emptyList();

    return variables.values();
  }

  public Map<String, Variable> getVariables() {
    if (variables == null)
      return Collections.<String, Variable>emptyMap();

    return Collections.<String, Variable>unmodifiableMap(variables);
  }

  public Set<String> getImportedPackages() {
    return importedPackages;
  }

  public Set<String> getImportedClasses() {
    if (importedClasses == null)
      return Collections.emptySet();

    return importedClasses;
  }

  public boolean isAutoImports() {
    return autoImports;
  }
}
TOP

Related Classes of org.jboss.errai.ioc.rebind.ioc.codegen.Context

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.