package com.onpositive.gae.baseviewer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jdt.internal.core.Annotation;
import org.eclipse.jdt.internal.core.CompilationUnit;
import org.eclipse.jdt.internal.core.ResolvedSourceType;
import org.eclipse.jdt.internal.core.SourceField;
import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.Category;
import com.google.appengine.api.datastore.Email;
import com.google.appengine.api.datastore.GeoPt;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Link;
import com.google.appengine.api.datastore.PhoneNumber;
import com.google.appengine.api.datastore.PostalAddress;
import com.google.appengine.api.datastore.ShortBlob;
import com.google.appengine.api.datastore.Text;
import com.google.appengine.api.users.User;
public class ProjectMiner {
public static final Class[] SUPPORTED_TYPES_FOR_JPA = new Class[] {
boolean.class, byte.class, char.class, double.class, float.class,
int.class, long.class, short.class, boolean[].class, byte[].class,
char[].class, double[].class, float[].class, int[].class,
long[].class, short[].class, java.lang.Boolean.class,
java.lang.Byte.class, java.lang.Character.class,
java.lang.Double.class, java.lang.Float.class,
java.lang.Integer.class, java.lang.Long.class,
java.lang.Short.class, java.lang.Boolean[].class,
java.lang.Byte[].class, java.lang.Character[].class,
java.lang.Double[].class, java.lang.Float[].class,
java.lang.Integer[].class, java.lang.Long[].class,
java.lang.Short[].class, java.lang.Number.class,
java.lang.String.class, java.lang.StringBuffer.class,
java.lang.String[].class, java.math.BigDecimal.class,
java.math.BigInteger.class, java.math.BigDecimal[].class,
java.math.BigInteger[].class, java.util.ArrayList.class,
java.util.Collection.class, java.util.Currency.class,
java.util.Date.class, java.util.Date[].class,
java.util.HashSet.class, java.util.Hashtable.class,
java.util.LinkedHashMap.class, java.util.LinkedHashSet.class,
java.util.LinkedList.class, java.util.List.class,
java.util.Locale.class, java.util.Locale[].class,
java.util.Map.class, java.util.Set.class, java.util.TreeMap.class,
java.util.TreeSet.class, java.util.Vector.class,
java.lang.Enum.class, java.lang.Enum[].class, Blob.class,
Key.class, Text.class, ShortBlob.class, Link.class, Category.class,
Email.class, PostalAddress.class, PhoneNumber.class, GeoPt.class,
User.class };
public static class FieldInfo {
public static final int COMPLETED = 0;
public static final int INCOMPLETED = 1;
private String name;
private String enclosingType;
private String fieldTypeName;
private Class fieldType;
public Class getFieldType() {
return fieldType;
}
public void setFieldType(Class fieldType) {
this.fieldType = fieldType;
}
private IField f;
IField getF() {
return f;
}
void setF(IField f) {
this.f = f;
}
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public FieldInfo(String name, String enclosingType, String fieldType,
int state) {
this.name = name;
this.enclosingType = enclosingType;
this.fieldTypeName = fieldType;
this.state = state;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEnclosingType() {
return enclosingType;
}
public void setEnclosingType(String enclosingType) {
this.enclosingType = enclosingType;
}
public String getFieldTypeName() {
return fieldTypeName;
}
public void setFieldTypeName(String fieldType) {
this.fieldTypeName = fieldType;
}
}
protected static boolean isSupportedType(String simpleName) {
boolean flag = false;
if (simpleName != null) {
for (Class t : SUPPORTED_TYPES_FOR_JPA) {
String n = t.getSimpleName();
if (n.equals(simpleName)) {
flag = true;
break;
}
}
}
return flag;
}
private static Class getSupported(String simpleName) {
if (simpleName != null) {
for (Class t : SUPPORTED_TYPES_FOR_JPA) {
String n = t.getSimpleName();
if (n.equals(simpleName)) {
if (t.isPrimitive()) {
if (t == float.class || t == double.class) {
return Double.class;
} else {
return Long.class;
}
} else {
return t;
}
}
}
}
return null;
}
protected static final ArrayList<String> JPA_PERSISTENT_ANNOTATIONS_FOR_TYPES = new ArrayList();
static {
JPA_PERSISTENT_ANNOTATIONS_FOR_TYPES.add("Entity");
}
protected static final ArrayList<String> JDO_PERSISTENT_ANNOTATIONS_FOR_TYPES = new ArrayList();
static {
JDO_PERSISTENT_ANNOTATIONS_FOR_TYPES.add("PersistenceCapable");
}
protected static final ArrayList<String> JPA_PERSISTENT_ANNOTATIONS_FOR_FIELDS = new ArrayList();
static {
JPA_PERSISTENT_ANNOTATIONS_FOR_FIELDS.add("Basic");
JPA_PERSISTENT_ANNOTATIONS_FOR_FIELDS.add("OneToOne");
JPA_PERSISTENT_ANNOTATIONS_FOR_FIELDS.add("OneToMany");
JPA_PERSISTENT_ANNOTATIONS_FOR_FIELDS.add("ManyToOne");
JPA_PERSISTENT_ANNOTATIONS_FOR_FIELDS.add("ManyToMany");
}
protected static final ArrayList<String> JDO_PERSISTENT_ANNOTATIONS_FOR_FIELDS = new ArrayList();
static {
JDO_PERSISTENT_ANNOTATIONS_FOR_FIELDS.add("Persistent");
}
protected static final ArrayList<String> EMBEDDED_ANNOTATIONS_FOR_FIELDS = new ArrayList();
static {
EMBEDDED_ANNOTATIONS_FOR_FIELDS.add("Embedded");
EMBEDDED_ANNOTATIONS_FOR_FIELDS.add("EmbeddedId");
}
protected class EmbeddedFieldsSearchRequestor extends SearchRequestor {
private HashMap<String, FieldInfo> fields;
private List<String> typeAnnotationSet;
private String[] fieldsAnnotationSet;
private String encType;
private void setEncType(String encType) {
this.encType = encType;
}
public String[] getFieldsAnnotationSet() {
return fieldsAnnotationSet;
}
public void setFieldsAnnotationSet(String[] fieldsAnnotationSet) {
this.fieldsAnnotationSet = fieldsAnnotationSet;
}
public void setFields(HashMap<String, FieldInfo> fields) {
this.fields = fields;
}
public List<String> getAnnotationSet() {
return typeAnnotationSet;
}
public void setTypeAnnotationSet(List<String> annotationSet) {
this.typeAnnotationSet = annotationSet;
}
public HashMap<String, FieldInfo> getFields() {
return fields;
}
public void acceptSearchMatch(SearchMatch match) throws CoreException {
Object element = match.getElement();
if (fields == null) {
fields = new HashMap();
}
if (element instanceof IType) {
IType rst = (IType) element;
IAnnotation ia = null;
ia = getAppropriateAnnotation(rst);
if (ia != null && ia.exists()) {
IField[] fields = rst.getFields();
for (IField f : fields) {
if (isCorrectField(f)) {
int state = FieldInfo.COMPLETED;
if (hasEmbeddedAnnotation(f)) {
state = FieldInfo.INCOMPLETED;
}
String fName = f.getElementName();
String tName = rst.getElementName();
if (encType != null) {
tName = encType;
}
String fType = Signature.toString(f
.getTypeSignature());
FieldInfo fi = new FieldInfo(fName, tName, fType,
state);
if (isSupportedType(fType)) {
fi.setFieldType(getSupported(fType));
}
if (state == FieldInfo.INCOMPLETED) {
fi.setF(f);
}
this.fields.put(fName, fi);
}
}
}
}
return;
}
private boolean hasEmbeddedAnnotation(IField f) {
for (String s : EMBEDDED_ANNOTATIONS_FOR_FIELDS) {
IAnnotation a = f.getAnnotation(s);
if (a != null && a.exists()) {
return true;
}
}
return false;
}
private boolean isCorrectField(IField f) {
if (fieldsAnnotationSet == null || fieldsAnnotationSet.length == 0) {
return true;
}
for (String s : fieldsAnnotationSet) {
IAnnotation ia = f.getAnnotation(s);
if (ia != null && ia.exists()) {
return true;
}
}
return false;
}
private IAnnotation getAppropriateAnnotation(IType t) {
IAnnotation[] iaa;
try {
iaa = t.getAnnotations();
for (IAnnotation ia : iaa) {
String en = ia.getElementName();
if (typeAnnotationSet.contains(en)) {
return ia;
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
return null;
}
}
protected class ReferenceChildSearchRequestor extends SearchRequestor {
private ArrayList<String> types = new ArrayList();
private List<String> annotationsSet;
private boolean isJDO = false;
private boolean isJDO() {
return isJDO;
}
private void setJDO(boolean isJDO) {
this.isJDO = isJDO;
}
public ArrayList<String> getTypes() {
return types;
}
public void setTypes(ArrayList<String> types) {
this.types = types;
}
public List<String> getAnnotationsSet() {
return annotationsSet;
}
public void setAnnotationsSet(List<String> annotationsSet) {
this.annotationsSet = annotationsSet;
}
public void acceptSearchMatch(SearchMatch match) throws CoreException {
Object element = match.getElement();
if (element instanceof IType) {
IType rst = (IType) element;
IAnnotation ia = null;
ia = getAppropriateAnnotation(rst);
if (ia != null && ia.exists()) {
IAnnotation ia2 = rst.getAnnotation("Table");
if (ia2 != null && ia2.exists()) {
String name = rst.getFullyQualifiedName();
String[] els = name.split("\\.");
types.add(els[els.length - 1]);
} else {
String name = rst.getFullyQualifiedName();
String[] els = name.split("\\.");
types.add(els[els.length - 1]);
}
}
}
return;
}
public ArrayList<String> getFound() {
return (ArrayList<String>) types.clone();
}
public void clear() {
types.clear();
}
private IAnnotation getAppropriateAnnotation(IType t) {
IAnnotation[] iaa;
try {
iaa = t.getAnnotations();
for (IAnnotation ia : iaa) {
String en = ia.getElementName();
if (annotationsSet.contains(en)) {
return ia;
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
return null;
}
}
private String kind;
private IJavaProject project;
private ArrayList<IType> types;
private IJavaSearchScope ijss;
public ProjectMiner(String kind2, IJavaProject project2) {
this.kind = kind2;
this.project = project2;
init();
}
protected HashMap<String, FieldInfo> getPossibleEmbeddedTypeMembers(
final String typename, final IJavaSearchScope ijss,
final String[] typeAnnotations, String[] fieldAnnotations,
String encType) {
SearchEngine eng = new SearchEngine();
EmbeddedFieldsSearchRequestor efcr = new EmbeddedFieldsSearchRequestor();
efcr.setTypeAnnotationSet(Arrays.asList(typeAnnotations));
efcr.setFieldsAnnotationSet(fieldAnnotations);
efcr.setEncType(encType);
SearchPattern patternFirst = SearchPattern.createPattern(".*"
+ typename, IJavaSearchConstants.CLASS,
IJavaSearchConstants.DECLARATIONS,
SearchPattern.R_PATTERN_MATCH);
try {
eng.search(patternFirst, new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, ijss, efcr,
new NullProgressMonitor());
return efcr.getFields();
} catch (CoreException e) {
Activator.log(e);
}
return null;
}
protected ArrayList<String> getPossibleRelatedKinds(String typeName,
IJavaSearchScope ijss, String[] annotationL) {
SearchEngine eng = new SearchEngine();
ReferenceChildSearchRequestor asr = new ReferenceChildSearchRequestor();
if (annotationL != null && annotationL.length != 0) {
asr.setAnnotationsSet((List<String>) Arrays.asList(annotationL));
} else {
asr.setAnnotationsSet(new ArrayList());
}
SearchPattern patternFirst = SearchPattern.createPattern(".*"
+ typeName, IJavaSearchConstants.CLASS,
IJavaSearchConstants.DECLARATIONS,
SearchPattern.R_PATTERN_MATCH);
try {
eng.search(patternFirst, new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, ijss, asr,
new NullProgressMonitor());
return asr.getFound();
} catch (CoreException e) {
Activator.log(e);
}
return null;
}
protected class SpecialAppEngSeacrhRequestor extends SearchRequestor {
private ArrayList<IType> types = new ArrayList();
public void acceptSearchMatch(SearchMatch match) throws CoreException {
Object element = match.getElement();
if (element instanceof IType) {
IType rst = (IType) element;
types.add(rst);
}
return;
}
public ArrayList<IType> getFound() {
return (ArrayList<IType>) types.clone();
}
public void clear() {
types.clear();
}
}
public HashMap<String, Class> findAllPossibleFields(Set<String> childs) {
try {
HashMap<String, Class> fieldss = new HashMap();
for (Iterator<IType> i = types.iterator(); i.hasNext();) {
IType r = i.next();
IAnnotation ia = r.getAnnotation("Entity");
if (ia != null && ia.exists()) {
IField[] fields = r.getFields();
for (IField f : fields) {
IField sf = (IField) f;
if (sf instanceof SourceField) {
SourceField ssf = (SourceField) sf;
String sigString = ssf.getTypeSignature();
IAnnotation[] ias = sf.getAnnotations();
if (ias == null || ias.length == 0 && true) {
sigString = Signature.getTypeErasure(sigString);
String simpleName = Signature
.toString(sigString);
String name = sf.getElementName();
if (isSupportedType(simpleName)) {
fieldss.put(name, getSupported(simpleName));
} else {
fieldss.put(name, Blob.class);
}
}
}
}
} else {
IAnnotation ib = r.getAnnotation("PersistenceCapable");
if (ib != null && ib.exists()) {
IField[] fields = r.getFields();
for (IField f : fields) {
IField sf = (IField) f;
if (sf instanceof SourceField) {
SourceField ssf = (SourceField) sf;
String sigString = ssf.getTypeSignature();
IAnnotation iaf = sf
.getAnnotation("Persistent");
IAnnotation iaPk = sf
.getAnnotation("PrimaryKey");
if (iaf != null && iaf.exists()
&& (iaPk == null || !iaPk.exists())) {
sigString = Signature
.getTypeErasure(sigString);
String simpleName = Signature
.toString(sigString);
String name = sf.getElementName();
boolean flg = containsSerializedFlag(iaf);
if ((isSupportedType(simpleName) || flg)
&& !childs.contains(name)) {
if (!flg) {
fieldss.put(name,
getSupported(simpleName));
} else {
if (isSupportedType(simpleName)) {
Class cl = getSupported(simpleName);
if (Collection.class
.isAssignableFrom(cl)) {
fieldss.put(name,
Collection.class);
}
} else {
fieldss.put(name, Blob.class);
}
}
}
}
}
}
}
}
}
return fieldss;
} catch (JavaModelException e) {
e.printStackTrace();
}
return null;
}
private boolean containsSerializedFlag(IAnnotation ia) {
if (ia instanceof Annotation) {
@SuppressWarnings("restriction")
Annotation a = (Annotation) ia;
ICompilationUnit ic = a.getCompilationUnit();
CompilationUnit cu = (CompilationUnit) ic;
ASTParser astParser = ASTParser.newParser(AST.JLS3);
astParser.setSource(cu.getContents());
ASTNode node = astParser.createAST(new NullProgressMonitor());
ASTNode aNode = a
.findNode((org.eclipse.jdt.core.dom.CompilationUnit) node);
if (aNode instanceof NormalAnnotation) {
NormalAnnotation aA = (NormalAnnotation) aNode;
List values = aA.values();
for (Object exp : values) {
if (exp instanceof MemberValuePair) {
MemberValuePair mvp = (MemberValuePair) exp;
String paramName = mvp.getName()
.getFullyQualifiedName();
if (paramName.startsWith("serialized")) {
Expression val = mvp.getValue();
if (val instanceof StringLiteral) {
StringLiteral sl = (StringLiteral) val;
if (sl.getLiteralValue().equals("true")) {
return true;
}
}
}
}
}
return false;
}
}
return false;
}
private void init() {
try {
ArrayList<IJavaElement> elements = prepareJavaElementSet();
ijss = SearchEngine.createJavaSearchScope(
elements.toArray(new IJavaElement[elements.size()]),
IJavaSearchScope.SOURCES);
if (kind != null && kind.length() > 0) {
types = findAllTypes(this.kind, elements);
} else {
types = new ArrayList<IType>();
}
} catch (CoreException e) {
Activator.log(e);
types = new ArrayList<IType>();
}
}
private ArrayList<IType> findAllTypes(String ck,
ArrayList<IJavaElement> elements) throws CoreException {
SearchEngine eng = new SearchEngine();
// AppSearchRequestor asr = new AppSearchRequestor();
SpecialAppEngSeacrhRequestor sAsr = new SpecialAppEngSeacrhRequestor();
SearchPattern patternFirst = SearchPattern.createPattern("*." + ck,
IJavaSearchConstants.CLASS, IJavaSearchConstants.DECLARATIONS,
SearchPattern.R_PATTERN_MATCH);
eng.search(patternFirst, new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, ijss, sAsr,
new NullProgressMonitor());
ArrayList<IType> allTypes = sAsr.getFound();
sAsr.clear();
return allTypes;
}
public HashMap<String, String> findAllPossibleRelatedKindsForThisKind() {
try {
HashMap<String, String> full = new HashMap();
if (types != null) {
for (Iterator<IType> i = types.iterator(); i.hasNext();) {
IType r = i.next();
IField[] fields = r.getFields();
for (IField f : fields) {
IAnnotation iaJDO = isJDO(f);
IAnnotation iaJPA = isJPA(f);
if ((iaJDO != null && iaJDO.exists())
|| (iaJPA != null && iaJPA.exists())) {
if (f instanceof IField) {
IField sf = (IField) f;
String s = sf.getTypeSignature();
String name = Signature.toString(s);
String[] ss = Signature.getTypeArguments(s);
if (ss.length == 1) {
name = Signature.toString(ss[0]);
}
String valName = sf.getElementName();
ArrayList<String> pch = null;
if (iaJDO != null && iaJDO.exists()) {
pch = getPossibleRelatedKinds(
name,
ijss,
JDO_PERSISTENT_ANNOTATIONS_FOR_TYPES
.toArray(new String[JDO_PERSISTENT_ANNOTATIONS_FOR_TYPES
.size()]));
} else if (iaJPA != null && iaJPA.exists()) {
pch = getPossibleRelatedKinds(
name,
ijss,
JPA_PERSISTENT_ANNOTATIONS_FOR_TYPES
.toArray(new String[JPA_PERSISTENT_ANNOTATIONS_FOR_TYPES
.size()]));
}
if (pch != null) {
for (Iterator<String> ii = pch.iterator(); ii
.hasNext();) {
String sss = ii.next();
full.put(valName, sss);
}
}
}
}
}
}
}
return full;
} catch (JavaModelException e) {
Activator.log(e);
}
return new HashMap<String, String>();
}
private ArrayList<IJavaElement> prepareJavaElementSet()
throws JavaModelException {
ArrayList<IJavaElement> elements = new ArrayList<IJavaElement>();
IPackageFragmentRoot[] elems = project.getAllPackageFragmentRoots();
for (IPackageFragmentRoot ipfr : elems) {
// if (ipfr.getKind() != IPackageFragmentRoot.K_SOURCE) {
// continue;
// }
IJavaElement[] children = ipfr.getChildren();
for (IJavaElement e : children) {
elements.add(e);
}
}
return elements;
}
private IAnnotation isJPA(IField f) {
try {
IAnnotation[] ia = f.getAnnotations();
for (IAnnotation a : ia) {
String name = a.getElementName();
if (JPA_PERSISTENT_ANNOTATIONS_FOR_FIELDS.contains(name)
&& a.exists()) {
return a;
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
return null;
}
private IAnnotation isJDO(IField f) {
try {
IAnnotation[] ia = f.getAnnotations();
for (IAnnotation a : ia) {
String name = a.getElementName();
if (JDO_PERSISTENT_ANNOTATIONS_FOR_FIELDS.contains(name)
&& a.exists()) {
return a;
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
return null;
}
protected class AnnotationSearchRequestor extends SearchRequestor {
private ArrayList<String> entityName = new ArrayList();
public ArrayList<String> getEntityName() {
return entityName;
}
public void clear() {
entityName.clear();
}
public void acceptSearchMatch(SearchMatch match) throws CoreException {
Object element = match.getElement();
if (element instanceof ResolvedSourceType) {
ResolvedSourceType type = (ResolvedSourceType) element;
String name = type.getElementName();
entityName.add(name);
}
return;
}
}
public String[] findAllPossibleKindsForProject() {
try {
SearchEngine engine = new SearchEngine();
ArrayList<IJavaElement> elements = new ArrayList<IJavaElement>();
IPackageFragmentRoot[] fragments = project
.getPackageFragmentRoots();
for (IPackageFragmentRoot fragment : fragments) {
int elementType = fragment.getKind();
/*
* if (elementType != IPackageFragmentRoot.K_SOURCE) { continue;
* }
*/
IJavaElement[] children = fragment.getChildren();
for (IJavaElement e : children) {
elements.add(e);
}
}
IJavaSearchScope ijss = SearchEngine.createJavaSearchScope(
elements.toArray(new IJavaElement[elements.size()]),
IJavaSearchScope.SOURCES);
AnnotationSearchRequestor asr = new AnnotationSearchRequestor();
SearchPattern patternFirst = SearchPattern.createPattern(
"PersistenceCapable", IJavaSearchConstants.ANNOTATION_TYPE,
IJavaSearchConstants.REFERENCES,
SearchPattern.R_EXACT_MATCH);
SearchPattern patternSecond = SearchPattern.createPattern("Entity",
IJavaSearchConstants.ANNOTATION_TYPE,
IJavaSearchConstants.REFERENCES,
SearchPattern.R_EXACT_MATCH);
engine.search(patternFirst, new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, ijss, asr,
new NullProgressMonitor());
ArrayList<String> full = new ArrayList<String>();
full.addAll(asr.getEntityName());
asr.clear();
engine.search(patternSecond, new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, ijss, asr,
new NullProgressMonitor());
full.addAll(asr.getEntityName());
return full.toArray(new String[full.size()]);
} catch (JavaModelException e) {
e.printStackTrace();
} catch (CoreException e) {
e.printStackTrace();
}
return null;
}
public HashMap<String, FieldInfo> getEmbeddedFields() {
try {
HashMap<String, FieldInfo> embeddedTypes = new HashMap();
for (Iterator<IType> i = types.iterator(); i.hasNext();) {
IType r = i.next();
boolean isjdo = isJDO(r);
boolean isjpa = isJPA(r);
if (isjdo || isjpa) {
IField[] fields = r.getFields();
for (IField f : fields) {
String name = Signature.toString(f.getTypeSignature());
IAnnotation emb = isFieldEmbedded(f);
if (emb != null && emb.exists()) {
findAllRelatedFields(embeddedTypes, isjdo, f, name,
null);
}
}
String key = isFieldsCompleted(embeddedTypes);
while (key != null) {
FieldInfo removed = embeddedTypes.remove(key);
String name = removed.getFieldTypeName();
String encType = removed.getEnclosingType();
IField f = removed.getF();
findAllRelatedFields(embeddedTypes, isjdo, f, name,
encType);
key = isFieldsCompleted(embeddedTypes);
}
}
}
return embeddedTypes;
} catch (JavaModelException e) {
e.printStackTrace();
}
return null;
}
private void findAllRelatedFields(HashMap<String, FieldInfo> embeddedTypes,
boolean isjdo, IField f, String name, String encType) {
HashMap<String, String> labels = null;
HashMap<String, FieldInfo> res = null;
if (isjdo) {
labels = parseAnnotation(f, true);
res = getPossibleEmbeddedTypeMembers(name, ijss,
new String[] { "EmbeddedOnly" },
new String[] { "Persistent" }, encType);
} else {
labels = parseAnnotation(f, false);
res = getPossibleEmbeddedTypeMembers(name, ijss,
new String[] { "Embeddable" }, new String[0], encType);
}
if (res != null) {
if (labels != null && labels.size() != 0) {
for (String l : labels.keySet()) {
if (res.keySet().contains(l)) {
FieldInfo e = res.get(l);
String nn = labels.get(l);
e.setName(nn);
res.remove(l);
res.put(nn, e);
}
}
}
embeddedTypes.putAll(res);
}
}
private String isFieldsCompleted(Map<String, FieldInfo> fm) {
for (String k : fm.keySet()) {
FieldInfo fi = fm.get(k);
if (fi.getState() == FieldInfo.INCOMPLETED) {
return k;
}
}
return null;
}
private HashMap<String, String> parseAnnotation(IField f, boolean isJdo) {
IAnnotation emb = isFieldEmbedded(f);
HashMap<String, String> elems = new HashMap();
IAnnotation[] ias;
if (isJdo) {
try {
ias = f.getAnnotations();
String annotationSetName = "Embedded";
String annotationName = "Persistent";
String nameProp = "name";
String colProp = "column";
for (IAnnotation ia : ias) {
if (ia.getElementName().equals(annotationSetName)) {
Annotation a = (Annotation) ia;
ICompilationUnit ic = a.getCompilationUnit();
CompilationUnit cu = (CompilationUnit) ic;
ASTParser astParser = ASTParser.newParser(AST.JLS3);
astParser.setSource(cu.getContents());
ASTNode node = astParser
.createAST(new NullProgressMonitor());
ASTNode aNode = a
.findNode((org.eclipse.jdt.core.dom.CompilationUnit) node);
if (aNode instanceof NormalAnnotation) {
NormalAnnotation na = (NormalAnnotation) aNode;
Expression exp = getAnnotationElement(na, "members");
parseAnnotationListElement(elems, annotationName,
nameProp, colProp, exp);
}
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
} else {
try {
ias = f.getAnnotations();
String annotationSetName = "AttributeOverrides";
String annotationName = "AttributeOverride";
String nameProp = "name";
String colProp = "column";
for (IAnnotation ia : ias) {
if (ia.getElementName().equals(annotationSetName)) {
if (ia instanceof Annotation) {
Annotation a = (Annotation) ia;
ICompilationUnit ic = a.getCompilationUnit();
CompilationUnit cu = (CompilationUnit) ic;
ASTParser astParser = ASTParser.newParser(AST.JLS3);
astParser.setSource(cu.getContents());
ASTNode node = astParser
.createAST(new NullProgressMonitor());
ASTNode aNode = a
.findNode((org.eclipse.jdt.core.dom.CompilationUnit) node);
if (aNode instanceof SingleMemberAnnotation) {
SingleMemberAnnotation sma = (SingleMemberAnnotation) aNode;
Expression val = sma.getValue();
parseAnnotationListElement(elems,
annotationName, nameProp, colProp, val);
}
}
} else if (ia.getElementName().equals(annotationName)) {
Annotation a = (Annotation) ia;
ICompilationUnit ic = a.getCompilationUnit();
CompilationUnit cu = (CompilationUnit) ic;
ASTParser astParser = ASTParser.newParser(AST.JLS3);
astParser.setSource(cu.getContents());
ASTNode node = astParser
.createAST(new NullProgressMonitor());
ASTNode aNode = a
.findNode((org.eclipse.jdt.core.dom.CompilationUnit) node);
if (aNode instanceof NormalAnnotation) {
parseAnnotationElement(elems, annotationName,
nameProp, colProp, aNode);
}
}
}
} catch (JavaModelException e) {
e.printStackTrace();
}
}
return elems;
}
protected void parseAnnotationListElement(HashMap<String, String> elems,
String annotationName, String nameProp, String colProp,
Expression exp) {
if (exp instanceof ArrayInitializer) {
ArrayInitializer ai = (ArrayInitializer) exp;
List<Expression> expL = ai.expressions();
for (Expression e : expL) {
parseAnnotationElement(elems, annotationName, nameProp,
colProp, e);
}
}
}
private void parseAnnotationElement(HashMap<String, String> elems,
String annotationName, String nameProp, String colProp, ASTNode e) {
if (e instanceof NormalAnnotation) {
NormalAnnotation na = (NormalAnnotation) e;
String naName = na.getTypeName().getFullyQualifiedName();
if (naName.equals(annotationName)) {
Expression nameEXP = getAnnotationElement(na, nameProp);
Expression columnExp = getAnnotationElement(na, colProp);
while (!(columnExp instanceof StringLiteral)) {
columnExp = getAnnotationElement(columnExp, nameProp);
}
if (nameEXP instanceof StringLiteral
&& columnExp instanceof StringLiteral) {
String nname = ((StringLiteral) nameEXP).getLiteralValue();
String ccol = ((StringLiteral) columnExp).getLiteralValue();
elems.put(nname, ccol);
}
}
}
}
private Expression getAnnotationElement(Expression na, String name) {
if (na instanceof StringLiteral) {
return na;
} else if (na instanceof NormalAnnotation) {
NormalAnnotation nan = (NormalAnnotation) na;
List val = nan.values();
for (Object v : val) {
if (v instanceof MemberValuePair) {
MemberValuePair mvp = (MemberValuePair) v;
if (mvp.getName().toString().startsWith(name)) {
return mvp.getValue();
}
}
}
}
return null;
}
private IAnnotation isFieldEmbedded(IField t) {
for (String s : EMBEDDED_ANNOTATIONS_FOR_FIELDS) {
IAnnotation emb = t.getAnnotation(s);
if (emb != null && emb.exists()) {
return emb;
}
}
return null;
}
private boolean isJPA(IType t) {
for (String s : JPA_PERSISTENT_ANNOTATIONS_FOR_TYPES) {
IAnnotation iaJPA = t.getAnnotation(s);
if (iaJPA != null && iaJPA.exists()) {
return true;
}
}
return false;
}
private boolean isJDO(IType t) {
for (String s : JDO_PERSISTENT_ANNOTATIONS_FOR_TYPES) {
IAnnotation iaJDO = t.getAnnotation(s);
if (iaJDO != null && iaJDO.exists()) {
return true;
}
}
return false;
}
}