/*******************************************************************************
* Copyright (c) 2007-2008 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributor:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.hibernate.eclipse.jdt.ui.internal.jpa.process;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.hibernate.eclipse.jdt.ui.internal.jpa.collect.CollectEntityInfo;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.EntityInfo;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.EntityInfosCollection;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.JPAConst;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.OwnerType;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.RefColumnInfo;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.RefEntityInfo;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.RefFieldInfo;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.RefType;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.EntityInfo.FieldGetterType;
/**
* Visitor to insert JPA annotations into proper
* places of entity class.
*
* @author Vitali
*/
public class ProcessEntityInfo extends ASTVisitor {
/**
* information about entity's annotations for whole compilation unit
*/
protected EntityInfosCollection entityInfos;
/**
* information about entity's annotations
*/
protected EntityInfo entityInfo;
/**
* information about all entities
*/
protected Map<String, EntityInfo> entities;
/**
* rewriter to generate new AST blocks
*/
protected ASTRewrite rewriter;
/**
* annotation style
*/
protected AnnotStyle annotationStyle = AnnotStyle.FIELDS;
/**
* default length for column which corresponds to String field
*/
protected int defaultStrLength = AllEntitiesProcessor.columnLength;
/**
* flag to enable optimistic locking
*/
protected boolean enableOptLock = false;
public void setEntityInfos(EntityInfosCollection entityInfos) {
this.entityInfos = entityInfos;
}
public void setEntities(Map<String, EntityInfo> entities) {
this.entities = entities;
}
public void setASTRewrite(ASTRewrite rewriter) {
this.rewriter = rewriter;
}
public boolean visit(CompilationUnit node) {
entityInfo = null;
// TODO: sort all imports in alphabetic order
//ListRewrite lrw = rewriter.getListRewrite(node, CompilationUnit.IMPORTS_PROPERTY);
for (int i = 0; i < JPAConst.ALL_IMPORTS.size(); i++) {
String tmp = JPAConst.ALL_IMPORTS.get(i);
if (entityInfos.needImport(tmp)) {
addImport(node, tmp);
}
}
return true;
}
public boolean addImport(CompilationUnit node, String importDeclaration) {
String[] importDeclarations = importDeclaration.split("\\."); //$NON-NLS-1$
if (importDeclarations.length <= 1) {
return false;
}
ImportDeclaration importDecl = rewriter.getAST().newImportDeclaration();
SimpleName simpleName0 = rewriter.getAST().newSimpleName(importDeclarations[0]);
SimpleName simpleName1 = rewriter.getAST().newSimpleName(importDeclarations[1]);
QualifiedName qualifiedName0 = rewriter.getAST().newQualifiedName(simpleName0, simpleName1);
for (int i = 2; i < importDeclarations.length; i++) {
SimpleName simpleNameI = rewriter.getAST().newSimpleName(importDeclarations[i]);
qualifiedName0 = rewriter.getAST().newQualifiedName(qualifiedName0, simpleNameI);
}
importDecl.setName(qualifiedName0);
ListRewrite lrw = rewriter.getListRewrite(node, CompilationUnit.IMPORTS_PROPERTY);
// insert import declaration in the proper place
// prefer alphabetic order and package separation
Iterator<?> it = lrw.getRewrittenList().iterator();
ASTNode insertBeforeNode = null;
for ( ; it.hasNext(); ) {
Object obj = it.next();
if (!(obj instanceof ImportDeclaration)) {
continue;
}
ImportDeclaration id = (ImportDeclaration)obj;
String idName = id.getName().getFullyQualifiedName();
if (idName.compareTo(importDeclaration) > 0) {
insertBeforeNode = id;
break;
}
}
if (insertBeforeNode == null) {
lrw.insertLast(importDecl, null);
}
else {
lrw.insertBefore(importDecl, insertBeforeNode, null);
}
return true;
}
@SuppressWarnings("unchecked")
public boolean visit(TypeDeclaration node) {
ITypeBinding typeBinding = node.resolveBinding();
String nodeName = typeBinding == null ? null : typeBinding.getBinaryName();
if (nodeName == null) {
return false;
}
entityInfo = entityInfos.getEntityInfo(nodeName);
if (entityInfo == null) {
return false;
}
if (entityInfo.isAddMappedSuperclassFlag()) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_MAPPEDSUPERCLASS));
ListRewrite lrw = rewriter.getListRewrite(node, TypeDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
if (entityInfo.isAddEntityFlag()) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_ENTITY));
ListRewrite lrw = rewriter.getListRewrite(node, TypeDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
/** /
if (!entityInfo.isImplicitConstructorFlag() && !entityInfo.isDefaultConstructorFlag() &&
entityInfo.isAddSerializableInterfaceFlag()) {
// add serializable interface
SimpleName sn = null;
//if (!entityInfo.isAddSerializableInterfaceImportFlag()) {
sn = rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_SERIALIZABLE);
//}
//else {
// sn = rewriter.getAST().newSimpleName(JPAConst.IMPORT_SERIALIZABLE);
//}
SimpleType st = rewriter.getAST().newSimpleType(sn);
ListRewrite lrw = rewriter.getListRewrite(node, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY);
lrw.insertFirst(st, null);
// add "private static final long serialVersionUID = 1L;"
// ...
}
/**/
if (!entityInfo.isImplicitConstructorFlag() && !entityInfo.isDefaultConstructorFlag() &&
entityInfo.isAddSerializableInterfaceFlag()) {
MethodDeclaration md = rewriter.getAST().newMethodDeclaration();
md.setConstructor(true);
Modifier modifier = rewriter.getAST().newModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
md.modifiers().add(modifier);
Block body = rewriter.getAST().newBlock();
md.setBody(body);
SimpleName sn = rewriter.getAST().newSimpleName(entityInfo.getName());
md.setName(sn);
ListRewrite lrw = rewriter.getListRewrite(node, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
List<?> list = lrw.getOriginalList();
MethodDeclaration insertBeforeNode = null;
Iterator<?> it = list.iterator();
while (it.hasNext()) {
Object obj = it.next();
if (obj instanceof MethodDeclaration) {
insertBeforeNode = (MethodDeclaration)obj;
break;
}
}
if (insertBeforeNode == null) {
lrw.insertLast(md, null);
}
else {
lrw.insertBefore(md, insertBeforeNode, null);
}
}
if (enableOptLock && entityInfo.isAddVersionFlag() && !entityInfo.hasVersionAnnotation()) {
// add property "version", add getter/setter getVersion/setVersion,
// add annotation for the property or for the getter
//
final String version = "version"; //$NON-NLS-1$
final String versionType = "Integer"; //$NON-NLS-1$
//
VariableDeclarationFragment vdFragment = rewriter.getAST().newVariableDeclarationFragment();
SimpleName variableName = rewriter.getAST().newSimpleName(version);
vdFragment.setName(variableName);
FieldDeclaration fieldVersion = rewriter.getAST().newFieldDeclaration(vdFragment);
Modifier modifier = rewriter.getAST().newModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
fieldVersion.modifiers().add(modifier);
Name typeName = rewriter.getAST().newName(versionType);
SimpleType type = rewriter.getAST().newSimpleType(typeName);
fieldVersion.setType(type);
//
MethodDeclaration mdGetter = rewriter.getAST().newMethodDeclaration();
modifier = rewriter.getAST().newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
mdGetter.modifiers().add(modifier);
Block body = rewriter.getAST().newBlock();
ReturnStatement returnVersion = rewriter.getAST().newReturnStatement();
variableName = rewriter.getAST().newSimpleName(version);
returnVersion.setExpression(variableName);
body.statements().add(returnVersion);
mdGetter.setBody(body);
SimpleName sn = rewriter.getAST().newSimpleName("getVersion"); //$NON-NLS-1$
mdGetter.setName(sn);
typeName = rewriter.getAST().newName(versionType);
type = rewriter.getAST().newSimpleType(typeName);
mdGetter.setReturnType2(type);
//
MethodDeclaration mdSetter = rewriter.getAST().newMethodDeclaration();
modifier = rewriter.getAST().newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
mdSetter.modifiers().add(modifier);
body = rewriter.getAST().newBlock();
Assignment assignment = rewriter.getAST().newAssignment();
FieldAccess fieldAccess = rewriter.getAST().newFieldAccess();
ThisExpression thisExpression = rewriter.getAST().newThisExpression();
fieldAccess.setExpression(thisExpression);
variableName = rewriter.getAST().newSimpleName(version);
fieldAccess.setName(variableName);
assignment.setLeftHandSide(fieldAccess);
variableName = rewriter.getAST().newSimpleName(version);
assignment.setRightHandSide(variableName);
ExpressionStatement expressionStatement = rewriter.getAST().newExpressionStatement(assignment);
body.statements().add(expressionStatement);
mdSetter.setBody(body);
sn = rewriter.getAST().newSimpleName("setVersion"); //$NON-NLS-1$
mdSetter.setName(sn);
SingleVariableDeclaration svd = rewriter.getAST().newSingleVariableDeclaration();
variableName = rewriter.getAST().newSimpleName(version);
svd.setName(variableName);
typeName = rewriter.getAST().newName(versionType);
type = rewriter.getAST().newSimpleType(typeName);
svd.setType(type);
mdSetter.parameters().add(svd);
//
ListRewrite lrw = rewriter.getListRewrite(node, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
if (entityInfo.getVersionFieldGetter() != FieldGetterType.FIELD &&
entityInfo.getVersionFieldGetter() != FieldGetterType.FIELD_GETTER) {
lrw.insertLast(fieldVersion, null);
}
if (entityInfo.getVersionFieldGetter() != FieldGetterType.GETTER &&
entityInfo.getVersionFieldGetter() != FieldGetterType.FIELD_GETTER) {
lrw.insertLast(mdGetter, null);
lrw.insertLast(mdSetter, null);
}
if (annotationStyle == AnnotStyle.FIELDS) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_VERSION));
lrw = rewriter.getListRewrite(fieldVersion, FieldDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
else if (annotationStyle == AnnotStyle.GETTERS) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_VERSION));
lrw = rewriter.getListRewrite(mdGetter, MethodDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
}
return true;
}
@SuppressWarnings("unchecked")
public boolean visit(FieldDeclaration node) {
if (entityInfo == null) {
return false;
}
if (annotationStyle != AnnotStyle.FIELDS) {
return true;
}
Type type = node.getType();
if (type == null) {
return true;
}
if (type.isSimpleType() || type.isPrimitiveType()) {
if (entityInfo.isAddGeneratedValueFlag()) {
String primaryIdName = entityInfo.getPrimaryIdName();
Iterator<VariableDeclarationFragment> itVarNames = node.fragments().iterator();
boolean addGeneratedValueMarker = false;
while (itVarNames.hasNext()) {
VariableDeclarationFragment var = itVarNames.next();
String name = var.getName().getIdentifier();
if (primaryIdName.equals(name)) {
addGeneratedValueMarker = true;
break;
}
}
if (addGeneratedValueMarker) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_GENERATED_VALUE));
ListRewrite lrw = rewriter.getListRewrite(node, FieldDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
}
if (entityInfo.isAddPrimaryIdFlag()) {
String primaryIdName = entityInfo.getPrimaryIdName();
Iterator<VariableDeclarationFragment> itVarNames = node.fragments().iterator();
boolean addIdMarker = false;
while (itVarNames.hasNext()) {
VariableDeclarationFragment var = itVarNames.next();
String name = var.getName().getIdentifier();
if (primaryIdName.equals(name)) {
addIdMarker = true;
break;
}
}
if (addIdMarker) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_ID));
ListRewrite lrw = rewriter.getListRewrite(node, FieldDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
}
if (enableOptLock && entityInfo.isAddVersionFlag() && !entityInfo.hasVersionAnnotation()) {
Iterator<VariableDeclarationFragment> itVarNames = node.fragments().iterator();
boolean addVersionMarker = false;
while (itVarNames.hasNext()) {
VariableDeclarationFragment var = itVarNames.next();
String name = var.getName().getIdentifier();
if ("version".equals(name)) { //$NON-NLS-1$
addVersionMarker = true;
break;
}
}
if (addVersionMarker) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_VERSION));
ListRewrite lrw = rewriter.getListRewrite(node, FieldDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
}
}
if (type.isSimpleType() && (AllEntitiesProcessor.columnLength != defaultStrLength)) {
SimpleType simpleType = (SimpleType)type;
String typeName = simpleType.getName().getFullyQualifiedName();
if ("java.lang.String".equals(typeName) || "String".equals(typeName)) { //$NON-NLS-1$ //$NON-NLS-2$
String fieldId = null;
Iterator<VariableDeclarationFragment> itVarNames = node.fragments().iterator();
while (itVarNames.hasNext()) {
VariableDeclarationFragment var = itVarNames.next();
fieldId = var.getName().getIdentifier();
if (fieldId != null) {
break;
}
}
RefColumnInfo rci = entityInfo.getRefColumnInfo(fieldId);
if (rci == null || !rci.isExist()) {
// if there is no @Column annotation - create new @Column annotation
// with user defined default value length
NormalAnnotation natd = rewriter.getAST().newNormalAnnotation();
natd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_COLUMN));
ListRewrite lrw = rewriter.getListRewrite(node, FieldDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(natd, null);
MemberValuePair mvp = rewriter.getAST().newMemberValuePair();
mvp.setName(rewriter.getAST().newSimpleName("length")); //$NON-NLS-1$
NumberLiteral nl = rewriter.getAST().newNumberLiteral(String.valueOf(defaultStrLength));
mvp.setValue(nl);
natd.values().add(mvp);
}
}
}
if (type.isSimpleType() || type.isParameterizedType() || type.isArrayType()) {
Iterator<VariableDeclarationFragment> itVarNames = node.fragments().iterator();
String fieldId = ""; //$NON-NLS-1$
RefType refType = RefType.UNDEF;
boolean annotated = false;
String fullyQualifiedName2 = ""; //$NON-NLS-1$
while (itVarNames.hasNext()) {
VariableDeclarationFragment var = itVarNames.next();
String name = var.getName().getIdentifier();
fieldId = name;
refType = entityInfo.getFieldIdRelValue(fieldId);
annotated = entityInfo.getFieldIdAnnotatedValue(fieldId);
fullyQualifiedName2 = entityInfo.getFieldIdFQNameValue(fieldId);
if (refType != RefType.UNDEF) {
break;
}
}
Set<RefFieldInfo> setRFI = entityInfo.getRefFieldInfoSet(fullyQualifiedName2);
if (!annotated && setRFI != null && isSimilarType(type, fullyQualifiedName2)) {
RefEntityInfo rei = entityInfo.getFieldIdRefEntityInfo(fieldId);
// try to process bidirectional relationships:
// nRefType == JPAConst.ONE2ONE - OneToOne - the owning side corresponds
// to the side that contains the corresponding foreign key
// nRefType == JPAConst.MANY2ONE - ManyToOne - owning side is always the "many" side
// nRefType == JPAConst.MANY2MANY - ManyToMany bidirectional relationships
// either side may be the owning side
if (setRFI.size() > 1 && refType != RefType.MANY2ONE) {
if (rei.mappedBy == null || rei.mappedBy == "") { //$NON-NLS-1$
addSimpleMarkerAnnotation(node, JPAConst.getRefType(refType));
}
else {
// give to the user information about selected mapping
addComplexNormalAnnotation(node, JPAConst.getRefType(refType), rei);
}
}
else if (refType == RefType.MANY2ONE || refType == RefType.ENUMERATED ||
rei.mappedBy == null || rei.mappedBy == "") { //$NON-NLS-1$
addSimpleMarkerAnnotation(node, JPAConst.getRefType(refType));
}
else {
// in case of bidirectional OneToOne - mark both sides with mappedBy -
// user should select the right decision
addComplexNormalAnnotation(node, JPAConst.getRefType(refType), rei);
}
}
}
return true;
}
@SuppressWarnings("unchecked")
public boolean visit(MethodDeclaration node) {
if (entityInfo == null) {
return false;
}
if (annotationStyle != AnnotStyle.GETTERS) {
return true;
}
if (node.getName().getFullyQualifiedName().compareTo(entityInfo.getName()) == 0 || node.isConstructor()) {
// this is constructor declaration
return true;
}
// -) is it setter?
if (node.getName().getIdentifier().startsWith("set") //$NON-NLS-1$
&& node.parameters().size() == 1) {
// setter - do not process it
return true;
}
// +) is it getter?
if (!(node.getName().getIdentifier().startsWith("get") //$NON-NLS-1$
|| node.getName().getIdentifier().startsWith("is")) //$NON-NLS-1$
|| node.parameters().size() > 0) {
// not the getter - do not process it
return true;
}
Type type = node.getReturnType2();
if (type == null) {
return true;
}
String returnIdentifier = CollectEntityInfo.getReturnIdentifier(node);
if (type.isSimpleType() || type.isPrimitiveType()) {
if (entityInfo.isAddGeneratedValueFlag()) {
String primaryIdName = entityInfo.getPrimaryIdName();
boolean addGeneratedValueMarker = false;
if (primaryIdName.equals(returnIdentifier)) {
addGeneratedValueMarker = true;
}
if (addGeneratedValueMarker) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_GENERATED_VALUE));
ListRewrite lrw = rewriter.getListRewrite(node, MethodDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
}
if (entityInfo.isAddPrimaryIdFlag()) {
String primaryIdName = entityInfo.getPrimaryIdName();
boolean addIdMarker = false;
if (primaryIdName.equals(returnIdentifier)) {
addIdMarker = true;
}
if (addIdMarker) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_ID));
ListRewrite lrw = rewriter.getListRewrite(node, MethodDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
}
if (enableOptLock && entityInfo.isAddVersionFlag() && !entityInfo.hasVersionAnnotation()) {
boolean addVersionMarker = false;
if ("version".equals(returnIdentifier)) { //$NON-NLS-1$
addVersionMarker = true;
}
if (addVersionMarker) {
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_VERSION));
ListRewrite lrw = rewriter.getListRewrite(node, MethodDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(matd, null);
}
}
}
if (type.isSimpleType() && (AllEntitiesProcessor.columnLength != defaultStrLength)) {
SimpleType simpleType = (SimpleType)type;
String typeName = simpleType.getName().getFullyQualifiedName();
if ("java.lang.String".equals(typeName) || "String".equals(typeName)) { //$NON-NLS-1$ //$NON-NLS-2$
String fieldId = returnIdentifier;
RefColumnInfo rci = entityInfo.getRefColumnInfo(fieldId);
if (rci == null || !rci.isExist()) {
// if there is no @Column annotation - create new @Column annotation
// with user defined default value length
NormalAnnotation natd = rewriter.getAST().newNormalAnnotation();
natd.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_COLUMN));
ListRewrite lrw = rewriter.getListRewrite(node, MethodDeclaration.MODIFIERS2_PROPERTY);
lrw.insertFirst(natd, null);
MemberValuePair mvp = rewriter.getAST().newMemberValuePair();
mvp.setName(rewriter.getAST().newSimpleName("length")); //$NON-NLS-1$
NumberLiteral nl = rewriter.getAST().newNumberLiteral(String.valueOf(defaultStrLength));
mvp.setValue(nl);
natd.values().add(mvp);
}
}
}
if (type.isSimpleType() || type.isParameterizedType() || type.isArrayType()) {
String fieldId = ""; //$NON-NLS-1$
RefType refType = RefType.UNDEF;
boolean annotated = false;
String fullyQualifiedName2 = ""; //$NON-NLS-1$
fieldId = returnIdentifier;
refType = entityInfo.getFieldIdRelValue(fieldId);
annotated = entityInfo.getFieldIdAnnotatedValue(fieldId);
fullyQualifiedName2 = entityInfo.getFieldIdFQNameValue(fieldId);
Set<RefFieldInfo> setRFI = entityInfo.getRefFieldInfoSet(fullyQualifiedName2);
if (!annotated && setRFI != null && isSimilarType(type, fullyQualifiedName2)) {
RefEntityInfo rei = entityInfo.getFieldIdRefEntityInfo(fieldId);
// try to process bidirectional relationships:
// nRefType == JPAConst.ONE2ONE - OneToOne - the owning side corresponds
// to the side that contains the corresponding foreign key
// nRefType == JPAConst.MANY2ONE - ManyToOne - owning side is always the "many" side
// nRefType == JPAConst.MANY2MANY - ManyToMany bidirectional relationships
// either side may be the owning side
if (setRFI.size() > 1 && refType != RefType.MANY2ONE) {
if (rei.mappedBy == null || rei.mappedBy == "") { //$NON-NLS-1$
addSimpleMarkerAnnotation(node, JPAConst.getRefType(refType));
}
else {
// give to the user information about selected mapping
addComplexNormalAnnotation(node, JPAConst.getRefType(refType), rei);
}
}
else if (refType == RefType.MANY2ONE || refType == RefType.ENUMERATED ||
rei.mappedBy == null || rei.mappedBy == "") { //$NON-NLS-1$
addSimpleMarkerAnnotation(node, JPAConst.getRefType(refType));
}
else {
// in case of bidirectional OneToOne - mark both sides with mappedBy -
// user should select the right decision
addComplexNormalAnnotation(node, JPAConst.getRefType(refType), rei);
}
}
}
return true;
}
// simple type name check
public boolean isSimilarType(Type type, String fullyQualifiedName) {
String typeName = null;
if (type.isSimpleType()) {
SimpleType st = (SimpleType)type;
typeName = st.getName().getFullyQualifiedName();
}
else if (type.isArrayType()) {
ArrayType at = (ArrayType)type;
Type elementType = at.getElementType();
if (elementType.isSimpleType()) {
SimpleType st = (SimpleType)elementType;
typeName = st.getName().getFullyQualifiedName();
}
}
if (typeName != null && fullyQualifiedName.indexOf(typeName) == -1) {
return false;
}
return true;
}
public boolean addSimpleMarkerAnnotation(BodyDeclaration node, String name) {
if (name == null || name.length() == 0) {
return false;
}
MarkerAnnotation matd = rewriter.getAST().newMarkerAnnotation();
matd.setTypeName(rewriter.getAST().newSimpleName(name));
ListRewrite lrw = null;
if (node instanceof FieldDeclaration) {
lrw = rewriter.getListRewrite(node, FieldDeclaration.MODIFIERS2_PROPERTY);
}
else if (node instanceof MethodDeclaration) {
lrw = rewriter.getListRewrite(node, MethodDeclaration.MODIFIERS2_PROPERTY);
}
if (lrw != null) {
lrw.insertFirst(matd, null);
}
return true;
}
@SuppressWarnings("unchecked")
public boolean addComplexNormalAnnotation(BodyDeclaration node, String name, RefEntityInfo rei) {
if (name == null || name.length() == 0) {
return false;
}
NormalAnnotation natd = rewriter.getAST().newNormalAnnotation();
MemberValuePair mvp = null;
if (rei.mappedBy != null && (rei.owner == OwnerType.YES ||
rei.owner == OwnerType.UNDEF)) {
mvp = rewriter.getAST().newMemberValuePair();
mvp.setName(rewriter.getAST().newSimpleName("mappedBy")); //$NON-NLS-1$
StringLiteral sl = rewriter.getAST().newStringLiteral();
sl.setLiteralValue(rei.mappedBy);
mvp.setValue(sl);
}
natd.setTypeName(rewriter.getAST().newSimpleName(name));
if (mvp != null) {
natd.values().add(mvp);
}
NormalAnnotation natd2 = null;
/** /
if (rei.owner == OwnerType.NO) {
natd2 = rewriter.getAST().newNormalAnnotation();
natd2.setTypeName(rewriter.getAST().newSimpleName(JPAConst.ANNOTATION_JOINCOLUMN));
mvp = null;
String fullyQualifiedName2 = rei.fullyQualifiedName;
EntityInfo entryInfo2 = entities.get(fullyQualifiedName2);
if (entryInfo2 != null) {
mvp = rewriter.getAST().newMemberValuePair();
mvp.setName(rewriter.getAST().newSimpleName("name")); //$NON-NLS-1$
StringLiteral sl = rewriter.getAST().newStringLiteral();
sl.setLiteralValue(entryInfo2.getPrimaryIdName());
mvp.setValue(sl);
}
if (mvp != null) {
natd2.values().add(mvp);
}
}
/**/
ListRewrite lrw = null;
if (node instanceof FieldDeclaration) {
lrw = rewriter.getListRewrite(node, FieldDeclaration.MODIFIERS2_PROPERTY);
}
else if (node instanceof MethodDeclaration) {
lrw = rewriter.getListRewrite(node, MethodDeclaration.MODIFIERS2_PROPERTY);
}
if (lrw != null) {
if (natd2 != null) {
lrw.insertFirst(natd2, null);
}
lrw.insertFirst(natd, null);
}
return true;
}
public AnnotStyle getAnnotationStyle() {
return annotationStyle;
}
public void setAnnotationStyle(AnnotStyle annotationStyle) {
this.annotationStyle = annotationStyle;
}
public int getDefaultStrLength() {
return defaultStrLength;
}
public void setDefaultStrLength(int defaultStrLength) {
this.defaultStrLength = defaultStrLength;
}
public boolean getEnableOptLock() {
return enableOptLock;
}
public void setEnableOptLock(boolean enableOptLock) {
this.enableOptLock = enableOptLock;
}
}