All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.karneim.pojobuilder.analysis.DirectivesFactory Maven / Gradle / Ivy

Go to download

The PojoBuilder Generator is a Java 6 compliant annotation processor that generates a fluent builder class for POJOs (Plain Old Java Object)

There is a newer version: 4.3.0
Show newest version
package net.karneim.pojobuilder.analysis;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

import net.karneim.pojobuilder.GeneratePojoBuilder;

public class DirectivesFactory {
  private final Elements elements;
  private final Types types;
  private final JavaModelAnalyzerUtil javaModelAnalyzerUtil;

  public DirectivesFactory(Elements elements, Types types,
      JavaModelAnalyzerUtil javaModelAnalyzerUtil) {
    this.elements = elements;
    this.types = types;
    this.javaModelAnalyzerUtil = javaModelAnalyzerUtil;
  }

  /**
   * Scans the annotation hierarchy of all annotations on the given (annotated) element for the
   * presence of a {@link GeneratePojoBuilder} annotation and returns a {@link Directives} object
   * populated with the aggregation of the specified {@link GeneratePojoBuilder} element values.
   * 

* Please note that element values can be overridden top-down. This means, that element values * that appear further up in the source code will be overridden by element values further down. * * @param annotatedEl the annotated element * @param orginatingElements this out parameter will be filled with all elements that have (or * could have) contributed to the {@link Directives} throughout the scan process. * @return a {@link Directives} object populated with the effective annotation element values */ public Directives getDirectives(Element annotatedEl, Set orginatingElements) { List hierarchy = findAnnotationHierarchy(annotatedEl); List relevantHierarchy = filterByType(hierarchy, GeneratePojoBuilder.class); Map valueMap = getValueMap(relevantHierarchy); fillOrginatingElements(orginatingElements, hierarchy); Directives result = new Directives(valueMap); validate(annotatedEl, result); return result; } private List filterByType(List hierarchy, Class class1) { TypeMirror generatePojoBuilderAnno = elements.getTypeElement(class1.getName()).asType(); List result = new ArrayList(); for (HierarchyElement el : hierarchy) { if (types.isSameType(el.annotation.getAnnotationType(), generatePojoBuilderAnno)) { result.add(el); } } return result; } private void fillOrginatingElements(Set result, List hierarchy) { for (HierarchyElement hierarchyElement : hierarchy) { result.add(javaModelAnalyzerUtil.getCompilationUnit(hierarchyElement.annotatedEl)); } } private void validate(Element annotatedEl, Directives directives) { if (directives.isGenerateBuilderProperties() && Void.class.getName().equals(directives.getBuilderInterfaceName())) { String message = String .format("Value for \"withBuilderInterface\" not specified. When setting \"withBuilderProperties\" to true, you must also specifiy a valid builder interface."); throw new InvalidElementException(message, annotatedEl); } } private static class HierarchyElement { Element annotatedEl; AnnotationMirror annotation; public HierarchyElement(Element annotatedEl, AnnotationMirror annotation) { super(); this.annotatedEl = annotatedEl; this.annotation = annotation; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((annotatedEl == null) ? 0 : annotatedEl.hashCode()); result = prime * result + ((annotation == null) ? 0 : annotation.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; HierarchyElement other = (HierarchyElement) obj; if (annotatedEl == null) { if (other.annotatedEl != null) return false; } else if (!annotatedEl.equals(other.annotatedEl)) return false; if (annotation == null) { if (other.annotation != null) return false; } else if (!annotation.equals(other.annotation)) return false; return true; } @Override public String toString() { return "HierarchyElement [annotatedEl=" + annotatedEl + ", annotation=" + annotation + "]"; } } private List findAnnotationHierarchy(Element annotatedEl) { Set visitedElements = new HashSet(); List result = new LinkedList(); findAnnotationHierarchy(annotatedEl, result, visitedElements); return result; } private void findAnnotationHierarchy(Element annotatedEl, List result, Set visitedElements) { if (!visitedElements.add(annotatedEl)) { return; } List annos = annotatedEl.getAnnotationMirrors(); for (AnnotationMirror anno : annos) { Element el = anno.getAnnotationType().asElement(); findAnnotationHierarchy(el, result, visitedElements); HierarchyElement hElem = new HierarchyElement(annotatedEl, anno); result.add(hElem); } } private boolean isGeneratePojoBuilderAnnotation(AnnotationMirror anno) { TypeElement generatePojoBuilderTypeEl = elements.getTypeElement(GeneratePojoBuilder.class.getName()); return types.isSameType(anno.getAnnotationType(), generatePojoBuilderTypeEl.asType()); } private Map getValueMap(List hierarchy) { Map result = null; for (HierarchyElement el : hierarchy) { if (isGeneratePojoBuilderAnnotation(el.annotation)) { if (result == null) { result = getValueMap(elements.getElementValuesWithDefaults(el.annotation)); } else { result.putAll(getValueMap(el.annotation.getElementValues())); } } } return result; } private Map getValueMap( Map values) { Map result = new HashMap(); for (Map.Entry entry : values .entrySet()) { String name = entry.getKey().getSimpleName().toString(); Object value = entry.getValue().getValue(); if (value instanceof TypeMirror) { TypeMirror tm = (TypeMirror) value; if (tm.getKind() == TypeKind.DECLARED) { DeclaredType declType = (DeclaredType) tm; TypeElement elem = (TypeElement) declType.asElement(); result.put(name, elem.getQualifiedName().toString()); } else { // TODO could this really happen? result.put(name, String.valueOf(value)); } } else { result.put(name, value); } } return result; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy