/*
* Copyright 2016 ArcBees 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 com.gwtplatform.common.processors.bundles;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.inject.Singleton;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import com.google.auto.service.AutoService;
import com.gwtplatform.common.client.NamedProviderBundleCollection;
import com.gwtplatform.common.client.annotations.ProviderBundle;
import com.gwtplatform.common.processors.AbstractGwtpAppProcessor;
import com.gwtplatform.processors.tools.SupportedAnnotationClasses;
import com.gwtplatform.processors.tools.bindings.BindingsProcessors;
import com.gwtplatform.processors.tools.domain.Type;
import static com.google.auto.common.MoreElements.asType;
import static com.gwtplatform.common.processors.module.GwtpAppModuleProcessor.MAIN_MODULE_TYPE;
import static com.gwtplatform.processors.tools.bindings.BindingContext.newBinding;
@AutoService(Processor.class)
@SupportedAnnotationClasses(ProviderBundle.class)
public class NamedProviderBundleCollectionProcessor extends AbstractGwtpAppProcessor {
private BindingsProcessors bindingsProcessors;
private ProviderBundleMetaInfReader metaInfReader;
private ProviderBundleMetaInfWriter metaInfWriter;
private ProviderBundleCollection collection;
@Override
protected void initSafe() {
bindingsProcessors = new BindingsProcessors(logger, utils, outputter);
metaInfReader = new ProviderBundleMetaInfReader(logger);
metaInfWriter = new ProviderBundleMetaInfWriter(logger, outputter);
}
@Override
protected void processSafe(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
try {
super.processSafe(annotations, roundEnv);
if (roundEnv.processingOver()) {
metaInfWriter.close();
}
} catch (Throwable e) {
// We don't do it in a finally block because we want to close the file at the last round only
metaInfWriter.close();
throw e;
}
}
@Override
protected void processAsApp(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
ensureBundleCollectionInitialized();
addBundlesToCollection(extractBundles(roundEnv));
if (roundEnv.processingOver()) {
collection.write();
}
}
private void ensureBundleCollectionInitialized() {
if (collection != null) {
return;
}
collection = new ProviderBundleCollection(logger, outputter);
loadBundlesFromMetaInf();
bindingsProcessors.process(newBinding(
MAIN_MODULE_TYPE,
new Type(NamedProviderBundleCollection.class),
collection.getType(),
Singleton.class));
}
private void loadBundlesFromMetaInf() {
for (Entry<String, List<Type>> bundle : metaInfReader.getBundles().entrySet()) {
for (Type type : bundle.getValue()) {
collection.addBundle(bundle.getKey(), type);
}
}
}
private void addBundlesToCollection(Set<? extends Element> bundles) {
for (Element bundle : bundles) {
String name = bundle.getAnnotation(ProviderBundle.class).value();
Type type = new Type(asType(bundle));
collection.addBundle(name, type);
}
}
@Override
protected void processAsModule(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
writeBundlesToMetaInf(extractBundles(roundEnv));
}
private Set<? extends Element> extractBundles(RoundEnvironment roundEnv) {
Set<? extends Element> bundles = roundEnv.getElementsAnnotatedWith(ProviderBundle.class);
return utils.getSourceFilter().filterElements(bundles);
}
private void writeBundlesToMetaInf(Set<? extends Element> bundles) {
for (Element bundle : bundles) {
String bundleName = bundle.getAnnotation(ProviderBundle.class).value();
String type = asType(bundle).getQualifiedName().toString();
metaInfWriter.addBundle(bundleName, type);
}
}
}