/******************************************************************************* * 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; } }