Skip to content

Instantly share code, notes, and snippets.

@agentgt
Created May 14, 2019 14:57
Show Gist options
  • Save agentgt/a3c8dc50ce992ee375d9e5a358172417 to your computer and use it in GitHub Desktop.
Save agentgt/a3c8dc50ce992ee375d9e5a358172417 to your computer and use it in GitHub Desktop.
Example of Hickory generating a prism for JPA column
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.type.TypeMirror;
import net.java.dev.hickory.prism.internal.*;
import java.util.HashMap;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
/** A Prism representing an {@code @javax.persistence.Column} annotation.
*/
public class ColumnPrism {
/** store prism value of columnDefinition */
private String _columnDefinition;
/** store prism value of insertable */
private Boolean _insertable;
/** store prism value of length */
private Integer _length;
/** store prism value of name */
private String _name;
/** store prism value of nullable */
private Boolean _nullable;
/** store prism value of precision */
private Integer _precision;
/** store prism value of scale */
private Integer _scale;
/** store prism value of table */
private String _table;
/** store prism value of unique */
private Boolean _unique;
/** store prism value of updatable */
private Boolean _updatable;
/**
* An instance of the Values inner class whose
* methods return the AnnotationValues used to build this prism.
* Primarily intended to support using Messager.
*/
public final Values values;
/** Return a prism representing the {@code @javax.persistence.Column} annotation on 'e'.
* similar to {@code e.getAnnotation(javax.persistence.Column.class)} except that
* an instance of this class rather than an instance of {@code javax.persistence.Column}
* is returned.
*/
public static ColumnPrism getInstanceOn(Element e) {
AnnotationMirror m = getMirror("javax.persistence.Column",e);
if(m == null) return null;
return getInstance(m);
}
/** Return a prism of the {@code @javax.persistence.Column} annotation whose mirror is mirror.
*/
public static ColumnPrism getInstance(AnnotationMirror mirror) {
return new ColumnPrism(mirror);
}
private ColumnPrism(AnnotationMirror mirror) {
for(ExecutableElement key : mirror.getElementValues().keySet()) {
memberValues.put(key.getSimpleName().toString(),mirror.getElementValues().get(key));
}
for(ExecutableElement member : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
defaults.put(member.getSimpleName().toString(),member.getDefaultValue());
}
_columnDefinition = getValue("columnDefinition",String.class);
_insertable = getValue("insertable",Boolean.class);
_length = getValue("length",Integer.class);
_name = getValue("name",String.class);
_nullable = getValue("nullable",Boolean.class);
_precision = getValue("precision",Integer.class);
_scale = getValue("scale",Integer.class);
_table = getValue("table",String.class);
_unique = getValue("unique",Boolean.class);
_updatable = getValue("updatable",Boolean.class);
this.values = new Values(memberValues);
this.mirror = mirror;
this.isValid = valid;
}
/**
* Returns a String representing the value of the {@code java.lang.String public abstract java.lang.String columnDefinition() } member of the Annotation.
* @see javax.persistence.Column#columnDefinition()
*/
public String columnDefinition() { return _columnDefinition; }
/**
* Returns a Boolean representing the value of the {@code boolean public abstract boolean insertable() } member of the Annotation.
* @see javax.persistence.Column#insertable()
*/
public Boolean insertable() { return _insertable; }
/**
* Returns a Integer representing the value of the {@code int public abstract int length() } member of the Annotation.
* @see javax.persistence.Column#length()
*/
public Integer length() { return _length; }
/**
* Returns a String representing the value of the {@code java.lang.String public abstract java.lang.String name() } member of the Annotation.
* @see javax.persistence.Column#name()
*/
public String name() { return _name; }
/**
* Returns a Boolean representing the value of the {@code boolean public abstract boolean nullable() } member of the Annotation.
* @see javax.persistence.Column#nullable()
*/
public Boolean nullable() { return _nullable; }
/**
* Returns a Integer representing the value of the {@code int public abstract int precision() } member of the Annotation.
* @see javax.persistence.Column#precision()
*/
public Integer precision() { return _precision; }
/**
* Returns a Integer representing the value of the {@code int public abstract int scale() } member of the Annotation.
* @see javax.persistence.Column#scale()
*/
public Integer scale() { return _scale; }
/**
* Returns a String representing the value of the {@code java.lang.String public abstract java.lang.String table() } member of the Annotation.
* @see javax.persistence.Column#table()
*/
public String table() { return _table; }
/**
* Returns a Boolean representing the value of the {@code boolean public abstract boolean unique() } member of the Annotation.
* @see javax.persistence.Column#unique()
*/
public Boolean unique() { return _unique; }
/**
* Returns a Boolean representing the value of the {@code boolean public abstract boolean updatable() } member of the Annotation.
* @see javax.persistence.Column#updatable()
*/
public Boolean updatable() { return _updatable; }
/**
* Determine whether the underlying AnnotationMirror has no errors.
* True if the underlying AnnotationMirror has no errors.
* When true is returned, none of the methods will return null.
* When false is returned, a least one member will either return null, or another
* prism that is not valid.
*/
public final boolean isValid;
/**
* The underlying AnnotationMirror of the annotation
* represented by this Prism.
* Primarily intended to support using Messager.
*/
public final AnnotationMirror mirror;
/**
* A class whose members corespond to those of javax.persistence.Column
* but which each return the AnnotationValue corresponding to
* that member in the model of the annotations. Returns null for
* defaulted members. Used for Messager, so default values are not useful.
*/
public static class Values {
private Map<String,AnnotationValue> values;
private Values(Map<String,AnnotationValue> values) {
this.values = values;
}
/** Return the AnnotationValue corresponding to the columnDefinition()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue columnDefinition(){ return values.get("columnDefinition");}
/** Return the AnnotationValue corresponding to the insertable()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue insertable(){ return values.get("insertable");}
/** Return the AnnotationValue corresponding to the length()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue length(){ return values.get("length");}
/** Return the AnnotationValue corresponding to the name()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue name(){ return values.get("name");}
/** Return the AnnotationValue corresponding to the nullable()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue nullable(){ return values.get("nullable");}
/** Return the AnnotationValue corresponding to the precision()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue precision(){ return values.get("precision");}
/** Return the AnnotationValue corresponding to the scale()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue scale(){ return values.get("scale");}
/** Return the AnnotationValue corresponding to the table()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue table(){ return values.get("table");}
/** Return the AnnotationValue corresponding to the unique()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue unique(){ return values.get("unique");}
/** Return the AnnotationValue corresponding to the updatable()
* member of the annotation, or null when the default value is implied.
*/
public AnnotationValue updatable(){ return values.get("updatable");}
}
private Map<String,AnnotationValue> defaults = new HashMap<String,AnnotationValue>(10);
private Map<String,AnnotationValue> memberValues = new HashMap<String,AnnotationValue>(10);
private boolean valid = true;
private <T> T getValue(String name, Class<T> clazz) {
T result = ColumnPrism.getValue(memberValues,defaults,name,clazz);
if(result == null) valid = false;
return result;
}
private <T> List<T> getArrayValues(String name, final Class<T> clazz) {
List<T> result = ColumnPrism.getArrayValues(memberValues,defaults,name,clazz);
if(result == null) valid = false;
return result;
}
private static AnnotationMirror getMirror(String fqn, Element target) {
for (AnnotationMirror m :target.getAnnotationMirrors()) {
CharSequence mfqn = ((TypeElement)m.getAnnotationType().asElement()).getQualifiedName();
if(fqn.contentEquals(mfqn)) return m;
}
return null;
}
private static <T> T getValue(Map<String,AnnotationValue> memberValues, Map<String,AnnotationValue> defaults, String name, Class<T> clazz) {
AnnotationValue av = memberValues.get(name);
if(av == null) av = defaults.get(name);
if(av == null) {
return null;
}
if(clazz.isInstance(av.getValue())) return clazz.cast(av.getValue());
return null;
}
private static <T> List<T> getArrayValues(Map<String,AnnotationValue> memberValues, Map<String,AnnotationValue> defaults, String name, final Class<T> clazz) {
AnnotationValue av = memberValues.get(name);
if(av == null) av = defaults.get(name);
if(av == null) {
return null;
}
if(av.getValue() instanceof List) {
List<T> result = new ArrayList<T>();
for(AnnotationValue v : getValueAsList(av)) {
if(clazz.isInstance(v.getValue())) {
result.add(clazz.cast(v.getValue()));
} else{
return null;
}
}
return result;
} else {
return null;
}
}
@SuppressWarnings("unchecked")
private static List<AnnotationValue> getValueAsList(AnnotationValue av) {
return (List<AnnotationValue>)av.getValue();
}
}
@agentgt
Copy link
Author

agentgt commented May 14, 2019

Hickory's doc:

https://www.mvndoc.com/c/com.jolira/hickory/index.html

    <dependency>
      <groupId>com.jolira</groupId>
      <artifactId>hickory</artifactId>
      <version>1.0.0</version>
      <scope>provided</scope>
      <optional>true</optional>
    </dependency>

    <dependency>
      <groupId>org.hibernate.javax.persistence</groupId>
      <artifactId>hibernate-jpa-2.1-api</artifactId>
      <version>1.0.0.Final</version>
      <scope>provided</scope>
      <optional>true</optional>
    </dependency>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment