/* * Copyright 2010 Gal Dolber. * * 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 com.guit.rebind.place; import com.google.gwt.core.ext.GeneratorContext; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; import com.google.inject.internal.BindingImpl; import com.google.inject.internal.Scoping; import com.google.inject.spi.Element; import com.guit.client.binder.contributor.RunAsync; import com.guit.client.place.Place; import com.guit.rebind.gin.GinContext; import com.guit.rebind.gin.GinContributor; import com.guit.rebind.gin.GinOracle; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; public class PlaceGinContributor implements GinContributor, PlaceProcessor { // Shared instance of places. For the generation protected static ArrayList<Class<?>> places = new ArrayList<Class<?>>(); private static final Class<?> placeClassType = Place.class; private static final Class<Singleton> singletonClassType = Singleton.class; private GinContext ginContext; @Override public void collaborate(GinContext ginContext, TreeLogger logger, GeneratorContext context) throws UnableToCompleteException { this.ginContext = ginContext; places.clear(); List<Element> elements = GinOracle.getElementsForModules(ginContext.getGModules()); processPlaces(logger, elements, this); } @Override public void process(Class<?> placeType) { places.add(placeType); String canonicalName = placeType.getCanonicalName(); if (placeType.isAnnotationPresent(RunAsync.class)) { ginContext.addAsyncProvidedType(canonicalName); } else { ginContext.addProvidedType(canonicalName); } } private void processPlaces(TreeLogger logger, List<Element> elements, PlaceProcessor placeProcessor) throws UnableToCompleteException { for (Element e : elements) { if (e instanceof BindingImpl<?>) { BindingImpl<?> binding = (BindingImpl<?>) e; Type type = ((TypeLiteral<?>) binding.getKey().getTypeLiteral()).getType(); if (type instanceof Class<?> && placeClassType.isAssignableFrom((Class<?>) type)) { Class<?> placeType = (Class<?>) type; // TODO What about @Singleton annotation? Scoping scoping = binding.getScoping(); if (scoping != null) { Class<? extends Annotation> scopeAnnotation = scoping.getScopeAnnotation(); if (scopeAnnotation != null && scopeAnnotation.equals(singletonClassType)) { placeProcessor.process(placeType); continue; } } logger.log(com.google.gwt.core.ext.TreeLogger.Type.ERROR, "All places should have Singleton scope(declared in module, not as Annotation). Found: " + placeType.getCanonicalName() + " Scope: " + binding.getScoping()); throw new UnableToCompleteException(); } } } } }