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

Source Code of org.jboss.errai.ioc.rebind.ioc.TypeInjector

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


import org.jboss.errai.codegen.framework.Parameter;
import org.jboss.errai.codegen.framework.Statement;
import org.jboss.errai.codegen.framework.builder.AnonymousClassStructureBuilder;
import org.jboss.errai.codegen.framework.builder.BlockBuilder;
import org.jboss.errai.codegen.framework.builder.impl.ObjectBuilder;
import org.jboss.errai.codegen.framework.meta.MetaClass;
import org.jboss.errai.codegen.framework.meta.MetaClassFactory;
import org.jboss.errai.codegen.framework.util.Refs;
import org.jboss.errai.ioc.client.container.BeanRef;
import org.jboss.errai.ioc.client.container.CreationalCallback;
import org.jboss.errai.ioc.client.container.CreationalContext;
import org.jboss.errai.ioc.rebind.IOCProcessingContext;

import javax.enterprise.inject.New;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import static org.jboss.errai.codegen.framework.builder.impl.ObjectBuilder.newInstanceOf;
import static org.jboss.errai.codegen.framework.meta.MetaClassFactory.parameterizedAs;
import static org.jboss.errai.codegen.framework.meta.MetaClassFactory.typeParametersOf;
import static org.jboss.errai.codegen.framework.util.Stmt.declareVariable;
import static org.jboss.errai.codegen.framework.util.Stmt.load;
import static org.jboss.errai.codegen.framework.util.Stmt.loadVariable;

public class TypeInjector extends Injector {
  protected final MetaClass type;
  protected boolean injected;
  protected boolean singleton;
  protected boolean psuedo;
  protected String varName;
  protected String creationalCallbackVarName;

  public TypeInjector(MetaClass type, IOCProcessingContext context) {
    this(type, context, new Annotation[0]);
  }

  public TypeInjector(MetaClass type, IOCProcessingContext context, Annotation[] additionalQualifiers) {
    this.type = type;
    this.singleton = context.isSingletonScope(type.getAnnotations());
    this.varName = InjectUtil.getNewVarName();

    try {
      Set<Annotation> qualifiers = new HashSet<Annotation>();
      qualifiers.addAll(InjectUtil.extractQualifiersFromType(type));
      qualifiers.addAll(Arrays.asList(additionalQualifiers));

      if (!qualifiers.isEmpty()) {

        qualifyingMetadata = context.getQualifyingMetadataFactory().createFrom(qualifiers.toArray(new
                Annotation[qualifiers.size()]));

      }
      else {
        qualifyingMetadata = context.getQualifyingMetadataFactory().createDefaultMetadata();
      }
    }
    catch (Throwable e) {
      // ignore
    }
  }

  @Override
  public Statement getType(InjectionContext injectContext, InjectableInstance injectableInstance) {
    Statement val = _getType(injectContext, injectableInstance);
    registerWithBeanManager(injectContext, val);
    return val;
  }

  private Statement _getType(InjectionContext injectContext, InjectableInstance injectableInstance) {
    if (isInjected()) {
      if (isSingleton()) {
        if (!hasNewQualifier(injectableInstance)) {
          return Refs.get(varName);
        }
        else if (creationalCallbackVarName != null) {
          return loadVariable(creationalCallbackVarName).invoke("getInstance", Refs.get("context"));
        }
      }
      else if (creationalCallbackVarName != null) {
        /**
         * Ensure each permutation of qualifier meta data results in a unique wiring scenario
         */
        final Set<Annotation> fromCompare = new HashSet<Annotation>(Arrays.asList(qualifyingMetadata.getQualifiers()));
        final Set<Annotation> toCompare;
        if (injectableInstance == null
                || injectableInstance.getQualifiers() == null
                || injectableInstance.getQualifiers().length == 0) {
          toCompare = new HashSet<Annotation>(Arrays.asList(injectContext.getProcessingContext()
                  .getQualifyingMetadataFactory().createDefaultMetadata().getQualifiers()));
        }
        else {
          toCompare = new HashSet<Annotation>(Arrays.asList(injectableInstance.getQualifiers()));
        }

        if (fromCompare.equals(toCompare)) {
          return loadVariable(creationalCallbackVarName).invoke("getInstance", Refs.get("context"));
        }
      }
    }

    IOCProcessingContext ctx = injectContext.getProcessingContext();

    MetaClass creationCallbackRef = parameterizedAs(CreationalCallback.class, typeParametersOf(type));

    final BlockBuilder<AnonymousClassStructureBuilder> callbackBuilder = newInstanceOf(creationCallbackRef).extend()
            .publicOverridesMethod("getInstance", Parameter.of(CreationalContext.class, "context", true));

    callbackBuilder.append(declareVariable(Class.class).named("beanType").initializeWith(load(type)));
    callbackBuilder.append(declareVariable(Annotation[].class).named("qualifiers")
            .initializeWith(load(qualifyingMetadata.getQualifiers())));

    ctx.pushBlockBuilder(callbackBuilder);

    InjectUtil.getConstructionStrategy(this, injectContext).generateConstructor(new ConstructionStatusCallback() {
      @Override
      public void callback(boolean constructed) {
        callbackBuilder.append(declareVariable(BeanRef.class).named("beanRef")
                .initializeWith(loadVariable("context").invoke("getBeanReference", Refs.get("beanType"),
                        Refs.get("qualifiers"))));

        callbackBuilder.append(loadVariable("context").invoke("addBean", Refs.get("beanRef"), Refs.get(varName)));
        injected = true;
      }
    });

    ctx.popBlockBuilder();

    creationalCallbackVarName = InjectUtil.getNewVarName();

    ctx.globalAppend(declareVariable(creationCallbackRef).asFinal().named(creationalCallbackVarName)
            .initializeWith(callbackBuilder.finish().finish()));

    Statement retVal;

    if (isSingleton()) {
      ctx.globalAppend(declareVariable(type).asFinal().named(varName)
              .initializeWith(loadVariable(creationalCallbackVarName).invoke("getInstance",
                      Refs.get("context"))));

      retVal = Refs.get(varName);
    }
    else {
      retVal = loadVariable(creationalCallbackVarName).invoke("getInstance", Refs.get("context"));
    }

    if (injectContext.isProxiedInjectorAvailable(type, qualifyingMetadata)) {
      ProxyInjector proxyInjector = (ProxyInjector) injectContext.getProxiedInjector(type, qualifyingMetadata);
      if (!proxyInjector.isProxied()) {
        proxyInjector.setProxied(true);
        proxyInjector.setProxyStatement(retVal);
      }
    }

    callbackBuilder.append(loadVariable(varName).returnValue());

    return retVal;
  }

  private static boolean hasNewQualifier(InjectableInstance instance) {
    if (instance != null) {
      for (Annotation annotation : instance.getQualifiers()) {
        if (annotation.annotationType().equals(New.class)) return true;
      }
    }
    return false;
  }

  @Override
  public Statement instantiateOnly(InjectionContext injectContext, InjectableInstance injectableInstance) {
    return getType(injectContext, injectableInstance);
  }

  @Override
  public boolean isInjected() {
    return injected;
  }

  @Override
  public boolean isSingleton() {
    return singleton;
  }

  public void setSingleton(boolean singleton) {
    this.singleton = singleton;
  }


  public boolean isPseudo() {
    return psuedo;
  }

  public void setPsuedo(boolean psuedo) {
    this.psuedo = psuedo;
  }

  @Override
  public String getVarName() {
    return varName;
  }

  @Override
  public MetaClass getInjectedType() {
    return type;
  }

  public String getCreationalCallbackVarName() {
    return creationalCallbackVarName;
  }

  private void registerWithBeanManager(InjectionContext context, Statement valueRef) {
    if (useBeanManager) {
      if (InjectUtil.checkIfTypeNeedsAddingToBeanStore(context, this)) {
        Statement initCallbackRef;
        if (getPostInitCallbackVar() == null) {
          initCallbackRef = load(null);
        }
        else {
          initCallbackRef = loadVariable(getPostInitCallbackVar());
        }

        if (isSingleton()) {
          context.getProcessingContext().appendToEnd(
                  loadVariable(context.getProcessingContext().getContextVariableReference())
                          .invoke("addSingletonBean", type, valueRef,
                                  qualifyingMetadata.render(), initCallbackRef)
          );
        }
        else {
          context.getProcessingContext().appendToEnd(
                  loadVariable(context.getProcessingContext().getContextVariableReference())
                          .invoke("addDependentBean", type, Refs.get(creationalCallbackVarName),
                                  qualifyingMetadata.render(), initCallbackRef));
        }
      }
    }
  }
}
TOP

Related Classes of org.jboss.errai.ioc.rebind.ioc.TypeInjector

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.