All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xapi.dev.util.GwtInjectionMap Maven / Gradle / Ivy

Go to download

This module exists solely to package all other gwt modules into a single uber jar. This makes deploying to non-mavenized targets much easier. Of course, you would be wise to inherit your dependencies individually; the uber jar is intended for projects like collide, which have complex configuration, and adding many jars would be a pain.

The newest version!
/*
 * Copyright 2012, We The Internet Ltd.
 *
 * All rights reserved.
 *
 * Distributed under a modified BSD License as follow:
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution, unless otherwise
 * agreed to in a written document signed by a director of We The Internet Ltd.
 *
 * Neither the name of We The Internet nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
package xapi.dev.util;

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

import xapi.annotation.inject.InstanceDefault;
import xapi.annotation.inject.InstanceOverride;
import xapi.annotation.inject.SingletonDefault;
import xapi.annotation.inject.SingletonOverride;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;

/**
 * A handy state-blob of all available types from the TypeOracle or runtime
 * reflection.  It is an expensive operation to iterate all types per generator,
 * so we store the state of active permutation targets here
 * and wrap the instance in a lazy singleton.
 *
 * @author James X. Nelson ([email protected], @james)
 */
public class GwtInjectionMap {

  final Map,JClassType> defaultSingletons = new HashMap,JClassType>();
  final Map,JClassType> defaultInstances = new HashMap,JClassType>();
  final Map,JClassType> gwtSingletons = new HashMap,JClassType>();
  final Map,JClassType> gwtInstances = new HashMap,JClassType>();
  final Map injectionArtifacts = new HashMap();
  private final PlatformSet platforms;

  public GwtInjectionMap(TreeLogger logger, GeneratorContext context) {
    this.platforms = CurrentGwtPlatform.getPlatforms(context);
    init(logger, context);
  }

  // visible for testing
  protected void init(TreeLogger logger, GeneratorContext context) {
    TypeOracle oracle = context.getTypeOracle();


    JClassType[] types = oracle.getTypes();
    for (JClassType type : types) {
      SingletonDefault defaultSingleton = type.getAnnotation(SingletonDefault.class);
      if (defaultSingleton != null && platforms.isAllowedType(type)) {
        JClassType old = defaultSingletons.get(defaultSingleton.implFor());
        if (old == null) {
          defaultSingletons.put(defaultSingleton.implFor(), type);
        } else {
          JClassType better = platforms.prefer(type, old, SingletonDefault.class);
          if (better == type) {
            defaultSingletons.put(defaultSingleton.implFor(), type);
          }
        }
      }

      InstanceDefault instanceDefault = type.getAnnotation(InstanceDefault.class);
      if (instanceDefault != null && platforms.isAllowedType(type)) {
        JClassType old = defaultInstances.get(instanceDefault.implFor());
        if (old == null) {
          defaultInstances.put(instanceDefault.implFor(), type);
        } else {
          JClassType better = platforms.prefer(type, old, InstanceDefault.class);
          if (better == type) {
            defaultInstances.put(instanceDefault.implFor(), type);
          }
        }
      }

      extractSingletonOverrides(logger, type, context);
      extractInstanceOverrides(logger, type, context);

    }
    if (logger.isLoggable(Type.TRACE)) {
      dumpMaps(logger);
    }
  }

  void dumpMaps(TreeLogger logger) {
    logger.log(Type.TRACE, "***************************");
    logger.log(Type.TRACE, "Dumping gwt injection map:");
    logger.log(Type.TRACE, "***************************");

    TreeLogger
    branch = logger.branch(Type.TRACE, "SingletonDefaults:");
    for (Class key: defaultSingletons.keySet()) {
      branch.log(Type.TRACE, key.getName()+" -> "+defaultSingletons.get(key).getQualifiedSourceName());
    }
    branch = logger.branch(Type.TRACE, "InstanceDefaults:");
    for (Class key: defaultInstances.keySet()) {
      branch.log(Type.TRACE, key.getName()+" -> "+defaultInstances.get(key).getQualifiedSourceName());
    }

    branch = logger.branch(Type.TRACE, "SingletonOverrides:");
    for (Class key: gwtSingletons.keySet()) {
      branch.log(Type.TRACE, key.getName()+" -> "+gwtSingletons.get(key).getQualifiedSourceName());
    }
    branch = logger.branch(Type.TRACE, "InstanceOverrides:");
    for (Class key: gwtInstances.keySet()) {
      branch.log(Type.TRACE, key.getName()+" -> "+gwtInstances.get(key).getQualifiedSourceName());
    }
  }

  protected void extractSingletonOverrides(TreeLogger logger, JClassType type, GeneratorContext context) {
    SingletonOverride singletonOverride = type.getAnnotation(SingletonOverride.class);
    if (singletonOverride == null) return;
    if (platforms.isAllowedType(type)) {
      JClassType override = gwtSingletons.get(singletonOverride.implFor());
      if (override == null) {
        gwtSingletons.put(singletonOverride.implFor(), type);
      } else {
        // TODO: have a config setting for "prefer platform or prefer priority";
        // currently, we prefer platform matches first, then sorted by priority.
        // The flag would make this check only look at priority, and ignore platform.
        JClassType best = platforms.prefer(type, override, SingletonOverride.class);
        logger.log(Type.WARN, best.getSimpleSourceName()+" chosen out of " +
        		type.getSimpleSourceName()+" and "+override.getSimpleSourceName());
        if (best == type) {
          gwtSingletons.put(singletonOverride.implFor(), type);
        }
      }
    }
  }

  protected void extractInstanceOverrides(TreeLogger logger, JClassType type, GeneratorContext context) {
    InstanceOverride instanceOverride = type.getAnnotation(InstanceOverride.class);
    if (instanceOverride != null) {
      if (platforms.isAllowedType(type)) {
        JClassType override = gwtInstances.get(instanceOverride.implFor());
        if (override == null) {
          gwtInstances.put(instanceOverride.implFor(), type);
        } else {
          JClassType best = platforms.prefer(type, override, InstanceOverride.class);
          if (best == type) {
            gwtInstances.put(instanceOverride.implFor(), type);
          }
        }
      }
    }
  }


  public synchronized Set,JClassType>> getGwtSingletons() {
    HashSet> keys = new HashSet>();
    // add anything missing to overrides map.
    keys.addAll(defaultSingletons.keySet());
    keys.removeAll(gwtSingletons.keySet());
    for (Class key : keys) {
      gwtSingletons.put(key, defaultSingletons.get(key));
    }
    return gwtSingletons.entrySet();
  }

  public synchronized Set,JClassType>> getGwtInstances() {
    HashSet> keys = new HashSet>();
    // add anything missing to overrides map.
    keys.addAll(defaultInstances.keySet());
    keys.removeAll(gwtInstances.keySet());
    for (Class key : keys) {
      gwtInstances.put(key, defaultInstances.get(key));
    }
    return gwtInstances.entrySet();
  }

  public InjectionCallbackArtifact getOrCreateArtifact(GeneratorContext ctx, String packageName,
    String className) {
    InjectionCallbackArtifact artifact = new InjectionCallbackArtifact(packageName, className);
    synchronized (injectionArtifacts) {
      if (injectionArtifacts.containsKey(artifact.getCanonicalName())) {
        return injectionArtifacts.get(artifact.getCanonicalName());
      }
      injectionArtifacts.put(artifact.getCanonicalName(), artifact);
    }
    return artifact;
  }

  public Iterable getArtifacts() {
    return injectionArtifacts.values();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy