/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* 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.kie.workbench.common.stunner.core.processors;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.MirroredTypeException;
import javax.lang.model.type.MirroredTypesException;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic;
import org.apache.commons.lang3.StringUtils;
import org.kie.workbench.common.stunner.core.definition.adapter.binding.BindableAdapterUtils;
import org.kie.workbench.common.stunner.core.definition.annotation.Definition;
import org.kie.workbench.common.stunner.core.definition.annotation.DefinitionSet;
import org.kie.workbench.common.stunner.core.definition.annotation.Property;
import org.kie.workbench.common.stunner.core.definition.annotation.Shape;
import org.kie.workbench.common.stunner.core.definition.annotation.ShapeSet;
import org.kie.workbench.common.stunner.core.definition.annotation.morph.Morph;
import org.kie.workbench.common.stunner.core.definition.annotation.morph.MorphBase;
import org.kie.workbench.common.stunner.core.definition.annotation.morph.MorphProperty;
import org.kie.workbench.common.stunner.core.definition.builder.VoidBuilder;
import org.kie.workbench.common.stunner.core.definition.property.PropertyMetaTypes;
import org.kie.workbench.common.stunner.core.processors.definition.BindableDefinitionAdapterGenerator;
import org.kie.workbench.common.stunner.core.processors.definitionset.BindableDefinitionSetAdapterGenerator;
import org.kie.workbench.common.stunner.core.processors.definitionset.DefinitionSetProxyGenerator;
import org.kie.workbench.common.stunner.core.processors.factory.ModelFactoryGenerator;
import org.kie.workbench.common.stunner.core.processors.morph.MorphDefinitionGenerator;
import org.kie.workbench.common.stunner.core.processors.morph.MorphDefinitionProviderGenerator;
import org.kie.workbench.common.stunner.core.processors.morph.MorphPropertyDefinitionGenerator;
import org.kie.workbench.common.stunner.core.processors.property.BindablePropertyAdapterGenerator;
import org.kie.workbench.common.stunner.core.processors.propertyset.BindablePropertySetAdapterGenerator;
import org.kie.workbench.common.stunner.core.processors.rule.BindableDefinitionSetRuleAdapterGenerator;
import org.kie.workbench.common.stunner.core.processors.rule.CardinalityRuleGenerator;
import org.kie.workbench.common.stunner.core.processors.rule.ConnectionRuleGenerator;
import org.kie.workbench.common.stunner.core.processors.rule.ContainmentRuleGenerator;
import org.kie.workbench.common.stunner.core.processors.rule.DockingRuleGenerator;
import org.kie.workbench.common.stunner.core.processors.rule.EdgeCardinalityRuleGenerator;
import org.kie.workbench.common.stunner.core.processors.rule.ExtensionRuleGenerator;
import org.kie.workbench.common.stunner.core.processors.shape.BindableShapeFactoryGenerator;
import org.kie.workbench.common.stunner.core.processors.shape.BindableShapeSetGenerator;
import org.uberfire.annotations.processors.AbstractErrorAbsorbingProcessor;
import org.uberfire.annotations.processors.AbstractGenerator;
import org.uberfire.annotations.processors.exceptions.GenerationException;
@SupportedAnnotationTypes({
MainProcessor.ANNOTATION_DEFINITION_SET,
MainProcessor.ANNOTATION_DEFINITION,
MainProcessor.ANNOTATION_PROPERTY_SET,
MainProcessor.ANNOTATION_PROPERTY,
MainProcessor.ANNOTATION_RULE_CAN_CONTAIN,
MainProcessor.ANNOTATION_RULE_CAN_DOCK,
MainProcessor.ANNOTATION_RULE_EXTENSIONS,
MainProcessor.ANNOTATION_RULE_EXTENSION,
MainProcessor.ANNOTATION_RULE_ALLOWED_CONNECTION,
MainProcessor.ANNOTATION_RULE_CAN_CONNECT,
MainProcessor.ANNOTATION_RULE_ALLOWED_EDGE_OCCURRS,
MainProcessor.ANNOTATION_RULE_EDGE_OCCS,
MainProcessor.ANNOTATION_RULE_ALLOWED_OCCS,
MainProcessor.ANNOTATION_RULE_OCCS,
MainProcessor.ANNOTATION_SHAPE,
MainProcessor.ANNOTATION_SHAPE_SET})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MainProcessor extends AbstractErrorAbsorbingProcessor {
public static final String ANNOTATION_DESCRIPTION = "org.kie.workbench.common.stunner.core.definition.annotation.Description";
public static final String ANNOTATION_NAME = "org.kie.workbench.common.stunner.core.definition.annotation.Name";
public static final String ANNOTATION_DEFINITION_SET = "org.kie.workbench.common.stunner.core.definition.annotation.DefinitionSet";
public static final String ANNOTATION_DEFINITION = "org.kie.workbench.common.stunner.core.definition.annotation.Definition";
public static final String ANNOTATION_DEFINITION_CATEGORY = "org.kie.workbench.common.stunner.core.definition.annotation.definition.Category";
public static final String ANNOTATION_DEFINITION_LABELS = "org.kie.workbench.common.stunner.core.definition.annotation.definition.Labels";
public static final String ANNOTATION_DEFINITION_TITLE = "org.kie.workbench.common.stunner.core.definition.annotation.definition.Title";
public static final String[] DEFINITION_ANNOTATIONS = new String[]{
ANNOTATION_DEFINITION_CATEGORY, ANNOTATION_DEFINITION_LABELS,
ANNOTATION_DEFINITION_TITLE
};
public static final String ANNOTATION_PROPERTY_SET = "org.kie.workbench.common.stunner.core.definition.annotation.PropertySet";
public static final String ANNOTATION_PROPERTY = "org.kie.workbench.common.stunner.core.definition.annotation.Property";
public static final String ANNOTATION_PROPERTY_DEFAULT_VALUE = "org.kie.workbench.common.stunner.core.definition.annotation.property.DefaultValue";
public static final String ANNOTATION_PROPERTY_ALLOWED_VALUES = "org.kie.workbench.common.stunner.core.definition.annotation.property.AllowedValues";
public static final String ANNOTATION_PROPERTY_VALUE = "org.kie.workbench.common.stunner.core.definition.annotation.property.Value";
public static final String ANNOTATION_PROPERTY_CAPTION = "org.kie.workbench.common.stunner.core.definition.annotation.property.Caption";
public static final String ANNOTATION_PROPERTY_TYPE = "org.kie.workbench.common.stunner.core.definition.annotation.property.Type";
public static final String ANNOTATION_PROPERTY_READONLY = "org.kie.workbench.common.stunner.core.definition.annotation.property.ReadOnly";
public static final String ANNOTATION_PROPERTY_OPTIONAL = "org.kie.workbench.common.stunner.core.definition.annotation.property.Optional";
public static final String ANNOTATION_MORPH = "org.kie.workbench.common.stunner.core.definition.annotation.morph.Morph";
public static final String ANNOTATION_MORPH_BASE = "org.kie.workbench.common.stunner.core.definition.annotation.morph.MorphBase";
public static final String ANNOTATION_MORPH_PROPERTY = "org.kie.workbench.common.stunner.core.definition.annotation.morph.MorphProperty";
public static final String ANNOTATION_RULE_CAN_CONTAIN = "org.kie.workbench.common.stunner.core.rule.annotation.CanContain";
public static final String ANNOTATION_RULE_CAN_DOCK = "org.kie.workbench.common.stunner.core.rule.annotation.CanDock";
public static final String ANNOTATION_RULE_EXTENSIONS = "org.kie.workbench.common.stunner.core.rule.annotation.RuleExtensions";
public static final String ANNOTATION_RULE_EXTENSION = "org.kie.workbench.common.stunner.core.rule.annotation.RuleExtension";
public static final String ANNOTATION_RULE_ALLOWED_CONNECTION = "org.kie.workbench.common.stunner.core.rule.annotation.AllowedConnections";
public static final String ANNOTATION_RULE_CAN_CONNECT = "org.kie.workbench.common.stunner.core.rule.annotation.CanConnect";
public static final String ANNOTATION_RULE_ALLOWED_OCCS = "org.kie.workbench.common.stunner.core.rule.annotation.AllowedOccurrences";
public static final String ANNOTATION_RULE_OCCS = "org.kie.workbench.common.stunner.core.rule.annotation.Occurrences";
public static final String ANNOTATION_RULE_ALLOWED_EDGE_OCCURRS = "org.kie.workbench.common.stunner.core.rule.annotation.AllowedEdgeOccurrences";
public static final String ANNOTATION_RULE_EDGE_OCCS = "org.kie.workbench.common.stunner.core.rule.annotation.EdgeOccurrences";
public static final String ANNOTATION_SHAPE_SET = "org.kie.workbench.common.stunner.core.client.annotation.ShapeSet";
public static final String ANNOTATION_SHAPE = "org.kie.workbench.common.stunner.core.client.annotation.Shape";
public static final String MORPH_DEFINITION_CLASSNAME = "MorphDefinition";
public static final String MORPH_PROPERTY_DEFINITION_CLASSNAME = "MorphPropertyDefinition";
public static final String MORPH_PROVIDER_CLASSNAME = "MorphDefinitionProvider";
public static final String RULE_CONTAINMENT_SUFFIX_CLASSNAME = "ContainmentRule";
public static final String RULE_DOCKING_SUFFIX_CLASSNAME = "DockingRule";
public static final String RULE_EXTENSION_SUFFIX_CLASSNAME = "ExtRule";
public static final String RULE_CONNECTION_SUFFIX_CLASSNAME = "ConnectionRule";
public static final String RULE_CARDINALITY_SUFFIX_CLASSNAME = "CardinalityRule";
public static final String RULE_EDGE_CARDINALITY_SUFFIX_CLASSNAME = "EdgeCardinalityRule";
public static final String DEFINITIONSET_ADAPTER_CLASSNAME = "DefinitionSetAdapterImpl";
public static final String DEFINITIONSET_PROXY_CLASSNAME = "DefinitionSetProxyImpl";
public static final String DEFINITION_FACTORY_CLASSNAME = "ModelFactoryImpl";
public static final String DEFINITION_ADAPTER_CLASSNAME = "DefinitionAdapterImpl";
public static final String PROPERTYSET_ADAPTER_CLASSNAME = "PropertySetAdapterImpl";
public static final String PROPERTY_ADAPTER_CLASSNAME = "PropertyAdapterImpl";
public static final String RULE_ADAPTER_CLASSNAME = "RuleAdapterImpl";
public static final String SHAPE_FACTORY_CLASSNAME = "ShapeFactory";
private final ProcessingContext processingContext = ProcessingContext.getInstance();
private final ContainmentRuleGenerator containmentRuleGenerator;
private final ConnectionRuleGenerator connectionRuleGenerator;
private final CardinalityRuleGenerator cardinalityRuleGenerator;
private final EdgeCardinalityRuleGenerator edgeCardinalityRuleGenerator;
private final DockingRuleGenerator dockingRuleGenerator;
private final ExtensionRuleGenerator extensionRuleGenerator;
private BindableDefinitionSetAdapterGenerator definitionSetAdapterGenerator;
private BindableDefinitionAdapterGenerator definitionAdapterGenerator;
private BindablePropertySetAdapterGenerator propertySetAdapterGenerator;
private BindablePropertyAdapterGenerator propertyAdapterGenerator;
private BindableDefinitionSetRuleAdapterGenerator ruleAdapterGenerator;
private DefinitionSetProxyGenerator definitionSetProxyGenerator;
private MorphDefinitionGenerator morphDefinitionGenerator;
private MorphPropertyDefinitionGenerator morphPropertyDefinitionGenerator;
private MorphDefinitionProviderGenerator morphDefinitionProviderGenerator;
private BindableShapeSetGenerator shapeSetGenerator;
private ModelFactoryGenerator generatedDefinitionFactoryGenerator;
private BindableShapeFactoryGenerator shapeFactoryGenerator;
public MainProcessor() {
ContainmentRuleGenerator ruleGenerator = null;
ConnectionRuleGenerator connectionRuleGenerator = null;
CardinalityRuleGenerator cardinalityRuleGenerator = null;
EdgeCardinalityRuleGenerator edgeCardinalityRuleGenerator = null;
DockingRuleGenerator dockingRuleGenerator = null;
ExtensionRuleGenerator extensionRuleGenerator = null;
BindableDefinitionSetAdapterGenerator definitionSetAdapterGenerator = null;
BindableDefinitionAdapterGenerator definitionAdapterGenerator = null;
BindablePropertySetAdapterGenerator propertySetAdapterGenerator = null;
BindablePropertyAdapterGenerator propertyAdapter = null;
MorphDefinitionGenerator morphDefinitionGenerator = null;
MorphPropertyDefinitionGenerator morphPropertyDefinitionGenerator = null;
MorphDefinitionProviderGenerator morphDefinitionProviderGenerator = null;
BindableDefinitionSetRuleAdapterGenerator ruleAdapter = null;
DefinitionSetProxyGenerator definitionSetProxyGenerator = null;
BindableShapeSetGenerator shapeSetGenerator = null;
BindableShapeFactoryGenerator shapeFactoryGenerator = null;
ModelFactoryGenerator generatedDefinitionFactoryGenerator = null;
try {
ruleGenerator = new ContainmentRuleGenerator();
propertyAdapter = new BindablePropertyAdapterGenerator();
ruleAdapter = new BindableDefinitionSetRuleAdapterGenerator();
connectionRuleGenerator = new ConnectionRuleGenerator();
cardinalityRuleGenerator = new CardinalityRuleGenerator();
edgeCardinalityRuleGenerator = new EdgeCardinalityRuleGenerator();
dockingRuleGenerator = new DockingRuleGenerator();
extensionRuleGenerator = new ExtensionRuleGenerator();
definitionAdapterGenerator = new BindableDefinitionAdapterGenerator();
definitionSetAdapterGenerator = new BindableDefinitionSetAdapterGenerator();
propertySetAdapterGenerator = new BindablePropertySetAdapterGenerator();
definitionSetProxyGenerator = new DefinitionSetProxyGenerator();
morphDefinitionGenerator = new MorphDefinitionGenerator();
morphPropertyDefinitionGenerator = new MorphPropertyDefinitionGenerator();
morphDefinitionProviderGenerator = new MorphDefinitionProviderGenerator();
shapeSetGenerator = new BindableShapeSetGenerator();
generatedDefinitionFactoryGenerator = new ModelFactoryGenerator();
shapeFactoryGenerator = new BindableShapeFactoryGenerator();
} catch (Throwable t) {
rememberInitializationError(t);
}
this.containmentRuleGenerator = ruleGenerator;
this.connectionRuleGenerator = connectionRuleGenerator;
this.cardinalityRuleGenerator = cardinalityRuleGenerator;
this.edgeCardinalityRuleGenerator = edgeCardinalityRuleGenerator;
this.dockingRuleGenerator = dockingRuleGenerator;
this.extensionRuleGenerator = extensionRuleGenerator;
this.definitionSetAdapterGenerator = definitionSetAdapterGenerator;
this.definitionAdapterGenerator = definitionAdapterGenerator;
this.propertySetAdapterGenerator = propertySetAdapterGenerator;
this.propertyAdapterGenerator = propertyAdapter;
this.ruleAdapterGenerator = ruleAdapter;
this.definitionSetProxyGenerator = definitionSetProxyGenerator;
this.morphDefinitionGenerator = morphDefinitionGenerator;
this.morphPropertyDefinitionGenerator = morphPropertyDefinitionGenerator;
this.morphDefinitionProviderGenerator = morphDefinitionProviderGenerator;
this.shapeSetGenerator = shapeSetGenerator;
this.generatedDefinitionFactoryGenerator = generatedDefinitionFactoryGenerator;
this.shapeFactoryGenerator = shapeFactoryGenerator;
}
public static String toValidId(final String id) {
return StringUtils.uncapitalize(id);
}
public static String toClassMemberId(final String className) {
int i = className.lastIndexOf(".");
String s = i > -1 ? className.substring(i + 1,
className.length()) : className;
return toValidId(s);
}
@Override
protected boolean processWithExceptions(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
if (roundEnv.processingOver()) {
return processLastRound(set,
roundEnv);
}
//If prior processing threw an error exit
if (roundEnv.errorRaised()) {
return false;
}
final Elements elementUtils = processingEnv.getElementUtils();
// Process Definition Sets types found on the processing environment.
for (Element e : roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_DEFINITION_SET))) {
processDefinitionSets(set,
e,
roundEnv);
}
// Process Definition types found on the processing environment.
for (Element e : roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_DEFINITION))) {
processDefinitions(set,
e,
roundEnv);
}
// Process Property Sets types found on the processing environment
// AND
// Process Property Sets types identified as dependant types for the annotated Defininitions. Note that
// those types cannot be directly found on the processing environment if the classes are in a third party
// dependency and not directly on the module sources.
final Set<? extends Element> propertySetElements = new LinkedHashSet<Element>() {{
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_PROPERTY_SET)));
addAll(processingContext.getPropertySetElements());
}};
for (Element e : propertySetElements) {
processPropertySets(set,
e,
roundEnv);
}
// Process Property types found on the processing environment
// AND
// Process PropertySets types identified as dependant types for the annotated Defininitions or Property Sets.
// Note that // those types cannot be directly found on the processing environment if the classes are in a
// third party dependency and not directly on the module sources.
final Set<? extends Element> propertyElements = new LinkedHashSet<Element>() {{
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_PROPERTY)));
addAll(processingContext.getPropertyElements());
}};
for (Element e : propertyElements) {
processProperties(set,
e,
roundEnv);
}
final Set<? extends Element> containRules = new LinkedHashSet<Element>() {{
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_CAN_CONTAIN)));
addAll(processingContext.getDefinitionElements());
removeAll(processingContext.getContainmentRuleElementsProcessed());
}};
for (Element e : containRules) {
processContainmentRules(e);
}
final Set<? extends Element> dockRules = new LinkedHashSet<Element>() {{
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_CAN_DOCK)));
addAll(processingContext.getDefinitionElements());
removeAll(processingContext.getDockingRuleElementsProcessed());
}};
for (Element e : dockRules) {
processDockingRules(e);
}
final Set<? extends Element> extRules = new LinkedHashSet<Element>() {{
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_EXTENSIONS)));
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_EXTENSION)));
}};
for (Element e : extRules) {
processRuleExtension(e);
}
final Set<? extends Element> occRules = new LinkedHashSet<Element>() {{
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_ALLOWED_OCCS)));
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_OCCS)));
}};
for (Element e : occRules) {
processCardinalityRules(e);
}
final Set<? extends Element> edgeOccRules = new LinkedHashSet<Element>() {{
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_ALLOWED_EDGE_OCCURRS)));
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_EDGE_OCCS)));
}};
for (Element e : edgeOccRules) {
processEdgeCardinalityRules(e);
}
final Set<? extends Element> cRules = new LinkedHashSet<Element>() {{
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_ALLOWED_CONNECTION)));
addAll(roundEnv.getElementsAnnotatedWith(elementUtils.getTypeElement(ANNOTATION_RULE_CAN_CONNECT)));
}};
for (Element e : cRules) {
processConnectionRules(e);
}
return true;
}
private boolean processDefinitionSets(final Set<? extends TypeElement> set,
final Element e,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered definition set class [" + classElement.getSimpleName() + "]");
final String packageName = packageElement.getQualifiedName().toString();
final String className = classElement.getSimpleName().toString();
processingContext.setDefinitionSet(packageName,
className);
String defSetClassName = packageName + "." + className;
// Description fields.
processFieldName(classElement,
defSetClassName,
ANNOTATION_DESCRIPTION,
processingContext.getDefSetAnnotations().getDescriptionFieldNames(),
true);
// Definitions identifiers.
DefinitionSet definitionSetAnn = e.getAnnotation(DefinitionSet.class);
List<? extends TypeMirror> mirrors = null;
try {
Class<?>[] defsClasses = definitionSetAnn.definitions();
} catch (MirroredTypesException mte) {
mirrors = mte.getTypeMirrors();
}
if (null == mirrors) {
throw new RuntimeException("No graph class class specifyed for the @DefinitionSet.");
}
Set<String> defIds = new LinkedHashSet<>();
for (TypeMirror mirror : mirrors) {
if (mirror.getKind().equals(TypeKind.DECLARED)) {
final TypeElement t = (TypeElement) ((DeclaredType) mirror).asElement();
processingContext.getDefinitionElements().add(t);
}
String fqcn = mirror.toString();
defIds.add(fqcn);
}
processingContext.getDefSetAnnotations().getDefinitionIds().addAll(defIds);
// Builder class.
processDefinitionSetModelBuilder(e,
defSetClassName,
processingContext.getDefSetAnnotations().getBuilderFieldNames());
// Graph factory type.
TypeMirror mirror = null;
try {
Class<?> graphClass = definitionSetAnn.graphFactory();
} catch (MirroredTypeException mte) {
mirror = mte.getTypeMirror();
}
if (null == mirror) {
throw new RuntimeException("No graph factory class specifyed for the @DefinitionSet.");
}
String fqcn = mirror.toString();
processingContext.getDefSetAnnotations().getGraphFactoryTypes().put(defSetClassName,
fqcn);
// Definition Set's qualifier.
try {
Class<?> qualifierClass = definitionSetAnn.qualifier();
} catch (MirroredTypeException mte) {
mirror = mte.getTypeMirror();
}
if (null == mirror) {
throw new RuntimeException("No qualifier class specifyed for the @DefinitionSet.");
}
processingContext.getDefSetAnnotations().getQualifiers().put(defSetClassName,
mirror.toString());
// Shape Set definition.
ShapeSet shapeSetAnn = e.getAnnotation(ShapeSet.class);
if (null != shapeSetAnn) {
processingContext.getDefSetAnnotations().setHasShapeSet(true);
}
}
return true;
}
private boolean processDefinitions(final Set<? extends TypeElement> set,
final Element e,
final RoundEnvironment roundEnv) throws Exception {
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
String defintionClassName = packageElement.getQualifiedName().toString() + "." + classElement.getSimpleName();
Map<String, String> baseTypes = processingContext.getDefinitionAnnotations().getBaseTypes();
TypeElement parentElement = getDefinitionInheritedType(classElement);
if (null != parentElement && !baseTypes.containsKey(defintionClassName)) {
PackageElement basePackageElement = (PackageElement) parentElement.getEnclosingElement();
String baseClassName = basePackageElement.getQualifiedName().toString() + "." + parentElement.getSimpleName();
baseTypes.put(defintionClassName,
baseClassName);
}
// Category fields.
processFieldName(classElement,
defintionClassName,
ANNOTATION_DEFINITION_CATEGORY,
processingContext.getDefinitionAnnotations().getCategoryFieldNames(),
true);
// Title fields.
processFieldName(classElement,
defintionClassName,
ANNOTATION_DEFINITION_TITLE,
processingContext.getDefinitionAnnotations().getTitleFieldNames(),
true);
// Description fields.
processFieldName(classElement,
defintionClassName,
ANNOTATION_DESCRIPTION,
processingContext.getDefinitionAnnotations().getDescriptionFieldNames(),
true);
// Labels fields.
processFieldName(classElement,
defintionClassName,
ANNOTATION_DEFINITION_LABELS,
processingContext.getDefinitionAnnotations().getLabelsFieldNames(),
true);
// Builder class.
processDefinitionModelBuilder(e,
defintionClassName,
processingContext.getDefinitionAnnotations().getBuilderFieldNames());
// Graph element.
Definition definitionAnn = e.getAnnotation(Definition.class);
TypeMirror mirror = null;
try {
Class<?> graphClass = definitionAnn.graphFactory();
} catch (MirroredTypeException mte) {
mirror = mte.getTypeMirror();
}
if (null == mirror) {
throw new RuntimeException("No graph factory class specified for the @Definition.");
}
String fqcn = mirror.toString();
processingContext.getDefinitionAnnotations().getGraphFactoryFieldNames().put(defintionClassName,
fqcn);
// PropertySets fields.
Map<String, Element> propertySetElements = getFieldNames(classElement,
ANNOTATION_PROPERTY_SET);
if (null != propertySetElements && !propertySetElements.isEmpty()) {
processingContext.getPropertySetElements().addAll(propertySetElements.values());
processingContext.getDefinitionAnnotations().getPropertySetFieldNames().put(defintionClassName,
new LinkedHashSet<>(propertySetElements.keySet()));
} else {
note("Definition for tye [" + defintionClassName + "] have no Property Set members.");
}
// Properties fields.
Map<String, Element> propertyElements = getFieldNames(classElement,
ANNOTATION_PROPERTY);
if (null != propertyElements && !propertyElements.isEmpty()) {
processingContext.getPropertyElements().addAll(propertyElements.values());
processingContext.getDefinitionAnnotations().getPropertyFieldNames().put(defintionClassName,
new LinkedHashSet<>(propertyElements.keySet()));
} else {
note("Definition for tye [" + defintionClassName + "] have no Property members.");
}
// -- Morphing annotations --
MorphBase morphBaseAnn = e.getAnnotation(MorphBase.class);
Morph morphAnn = e.getAnnotation(Morph.class);
if (null != morphBaseAnn && null != morphAnn) {
TypeElement superElement = getAnnotationInTypeInheritance(classElement,
MorphBase.class.getName());
final String packageName = packageElement.getQualifiedName().toString();
String morphBaseClassName = packageName + "." + superElement.getSimpleName().toString();
Map<String, String> defaultTypesMap = processingContext.getMorphingAnnotations().getBaseDefaultTypes();
if (null == defaultTypesMap.get(morphBaseClassName)) {
TypeMirror morphDefaultTypeMirror = null;
try {
Class<?> defaultTypeClass = morphBaseAnn.defaultType();
} catch (MirroredTypeException mte) {
morphDefaultTypeMirror = mte.getTypeMirror();
}
if (null == morphDefaultTypeMirror) {
throw new RuntimeException("No default type class specifyed for the @MorphBase.");
}
String morphDefaultTypeClassName = morphDefaultTypeMirror.toString();
processingContext.getMorphingAnnotations().getBaseDefaultTypes().put(morphBaseClassName,
morphDefaultTypeClassName);
// MorphBase - targets
List<? extends TypeMirror> morphTargetMirrors = null;
try {
Class<?>[] defsClasses = morphBaseAnn.targets();
} catch (MirroredTypesException mte) {
morphTargetMirrors = mte.getTypeMirrors();
}
if (null != morphTargetMirrors) {
Set<String> morphTargetMirrorClasses = new LinkedHashSet<>();
for (TypeMirror morphTargetMirror : morphTargetMirrors) {
String morphTargetMirrorClassName = morphTargetMirror.toString();
morphTargetMirrorClasses.add(morphTargetMirrorClassName);
}
processingContext.getMorphingAnnotations().getBaseTargets().put(morphBaseClassName,
morphTargetMirrorClasses);
}
// Morph Properties.
processMorphProperties(superElement,
morphBaseClassName);
}
TypeMirror morphBaseTypeMirror = null;
try {
Class<?> defaultTypeClass = morphAnn.base();
} catch (MirroredTypeException mte) {
morphBaseTypeMirror = mte.getTypeMirror();
}
if (null == morphBaseTypeMirror) {
throw new RuntimeException("No base type class specifyed for the @MorphBase.");
}
String morphBaseTypeClassName = morphBaseTypeMirror.toString();
Set<String> currentTargets = processingContext.getMorphingAnnotations().getBaseTargets().get(morphBaseTypeClassName);
if (null == currentTargets) {
currentTargets = new LinkedHashSet<>();
processingContext.getMorphingAnnotations().getBaseTargets().put(morphBaseTypeClassName,
currentTargets);
}
currentTargets.add(defintionClassName);
}
// Shape Definitions Factory.
Shape shapeAnn = e.getAnnotation(Shape.class);
if (null != shapeAnn) {
TypeMirror sfm = null;
try {
Class<?> graphClass = shapeAnn.factory();
} catch (MirroredTypeException mte) {
sfm = mte.getTypeMirror();
}
if (null == sfm) {
throw new RuntimeException("No ShapeDef Factory class class specifyed for the Definition ["
+ defintionClassName + "]");
}
String sfmfqcn = sfm.toString();
TypeMirror sm = null;
try {
Class<?> graphClass = shapeAnn.def();
} catch (MirroredTypeException mte) {
sm = mte.getTypeMirror();
}
if (null == sm) {
throw new RuntimeException("No Shape Def class class specifyed for the @Definition.");
}
String smfqcn = sm.toString();
if (!processingContext.getDefinitionAnnotations().getShapeDefinitions().containsKey(defintionClassName)) {
processingContext.getDefinitionAnnotations()
.getShapeDefinitions().put(defintionClassName,
new String[]{sfmfqcn, smfqcn});
}
}
}
return false;
}
private String getTypeName(final Element e) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
return packageElement.getQualifiedName().toString() + "." + classElement.getSimpleName();
}
private TypeElement getAnnotationInTypeInheritance(final TypeElement classElement,
final String annotation) {
TypeElement c = classElement;
while (null != c &&
!hasAnnotation(c,
annotation) &&
!classElement.getQualifiedName().toString().equals(Object.class.getName())) {
c = getParent(c);
}
return c;
}
private boolean hasAnnotation(final TypeElement classElement,
final String annotation) {
Element actionElement = processingEnv.getElementUtils().getTypeElement(annotation);
TypeMirror actionType = actionElement.asType();
if (null != classElement) {
List<? extends AnnotationMirror> mirrors = classElement.getAnnotationMirrors();
if (null != mirrors && !mirrors.isEmpty()) {
for (AnnotationMirror m : mirrors) {
if (m.getAnnotationType().equals(actionType)) {
return true;
}
}
}
}
return false;
}
private void processMorphProperties(final TypeElement classElement,
final String definitionClassName) {
final Messager messager = processingEnv.getMessager();
final Elements elementUtils = processingEnv.getElementUtils();
List<VariableElement> variableElements = ElementFilter.fieldsIn(classElement.getEnclosedElements());
for (VariableElement variableElement : variableElements) {
if (GeneratorUtils.getAnnotation(elementUtils,
variableElement,
ANNOTATION_MORPH_PROPERTY) != null) {
final TypeMirror fieldReturnType = variableElement.asType();
final String fieldReturnTypeName = GeneratorUtils.getTypeMirrorDeclaredName(fieldReturnType);
final String fieldName = variableElement.getSimpleName().toString();
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered Morph Property " +
"for class [" + classElement.getSimpleName() + "] " +
"at field [" + fieldName + "] " +
"of return type [" + fieldReturnTypeName + "]");
// MorphBase - defaultType
MorphProperty morphBaseAnn = variableElement.getAnnotation(MorphProperty.class);
TypeMirror morphDefaultTypeMirror = null;
try {
Class<?> defaultTypeClass = morphBaseAnn.binder();
} catch (MirroredTypeException mte) {
morphDefaultTypeMirror = mte.getTypeMirror();
}
if (null == morphDefaultTypeMirror) {
throw new RuntimeException("No binder class specifyed for the @MorphProperty.");
}
String binderClassName = morphDefaultTypeMirror.toString();
ProcessingMorphProperty morphProperty = new ProcessingMorphProperty(fieldReturnTypeName,
StringUtils.capitalize(fieldName),
binderClassName);
List<ProcessingMorphProperty> morphProperties = processingContext.getMorphingAnnotations().getBaseMorphProperties().get(definitionClassName);
if (null == morphProperties) {
morphProperties = new LinkedList<>();
processingContext.getMorphingAnnotations().getBaseMorphProperties().put(definitionClassName,
morphProperties);
}
morphProperties.add(morphProperty);
}
}
}
private TypeElement getDefinitionInheritedType(TypeElement classElement) {
final Elements elementUtils = processingEnv.getElementUtils();
classElement = getParent(classElement);
while (!classElement.toString().equals(Object.class.getName())) {
List<VariableElement> variableElements = ElementFilter.fieldsIn(classElement.getEnclosedElements());
for (VariableElement variableElement : variableElements) {
for (String annotation : DEFINITION_ANNOTATIONS) {
if (GeneratorUtils.getAnnotation(elementUtils,
variableElement,
annotation) != null) {
return classElement;
}
}
}
classElement = getParent(classElement);
}
return null;
}
private TypeElement getParent(final TypeElement classElement) {
return (TypeElement) processingEnv.getTypeUtils().asElement(classElement.getSuperclass());
}
private void processDefinitionModelBuilder(final Element e,
final String className,
final Map<String, String> processingContextMap) {
Definition definitionAnn = e.getAnnotation(Definition.class);
TypeMirror bMirror = null;
try {
Class<?> builderClass = definitionAnn.builder();
} catch (MirroredTypeException mte) {
bMirror = mte.getTypeMirror();
}
if (null != bMirror && !VoidBuilder.class.getName().equals(bMirror.toString())) {
String fqcn = bMirror.toString();
processingContextMap.put(className,
fqcn);
}
}
private void processDefinitionSetModelBuilder(final Element e,
final String className,
final Map<String, String> processingContextMap) {
DefinitionSet definitionAnn = e.getAnnotation(DefinitionSet.class);
TypeMirror bMirror = null;
try {
Class<?> builderClass = definitionAnn.builder();
} catch (MirroredTypeException mte) {
bMirror = mte.getTypeMirror();
}
if (null != bMirror && !VoidBuilder.class.getName().equals(bMirror.toString())) {
String fqcn = bMirror.toString();
processingContextMap.put(className,
fqcn);
}
}
private boolean processPropertySets(final Set<? extends TypeElement> set,
final Element e,
final RoundEnvironment roundEnv) throws Exception {
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
String propertyClassName = packageElement.getQualifiedName().toString() + "." + classElement.getSimpleName();
// Name fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_NAME,
processingContext.getPropertySetAnnotations().getNameFieldNames(),
true);
// Properties fields.
Map<String, Element> propertyElements = getFieldNames(classElement,
ANNOTATION_PROPERTY);
if (null != propertyElements) {
processingContext.getPropertyElements().addAll(propertyElements.values());
processingContext.getPropertySetAnnotations().getPropertiesFieldNames().put(propertyClassName,
new LinkedHashSet<>(propertyElements.keySet()));
if (propertyElements.isEmpty()) {
note("Property Set for tye [" + propertyClassName + "] have no Property members.");
}
}
}
return false;
}
private boolean processProperties(final Set<? extends TypeElement> set,
final Element e,
final RoundEnvironment roundEnv) throws Exception {
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
String propertyClassName = packageElement.getQualifiedName().toString() + "." + classElement.getSimpleName();
// Meta-properties
Property metaProperty = e.getAnnotation(Property.class);
if (null != metaProperty) {
PropertyMetaTypes type = metaProperty.meta();
if (!PropertyMetaTypes.NONE.equals(type)) {
processingContext.getMetaPropertyTypes().put(type,
propertyClassName + ".class");
}
}
// Value fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_PROPERTY_VALUE,
processingContext.getPropertyAnnotations().getValueFieldNames(),
true);
// Default Value fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_PROPERTY_DEFAULT_VALUE,
processingContext.getPropertyAnnotations().getDefaultValueFieldNames(),
true);
// Allowed Values fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_PROPERTY_ALLOWED_VALUES,
processingContext.getPropertyAnnotations().getAllowedValuesFieldNames(),
false);
// Caption fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_PROPERTY_CAPTION,
processingContext.getPropertyAnnotations().getCaptionFieldNames(),
true);
// Description fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_DESCRIPTION,
processingContext.getPropertyAnnotations().getDescriptionFieldNames(),
true);
// Type fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_PROPERTY_TYPE,
processingContext.getPropertyAnnotations().getTypeFieldNames(),
true);
// Read only fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_PROPERTY_READONLY,
processingContext.getPropertyAnnotations().getReadOnlyFieldNames(),
true);
// Optional fields.
processFieldName(classElement,
propertyClassName,
ANNOTATION_PROPERTY_OPTIONAL,
processingContext.getPropertyAnnotations().getOptionalFieldNames(),
true);
}
return false;
}
private void processFieldName(final TypeElement classElement,
final String propertyClassName,
final String annotation,
final Map<String, String> ctxMap,
final boolean mandatory) {
Map<String, Element> fieldNames = getFieldNames(classElement,
annotation);
boolean empty = fieldNames.isEmpty();
if (mandatory && empty) {
throw new RuntimeException("No annotation of type [" + annotation + "] for Property of class [" + classElement + "]");
}
if (!empty) {
ctxMap.put(propertyClassName,
fieldNames.keySet().iterator().next());
}
}
private Map<String, Element> getFieldNames(TypeElement classElement,
String annotation) {
final Messager messager = processingEnv.getMessager();
final Elements elementUtils = processingEnv.getElementUtils();
Map<String, Element> result = new LinkedHashMap<>();
while (!classElement.toString().equals(Object.class.getName())) {
List<VariableElement> variableElements = ElementFilter.fieldsIn(classElement.getEnclosedElements());
for (VariableElement variableElement : variableElements) {
if (GeneratorUtils.getAnnotation(elementUtils,
variableElement,
annotation) != null) {
final TypeMirror fieldReturnType = variableElement.asType();
final TypeElement t = (TypeElement) ((DeclaredType) fieldReturnType).asElement();
final String fieldReturnTypeName = GeneratorUtils.getTypeMirrorDeclaredName(fieldReturnType);
final String fieldName = variableElement.getSimpleName().toString();
result.put(fieldName,
t);
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered property value " +
"for class [" + classElement.getSimpleName() + "] " +
"at field [" + fieldName + "] " +
"of return type [" + fieldReturnTypeName + "]");
}
}
classElement = getParent(classElement);
}
return result;
}
private boolean processContainmentRules(final Element e) throws Exception {
final Messager messager = processingEnv.getMessager();
final boolean isIface = e.getKind() == ElementKind.INTERFACE;
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isIface || isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered containment rule for class [" + classElement.getSimpleName() + "]");
final String classNameActivity = classElement.getSimpleName() + RULE_CONTAINMENT_SUFFIX_CLASSNAME;
generateRuleCode(containmentRuleGenerator,
messager,
classElement,
packageElement,
classNameActivity);
}
return true;
}
private boolean processRuleExtension(final Element e) throws Exception {
final Messager messager = processingEnv.getMessager();
final boolean isIface = e.getKind() == ElementKind.INTERFACE;
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isIface || isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered rule extension for class [" + classElement.getSimpleName() + "]");
final String classNameActivity = classElement.getSimpleName() + RULE_EXTENSION_SUFFIX_CLASSNAME;
generateRuleCode(extensionRuleGenerator,
messager,
classElement,
packageElement,
classNameActivity);
}
return true;
}
private boolean processDockingRules(final Element e) throws Exception {
final Messager messager = processingEnv.getMessager();
final boolean isIface = e.getKind() == ElementKind.INTERFACE;
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isIface || isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered docking rule for class [" + classElement.getSimpleName() + "]");
final String classNameActivity = classElement.getSimpleName() + RULE_DOCKING_SUFFIX_CLASSNAME;
generateRuleCode(dockingRuleGenerator,
messager,
classElement,
packageElement,
classNameActivity);
}
return true;
}
private boolean processEdgeCardinalityRules(final Element e) throws Exception {
final Messager messager = processingEnv.getMessager();
final boolean isIface = e.getKind() == ElementKind.INTERFACE;
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isIface || isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered edge cardinality rule for class [" + classElement.getSimpleName() + "]");
final String classNameActivity = classElement.getSimpleName() + RULE_EDGE_CARDINALITY_SUFFIX_CLASSNAME;
generateRuleCode(edgeCardinalityRuleGenerator,
messager,
classElement,
packageElement,
classNameActivity);
}
return true;
}
private boolean processCardinalityRules(final Element e) throws Exception {
final Messager messager = processingEnv.getMessager();
final boolean isIface = e.getKind() == ElementKind.INTERFACE;
final boolean isClass = e.getKind() == ElementKind.CLASS;
if (isIface || isClass) {
TypeElement classElement = (TypeElement) e;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered cardinality rule for class [" + classElement.getSimpleName() + "]");
final String classNameActivity = classElement.getSimpleName() + RULE_CARDINALITY_SUFFIX_CLASSNAME;
generateRuleCode(cardinalityRuleGenerator,
messager,
classElement,
packageElement,
classNameActivity);
}
return true;
}
private boolean processConnectionRules(final Element element) throws Exception {
final Messager messager = processingEnv.getMessager();
final boolean isIface = element.getKind() == ElementKind.INTERFACE;
final boolean isClass = element.getKind() == ElementKind.CLASS;
if (isIface || isClass) {
TypeElement classElement = (TypeElement) element;
PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
messager.printMessage(Diagnostic.Kind.NOTE,
"Discovered connection rule for class [" + classElement.getSimpleName() + "]");
final String classNameActivity = classElement.getSimpleName() + RULE_CONNECTION_SUFFIX_CLASSNAME;
generateRuleCode(connectionRuleGenerator,
messager,
classElement,
packageElement,
classNameActivity);
}
return true;
}
private void generateRuleCode(final AbstractGenerator generator,
final Messager messager,
final TypeElement classElement,
final PackageElement packageElement,
final String classNameActivity) {
try {
final String packageName = packageElement.getQualifiedName().toString();
//Try generating code for each required class
messager.printMessage(Diagnostic.Kind.NOTE,
"Generating ryke code for [" + classNameActivity + "]");
generator.generate(packageName,
packageElement,
classNameActivity,
classElement,
processingEnv);
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg,
classElement);
}
}
private boolean processLastRound(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
processLastRoundDefinitionSetProxyAdapter(set,
roundEnv);
processLastRoundDefinitionSetAdapter(set,
roundEnv);
processLastRoundPropertySetAdapter(set,
roundEnv);
processLastRoundDefinitionFactory(set,
roundEnv);
processLastRoundDefinitionAdapter(set,
roundEnv);
processLastRoundPropertyAdapter(set,
roundEnv);
processLastRoundRuleAdapter(set,
roundEnv);
processLastRoundMorphing(set,
roundEnv);
processLastRoundShapesStuffGenerator(set,
roundEnv);
return true;
}
private boolean processLastRoundMorphing(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
// Ensure visible on both backend and client sides.
final String packageName = getGeneratedPackageName() + ".definition.morph";
final Set<String> generatedDefinitionClasses = new LinkedHashSet<>();
// MORPH DEFINITIONS GENERATION.
Map<String, Set<String>> baseTargets = processingContext.getMorphingAnnotations().getBaseTargets();
if (null != baseTargets && !baseTargets.isEmpty()) {
for (Map.Entry<String, Set<String>> entry : baseTargets.entrySet()) {
String baseType = entry.getKey();
Set<String> targets = entry.getValue();
final String className = getMorphDefinitionClassName(packageName,
baseType,
MORPH_DEFINITION_CLASSNAME)[0];
final String classFQName = getMorphDefinitionClassName(packageName,
baseType,
MORPH_DEFINITION_CLASSNAME)[1];
String defaultType = processingContext.getMorphingAnnotations().getBaseDefaultTypes().get(baseType);
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting MorphDefinition adf for class named " + classFQName);
final StringBuffer ruleClassCode = morphDefinitionGenerator.generate(packageName,
className,
baseType,
targets,
defaultType,
messager);
writeCode(packageName,
className,
ruleClassCode);
generatedDefinitionClasses.add(classFQName);
}
}
// MORPH PROPERTY DEFINITIONS GENERATION.
Map<String, List<ProcessingMorphProperty>> morphProperties = processingContext.getMorphingAnnotations().getBaseMorphProperties();
if (null != morphProperties && !morphProperties.isEmpty()) {
for (Map.Entry<String, List<ProcessingMorphProperty>> entry : morphProperties.entrySet()) {
String baseType = entry.getKey();
List<ProcessingMorphProperty> properties = entry.getValue();
final String className = getMorphDefinitionClassName(packageName,
baseType,
MORPH_PROPERTY_DEFINITION_CLASSNAME)[0];
final String classFQName = getMorphDefinitionClassName(packageName,
baseType,
MORPH_PROPERTY_DEFINITION_CLASSNAME)[1];
String defaultType = processingContext.getMorphingAnnotations().getBaseDefaultTypes().get(baseType);
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting MorphPropertyDefinition adf for class named " + classFQName);
final StringBuffer ruleClassCode = morphPropertyDefinitionGenerator.generate(packageName,
className,
baseType,
properties,
defaultType,
messager);
writeCode(packageName,
className,
ruleClassCode);
generatedDefinitionClasses.add(classFQName);
}
}
// MORPH DEFINITIONS PROVIDER GENERATION.
if (!generatedDefinitionClasses.isEmpty()) {
final String className = getSetClassPrefix() + MORPH_PROVIDER_CLASSNAME;
final String classFQName = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting MorphDefinitionProvider adf for class named " + classFQName);
final StringBuffer ruleClassCode = morphDefinitionProviderGenerator.generate(packageName,
className,
generatedDefinitionClasses,
messager);
writeCode(packageName,
className,
ruleClassCode);
}
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private String[] getMorphDefinitionClassName(final String packageName,
final String baseType,
final String suffix) {
String baseTypeName = baseType.substring(baseType.lastIndexOf(".") + 1,
baseType.length());
final String className = baseTypeName + suffix;
String fqcn = packageName + "." + className;
return new String[]{className, fqcn};
}
private boolean processLastRoundRuleAdapter(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
// Ensure visible on both backend and client sides.
final String packageName = getGeneratedPackageName() + ".definition.adapter.binding";
final String className = getSetClassPrefix() + RULE_ADAPTER_CLASSNAME;
final String classFQName = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting RuleAdapter adf for class named " + classFQName);
final StringBuffer ruleClassCode = ruleAdapterGenerator.generate(packageName,
className,
processingContext.getDefinitionSet().getClassName(),
processingContext.getRules(),
messager);
writeCode(packageName,
className,
ruleClassCode);
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private boolean processLastRoundDefinitionSetAdapter(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
// Ensure visible on both backend and client sides.
final String packageName = getGeneratedPackageName() + ".definition.adapter.binding";
final String className = getSetClassPrefix() + DEFINITIONSET_ADAPTER_CLASSNAME;
final String classFQName = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting ErraiBinderAdapter adf named " + classFQName);
final StringBuffer ruleClassCode = definitionSetAdapterGenerator.generate(packageName,
className,
processingContext.getDefSetAnnotations(),
messager);
writeCode(packageName,
className,
ruleClassCode);
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private boolean processLastRoundDefinitionSetProxyAdapter(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
// Ensure visible on both backend and client sides.
final String packageName = getGeneratedPackageName() + ".definition.adapter.binding";
final String className = getSetClassPrefix() + DEFINITIONSET_PROXY_CLASSNAME;
final String classFQName = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting DefinitionSetProxyAdapter adf for class named " + classFQName);
final StringBuffer ruleClassCode = definitionSetProxyGenerator.generate(packageName,
className,
processingContext.getDefinitionSet(),
processingContext.getDefSetAnnotations().getBuilderFieldNames(),
messager);
writeCode(packageName,
className,
ruleClassCode);
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private boolean processLastRoundPropertySetAdapter(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
// Ensure visible on both backend and client sides.
final String packageName = getGeneratedPackageName() + ".definition.adapter.binding";
final String className = getSetClassPrefix() + PROPERTYSET_ADAPTER_CLASSNAME;
final String classFQName = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting ErraiBinderAdapter adf named " + classFQName);
final StringBuffer ruleClassCode = propertySetAdapterGenerator.generate(packageName,
className,
processingContext.getPropertySetAnnotations(),
messager);
writeCode(packageName,
className,
ruleClassCode);
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private boolean processLastRoundDefinitionFactory(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
final int size = processingContext.getDefinitionAnnotations().getBuilderFieldNames().size() +
processingContext.getDefSetAnnotations().getBuilderFieldNames().size();
if (size > 0) {
final Map<String, String> buildersMap = new LinkedHashMap<>();
if (!processingContext.getDefinitionAnnotations().getBuilderFieldNames().isEmpty()) {
buildersMap.putAll(processingContext.getDefinitionAnnotations().getBuilderFieldNames());
}
if (!processingContext.getDefSetAnnotations().getBuilderFieldNames().isEmpty()) {
buildersMap.putAll(processingContext.getDefSetAnnotations().getBuilderFieldNames());
}
// Ensure visible on both backend and client sides.
final String packageName = getGeneratedPackageName() + ".definition.factory";
final String className = getSetClassPrefix() + DEFINITION_FACTORY_CLASSNAME;
final String classFQName = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting ModelFactory adf for class named " + classFQName);
final StringBuffer ruleClassCode = generatedDefinitionFactoryGenerator.generate(packageName,
className,
buildersMap,
messager);
writeCode(packageName,
className,
ruleClassCode);
}
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private boolean processLastRoundDefinitionAdapter(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
// Ensure visible on both backend and client sides.
final String packageName = getGeneratedPackageName() + ".definition.adapter.binding";
final String className = getSetClassPrefix() + DEFINITION_ADAPTER_CLASSNAME;
final String classFQName = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting ErraiBinderAdapter adf named " + classFQName);
final StringBuffer ruleClassCode = definitionAdapterGenerator.generate(packageName,
className,
processingContext,
messager);
writeCode(packageName,
className,
ruleClassCode);
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private boolean processLastRoundPropertyAdapter(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
// Ensure visible on both backend and client sides.
final String packageName = getGeneratedPackageName() + ".definition.adapter.binding";
final String className = getSetClassPrefix() + PROPERTY_ADAPTER_CLASSNAME;
final String classFQName = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting ErraiBinderAdapter adf named " + classFQName);
final StringBuffer ruleClassCode = propertyAdapterGenerator.generate(packageName,
className,
processingContext.getPropertyAnnotations(),
messager);
writeCode(packageName,
className,
ruleClassCode);
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private boolean processLastRoundShapesStuffGenerator(final Set<? extends TypeElement> set,
final RoundEnvironment roundEnv) throws Exception {
final Messager messager = processingEnv.getMessager();
try {
String shapeFactoryClassname = null;
// Generate the Shape Factory, if exist shape definitions.
if (processingContext.getDefSetAnnotations().hasShapeSet() &&
!processingContext.getDefinitionAnnotations().getShapeDefinitions().isEmpty()) {
// Ensure only visible on client side.
final String packageName = getGeneratedPackageName() + ".client.shape";
final String className = getSetClassPrefix() + SHAPE_FACTORY_CLASSNAME;
shapeFactoryClassname = packageName + "." + className;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting Shape Factory bean adf " +
"[" + shapeFactoryClassname + "]");
final StringBuffer sfClassCode = shapeFactoryGenerator.generate(packageName,
className,
processingContext.getDefinitionAnnotations(),
messager);
writeCode(packageName,
className,
sfClassCode);
// Generate the Shape Set if annotation present ( Ensure only visible on client side. ).
final String packageName2 = getGeneratedPackageName() + ".client.shape";
final String className2 = getSetClassPrefix() + BindableAdapterUtils.SHAPE_SET_SUFFIX;
final String classFQName2 = packageName2 + "." + className2;
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting Shape Set bean adf " +
"[" + classFQName2 + "]");
final String defSetClassName = processingContext.getDefinitionSet().getClassName();
final StringBuffer ssClassCode = shapeSetGenerator.generate(packageName2,
className2,
defSetClassName,
shapeFactoryClassname,
messager);
writeCode(packageName2,
className2,
ssClassCode);
}
} catch (GenerationException ge) {
final String msg = ge.getMessage();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
msg);
}
return true;
}
private String getGeneratedPackageName() {
final String s = processingContext.getDefinitionSet().getClassName();
return s.substring(0,
s.lastIndexOf("."));
}
private String getSetClassPrefix() {
return processingContext.getDefinitionSet().getId();
}
private void note(String message) {
log(Diagnostic.Kind.NOTE,
message);
}
private void warn(String message) {
log(Diagnostic.Kind.WARNING,
message);
}
private void error(String message) {
log(Diagnostic.Kind.ERROR,
message);
}
private void log(Diagnostic.Kind kind,
String message) {
final Messager messager = processingEnv.getMessager();
messager.printMessage(kind,
message);
}
}