/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* 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.asakusafw.operator.method;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.processing.Completion;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
import com.asakusafw.operator.AbstractOperatorAnnotationProcessor;
import com.asakusafw.operator.CompileEnvironment;
import com.asakusafw.operator.OperatorDriver;
import com.asakusafw.operator.description.ClassDescription;
import com.asakusafw.operator.model.OperatorClass;
import com.asakusafw.operator.util.Logger;
/**
* Processes Asakusa Operator Annotations.
*/
public class OperatorAnnotationProcessor extends AbstractOperatorAnnotationProcessor {
static final Logger LOG = Logger.get(OperatorAnnotationProcessor.class);
static final Collection<CompileEnvironment.Support> FEATURES = Collections.unmodifiableSet(EnumSet.of(
CompileEnvironment.Support.STRICT_PARAMETER_ORDER,
CompileEnvironment.Support.FORCE_REGENERATE_RESOURCES,
CompileEnvironment.Support.FORCE_GENERATE_IMPLEMENTATION,
CompileEnvironment.Support.FORCE_NORMALIZE_MEMBER_NAME));
@Override
protected CompileEnvironment createCompileEnvironment(ProcessingEnvironment processingEnv) {
return CompileEnvironment.newInstance(
processingEnv,
CompileEnvironment.Support.DATA_MODEL_REPOSITORY,
CompileEnvironment.Support.OPERATOR_DRIVER,
CompileEnvironment.Support.FORCE_GENERATE_IMPLEMENTATION,
CompileEnvironment.Support.FORCE_NORMALIZE_MEMBER_NAME,
CompileEnvironment.Support.STRICT_PARAMETER_ORDER);
}
@Override
protected Collection<CompileEnvironment.Support> getSupportedFeatures() {
return FEATURES;
}
@Override
public Set<String> getSupportedAnnotationTypes() {
if (environment == null) {
return Collections.singleton("*"); //$NON-NLS-1$
}
Set<String> results = new HashSet<>();
for (OperatorDriver driver : environment.getOperatorDrivers()) {
ClassDescription annotationType = driver.getAnnotationTypeName();
results.add(annotationType.getClassName());
}
return results;
}
@Override
public Iterable<? extends Completion> getCompletions(
Element element,
AnnotationMirror annotation,
ExecutableElement member,
String userText) {
if (environment == null) {
return Collections.emptySet();
}
if (element.getKind() != ElementKind.METHOD) {
return Collections.emptyList();
}
OperatorDriver driver = this.environment.findDriver((TypeElement) annotation.getAnnotationType().asElement());
if (driver == null) {
return Collections.emptyList();
} else {
ExecutableElement method = (ExecutableElement) element;
OperatorDriver.Context context = new OperatorDriver.Context(environment, annotation, method);
return driver.getCompletions(context, member, userText);
}
}
@Override
protected void run(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
assert annotations != null;
assert roundEnv != null;
OperatorMethodAnalyzer analyzer = new OperatorMethodAnalyzer(environment);
for (TypeElement annotation : annotations) {
Set<ExecutableElement> methods = ElementFilter.methodsIn(roundEnv.getElementsAnnotatedWith(annotation));
for (ExecutableElement method : methods) {
analyzer.register(annotation, method);
}
}
Collection<OperatorClass> operatorClasses = analyzer.resolve();
LOG.debug("found {} operator classes", operatorClasses.size()); //$NON-NLS-1$
OperatorFactoryEmitter factoryEmitter = new OperatorFactoryEmitter(environment);
OperatorImplementationEmitter implementationEmitter = new OperatorImplementationEmitter(environment);
for (OperatorClass aClass : operatorClasses) {
LOG.debug("emitting support class: {}", aClass.getDeclaration().getQualifiedName()); //$NON-NLS-1$
factoryEmitter.emit(aClass);
if (environment.isForceGenerateImplementation()
|| aClass.getDeclaration().getModifiers().contains(Modifier.ABSTRACT)) {
implementationEmitter.emit(aClass);
}
}
}
}