package org.etk.model.apt; import java.io.IOException; import java.io.PrintWriter; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.ProcessingEnvironment; 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.Element; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import org.etk.model.api.annotations.Entity; import org.etk.model.plugins.entity.binding.EntityBinding; import org.etk.model.plugins.entity.binding.EntityBindingBuilder; import org.etk.orm.api.annotations.NamespaceMapping; import org.etk.orm.api.annotations.NodeTypeDefs; import org.etk.orm.plugins.bean.mapping.BeanMapping; import org.etk.orm.plugins.bean.typegen.NodeType; import org.etk.orm.plugins.bean.typegen.SchemaBuilder; import org.etk.orm.plugins.mapper.SetMap; import org.etk.reflect.api.ClassTypeInfo; import org.etk.reflect.api.TypeResolver; import org.etk.reflect.apt.jxlr.metadata.JxLReflectionMetadata; import org.etk.reflect.core.TypeResolverImpl; @SupportedSourceVersion(SourceVersion.RELEASE_5) @SupportedAnnotationTypes({ "org.etk.model.api.annotations.Entity"}) public class EntityProcessor extends AbstractProcessor { /** . */ private final TypeResolver<Object> domain = TypeResolverImpl.create(JxLReflectionMetadata.newInstance()); /** . */ private ProcessingEnvironment env; @Override public void init(ProcessingEnvironment env) { // this.env = env; // super.init(env); } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { try { return _process(annotations, roundEnv); } catch (RuntimeException e) { e.printStackTrace(); throw e; } } private boolean _process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { Map<String, PackageMetaData> packageMetaData = new HashMap<String, PackageMetaData>(); Set<? extends Element> a = roundEnv.getElementsAnnotatedWith(NodeTypeDefs.class); for (Element e : a) { PackageElement pkgElt = (PackageElement) e; String packageName = new StringBuilder().append(pkgElt.getQualifiedName()).toString(); NodeTypeDefs ntDefs = pkgElt.getAnnotation(NodeTypeDefs.class); Map<String, String> prefixMappings = Collections.emptyMap(); for (NamespaceMapping mapping : ntDefs.namespaces()) { if (prefixMappings.isEmpty()) { prefixMappings = new HashMap<String, String>(); } prefixMappings.put(mapping.prefix(), mapping.uri()); } packageMetaData.put(packageName, new PackageMetaData(packageName, prefixMappings, ntDefs.deep())); } Set<Element> elts = new HashSet<Element>(); elts.addAll(roundEnv.getElementsAnnotatedWith(Entity.class)); try { process(roundEnv, elts, packageMetaData); } catch (Exception e) { throw new RuntimeException(e); } return true; } private void process( RoundEnvironment roundEnv, Set<Element> elts, Map<String, PackageMetaData> packageMetaDatas) throws Exception { Filer filer = processingEnv.getFiler(); Set<ClassTypeInfo> classTypes = new HashSet<ClassTypeInfo>(); SetMap<String, ClassTypeInfo> packageToClassTypes = new SetMap<String, ClassTypeInfo>(); for (Element elt : elts) { TypeElement typeElt = (TypeElement)elt; // ClassTypeInfo cti = (ClassTypeInfo)domain.resolve(typeElt); // TreeMap<Integer, PackageMetaData> packageSorter = new TreeMap<Integer, PackageMetaData>(); for (PackageMetaData packageMetaData : packageMetaDatas.values()) { int dist = packageMetaData.distance(cti); if (dist >= 0) { packageSorter.put(dist, packageMetaData); } } // Find the most appropriate package in those which are declared if (packageSorter.size() > 0) { PackageMetaData packageMetaData = packageSorter.values().iterator().next(); Set<ClassTypeInfo> set = packageToClassTypes.get(packageMetaData.packageName); set.add(cti); } processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "About to process the type " + cti.getName()); classTypes.add(cti); try { JavaFileObject jfo = filer.createSourceFile(typeElt.getQualifiedName() + "_ENTITY", typeElt); PrintWriter out = new PrintWriter(jfo.openWriter()); StringBuilder builder = new StringBuilder(); new ProxyTypeGenerator(cti).build(builder); out.write(builder.toString()); out.close(); } catch (IOException e) { throw new RuntimeException(e); } } // Build mapping EntityBindingBuilder amp = new EntityBindingBuilder(); Map<ClassTypeInfo, EntityBinding> beanMappings = amp.build(classTypes); // Build property literals for (EntityBinding beanMapping : beanMappings.values()) { if (!beanMapping.isAbstract()) { new PropertyLiteralGenerator(beanMapping).build(filer); } } } }