/*******************************************************************************
* 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.collect;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.hibernate.eclipse.jdt.ui.internal.jpa.common.EntityInfo;
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.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.Utils;
import org.hibernate.eclipse.jdt.ui.internal.jpa.process.AnnotStyle;
/**
* Collect information about JPA entity and it's dependences.
*
* @author Vitali Yemialyanchyk
*/
public class AllEntitiesInfoCollector {
/**
* map:
* javaProjectName + "/" + fullyQualifiedName entity name -> EntityInfo
* this collection of processed entities
*/
protected Map<String, EntityInfo> mapCUs_Info = new TreeMap<String, EntityInfo>();
/**
* annotation style preference
*/
protected AnnotStyle annotationStylePreference = AnnotStyle.FIELDS;
public void initCollector() {
// clear collection
mapCUs_Info.clear();
}
/**
* pair of 2 particular fields from 2 particular entities
*/
static protected class ProcessItem {
// field names
public String fieldId = null;
public String fieldId2 = null;
// information about field from both entities
public RefEntityInfo refEntityInfo = null;
public RefEntityInfo refEntityInfo2 = null;
}
/**
* abstract interface for connection of entities
*/
protected abstract class IConnector {
/**
* object for processing
*/
protected ProcessItem pi;
public void setProcessItem(ProcessItem processItem) {
this.pi = processItem;
}
public abstract boolean updateRelation();
}
/**
* responsible for enumeration all entities pairs which
* succeed in recognize
*/
protected class EntityProcessor {
protected IConnector connector;
public void setConnector(IConnector connector) {
this.connector = connector;
}
/**
* enumerate function
*/
public void enumEntityPairs() {
Iterator<Map.Entry<String, EntityInfo>> it = mapCUs_Info.entrySet().iterator();
ProcessItem pi = new ProcessItem();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
// entry.getKey() - fully qualified name
// entry.getValue() - EntityInfo
EntityInfo entryInfo = entry.getValue();
String fullyQualifiedName = entryInfo.getFullyQualifiedName();
String javaProjectName = entryInfo.getJavaProjectName();
assert(entry.getKey().equals(javaProjectName + "/" + fullyQualifiedName)); //$NON-NLS-1$
// get references map:
// * field id -> RefEntityInfo
Iterator<Map.Entry<String, RefEntityInfo>> referencesIt =
entryInfo.getReferences().entrySet().iterator();
while (referencesIt.hasNext()) {
Map.Entry<String, RefEntityInfo> entry2 = referencesIt.next();
// entry2.getKey() - field id
// entry2.getValue() - RefEntityInfo
pi.fieldId = entry2.getKey();
pi.refEntityInfo = entry2.getValue();
String fullyQualifiedName2 = pi.refEntityInfo.fullyQualifiedName;
EntityInfo entryInfo2 = mapCUs_Info.get(javaProjectName + "/" + fullyQualifiedName2); //$NON-NLS-1$
assert(fullyQualifiedName2.equals(entryInfo2.getFullyQualifiedName()));
if (entryInfo2 != null && pi.refEntityInfo != null) {
pi.refEntityInfo2 = null;
pi.fieldId2 = null;
Set<RefFieldInfo> setRefEntityInfo = entryInfo2.getRefFieldInfoSet(fullyQualifiedName);
if (setRefEntityInfo != null) {
if (setRefEntityInfo.size() == 1) {
Iterator<RefFieldInfo> itTmp = setRefEntityInfo.iterator();
RefFieldInfo rfi = itTmp.next();
pi.fieldId2 = rfi.fieldId;
pi.refEntityInfo2 = entryInfo2.getFieldIdRefEntityInfo(pi.fieldId2);
}
else if (setRefEntityInfo.size() > 1) {
// this case of complex decision - omit this,
// give other entities opportunity to solve this.
// in case of no solution - user should define this himself
pi.refEntityInfo2 = null;
}
}
if (connector != null) {
connector.setProcessItem(pi);
connector.updateRelation();
}
}
}
}
}
}
public void updateOwner(ProcessItem pi) {
if (pi.refEntityInfo.refType == RefType.ONE2ONE) {
//pi.refEntityInfo.owner = OwnerType.UNDEF;
//pi.refEntityInfo2.owner = OwnerType.UNDEF;
if ((pi.refEntityInfo.owner == OwnerType.UNDEF &&
pi.refEntityInfo2.owner == OwnerType.UNDEF) ||
(pi.refEntityInfo.owner == OwnerType.YES &&
pi.refEntityInfo2.owner == OwnerType.YES) ||
(pi.refEntityInfo.owner == OwnerType.NO &&
pi.refEntityInfo2.owner == OwnerType.NO))
{
// this is the ambiguous case
// TODO: this is temporary solution for GA
// select owner in lexicographical order
if (pi.refEntityInfo.fullyQualifiedName.compareTo(
pi.refEntityInfo2.fullyQualifiedName) > 0) {
pi.refEntityInfo.owner = OwnerType.YES;
pi.refEntityInfo2.owner = OwnerType.NO;
}
else {
pi.refEntityInfo.owner = OwnerType.NO;
pi.refEntityInfo2.owner = OwnerType.YES;
}
}
else if (pi.refEntityInfo.owner == OwnerType.UNDEF ||
pi.refEntityInfo2.owner == OwnerType.UNDEF) {
if (pi.refEntityInfo.owner == OwnerType.YES) {
pi.refEntityInfo2.owner = OwnerType.NO;
}
else if (pi.refEntityInfo.owner == OwnerType.NO) {
pi.refEntityInfo2.owner = OwnerType.YES;
}
else if (pi.refEntityInfo2.owner == OwnerType.YES) {
pi.refEntityInfo.owner = OwnerType.NO;
}
else if (pi.refEntityInfo2.owner == OwnerType.NO) {
pi.refEntityInfo.owner = OwnerType.YES;
}
}
}
else if (pi.refEntityInfo.refType == RefType.ONE2MANY) {
pi.refEntityInfo.owner = OwnerType.YES;
pi.refEntityInfo2.owner = OwnerType.NO;
}
else if (pi.refEntityInfo.refType == RefType.MANY2ONE) {
pi.refEntityInfo.owner = OwnerType.NO;
pi.refEntityInfo2.owner = OwnerType.YES;
}
else if (pi.refEntityInfo.refType == RefType.MANY2MANY) {
//pi.refEntityInfo.owner = OwnerType.UNDEF;
//pi.refEntityInfo2.owner = OwnerType.UNDEF;
if ((pi.refEntityInfo.owner == OwnerType.UNDEF &&
pi.refEntityInfo2.owner == OwnerType.UNDEF) ||
(pi.refEntityInfo.owner == OwnerType.YES &&
pi.refEntityInfo2.owner == OwnerType.YES) ||
(pi.refEntityInfo.owner == OwnerType.NO &&
pi.refEntityInfo2.owner == OwnerType.NO))
{
// this is the ambiguous case
// TODO: this is temporary solution for GA
// select owner in lexicographical order
if (pi.refEntityInfo.fullyQualifiedName.compareTo(
pi.refEntityInfo2.fullyQualifiedName) > 0) {
pi.refEntityInfo.owner = OwnerType.YES;
pi.refEntityInfo2.owner = OwnerType.NO;
}
else {
pi.refEntityInfo.owner = OwnerType.NO;
pi.refEntityInfo2.owner = OwnerType.YES;
}
}
else if (pi.refEntityInfo.owner == OwnerType.UNDEF ||
pi.refEntityInfo2.owner == OwnerType.UNDEF) {
if (pi.refEntityInfo.owner == OwnerType.YES) {
pi.refEntityInfo2.owner = OwnerType.NO;
}
else if (pi.refEntityInfo.owner == OwnerType.NO) {
pi.refEntityInfo2.owner = OwnerType.YES;
}
else if (pi.refEntityInfo2.owner == OwnerType.YES) {
pi.refEntityInfo.owner = OwnerType.NO;
}
else if (pi.refEntityInfo2.owner == OwnerType.NO) {
pi.refEntityInfo.owner = OwnerType.YES;
}
}
}
}
/**
* responsible for enumeration all entities pairs and
* setup relations between single candidate for several items case
*/
protected class EntitySingleCandidateResolver {
/**
* enumerate function
*/
public void enumEntityPairs() {
Iterator<Map.Entry<String, EntityInfo>> it = mapCUs_Info.entrySet().iterator();
ProcessItem pi = new ProcessItem();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
// entry.getKey() - fully qualified name
// entry.getValue() - EntityInfo
EntityInfo entryInfo = entry.getValue();
String fullyQualifiedName = entryInfo.getFullyQualifiedName();
String javaProjectName = entryInfo.getJavaProjectName();
assert(entry.getKey().equals(javaProjectName + "/" + fullyQualifiedName)); //$NON-NLS-1$
// get references map:
// * field id -> RefEntityInfo
Iterator<Map.Entry<String, RefEntityInfo>> referencesIt =
entryInfo.getReferences().entrySet().iterator();
while (referencesIt.hasNext()) {
Map.Entry<String, RefEntityInfo> entry2 = referencesIt.next();
// entry2.getKey() - field id
// entry2.getValue() - RefEntityInfo
pi.fieldId = entry2.getKey();
pi.refEntityInfo = entry2.getValue();
String fullyQualifiedName2 = pi.refEntityInfo.fullyQualifiedName;
EntityInfo entryInfo2 = mapCUs_Info.get(javaProjectName + "/" + fullyQualifiedName2); //$NON-NLS-1$
assert(fullyQualifiedName2.equals(entryInfo2.getFullyQualifiedName()));
if (entryInfo2 != null && pi.refEntityInfo != null) {
pi.refEntityInfo2 = null;
pi.fieldId2 = null;
Set<RefFieldInfo> setRefEntityInfo = entryInfo2.getRefFieldInfoSet(fullyQualifiedName);
if (setRefEntityInfo != null && setRefEntityInfo.size() > 1) {
// this case of complex decision - but if there is 1 candidate
// it is possible to select this candidate automatically
// in case of no solution - user should define this himself
// try to find 1 suitable candidate
RefType suitableRefType = RefType.UNDEF;
if (pi.refEntityInfo.refType == RefType.ONE2ONE) {
suitableRefType = RefType.ONE2ONE;
}
else if (pi.refEntityInfo.refType == RefType.ONE2MANY) {
suitableRefType = RefType.MANY2ONE;
}
else if (pi.refEntityInfo.refType == RefType.MANY2ONE) {
suitableRefType = RefType.ONE2MANY;
}
else if (pi.refEntityInfo.refType == RefType.MANY2MANY) {
suitableRefType = RefType.MANY2MANY;
}
RefFieldInfo rfiSingleCandidat = null;
Iterator<RefFieldInfo> itTmp = setRefEntityInfo.iterator();
while (itTmp.hasNext()) {
RefFieldInfo rfi = itTmp.next();
if (rfi.refType == suitableRefType) {
if (rfiSingleCandidat == null) {
rfiSingleCandidat = rfi;
}
else {
// there are a least 2 candidates
break;
}
}
}
if (!itTmp.hasNext() && rfiSingleCandidat != null) {
pi.fieldId2 = rfiSingleCandidat.fieldId;
pi.refEntityInfo2 = entryInfo2.getFieldIdRefEntityInfo(pi.fieldId2);
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
}
}
}
}
}
}
public boolean hasMappedSuperclassVersion(String javaProjectName, String parentName) {
if (parentName == null) {
return false;
}
EntityInfo entryInfoParent = mapCUs_Info.get(javaProjectName + "/" + parentName); //$NON-NLS-1$
if (entryInfoParent == null) {
return false;
}
if (entryInfoParent.isAddMappedSuperclassFlag() ||
entryInfoParent.hasMappedSuperclassAnnotation()) {
return true;
}
return false;
}
/**
* process all entities pairs iteratively:
* firstly process pairs with more information about and
* pairs with small information about - process in last order
*/
public void resolveRelations() {
Iterator<Map.Entry<String, EntityInfo>> it = null;
// resolve parent/child relations
// in the case if a child has a @MappedSuperclass parent with version property
// we shouldn't add version property to the child
it = mapCUs_Info.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
EntityInfo entityInfo = entry.getValue();
String javaProjectName = entityInfo.getJavaProjectName();
String parentName = entityInfo.getFullyQualifiedParentName();
if (hasMappedSuperclassVersion(javaProjectName, parentName)) {
entityInfo.setAddVersionFlag(false);
}
else {
entityInfo.setAddVersionFlag(true);
}
entityInfo.updateVersionImport(entityInfo.isAddVersionFlag());
}
//
// resolve connection relations
int fromVariableCounter = 0;
int fromMethodCounter = 0;
// generate RefFieldInfoMap (for simple process)
it = mapCUs_Info.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
EntityInfo entryInfo = entry.getValue();
entryInfo.generateRefFieldInfoMap();
fromVariableCounter += entryInfo.getFromVariableCounter();
fromMethodCounter += entryInfo.getFromMethodCounter();
}
if (fromVariableCounter >= fromMethodCounter) {
annotationStylePreference = AnnotStyle.FIELDS;
}
else {
annotationStylePreference = AnnotStyle.GETTERS;
}
// update relations
EntityProcessor ep = new EntityProcessor();
// 0)
// process the user prompts
IConnector promptsConnector = new IConnector() {
public boolean updateRelation() {
if (pi == null) {
return false;
}
if (pi.refEntityInfo == null || pi.refEntityInfo2 == null) {
return false;
}
int hasPrompt = 0; // no user prompt
// - use it as prompting from the user
if ((pi.fieldId != null && pi.fieldId.equals(pi.refEntityInfo2.mappedBy))) {
hasPrompt |= 1;
}
if ((pi.fieldId2 != null && pi.fieldId2.equals(pi.refEntityInfo.mappedBy))) {
hasPrompt |= 2;
}
if (hasPrompt != 0) {
// remember: in case of incorrect user prompts - we proceed his suggestions
if (hasPrompt == 1) {
if (pi.refEntityInfo2.refType == RefType.ONE2ONE) {
pi.refEntityInfo.refType = RefType.ONE2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.ONE2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
else if (pi.refEntityInfo2.refType == RefType.ONE2MANY) {
pi.refEntityInfo.refType = RefType.MANY2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.ONE2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
else if (pi.refEntityInfo2.refType == RefType.MANY2ONE) {
pi.refEntityInfo.refType = RefType.ONE2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.MANY2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
else if (pi.refEntityInfo2.refType == RefType.MANY2MANY) {
pi.refEntityInfo.refType = RefType.MANY2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.MANY2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
}
else if (hasPrompt == 2) {
if (pi.refEntityInfo.refType == RefType.ONE2ONE) {
pi.refEntityInfo.refType = RefType.ONE2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId;
pi.refEntityInfo2.refType = RefType.ONE2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId2;
updateOwner(pi);
}
else if (pi.refEntityInfo.refType == RefType.ONE2MANY) {
pi.refEntityInfo.refType = RefType.ONE2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId;
pi.refEntityInfo2.refType = RefType.MANY2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId2;
updateOwner(pi);
}
else if (pi.refEntityInfo.refType == RefType.MANY2ONE) {
pi.refEntityInfo.refType = RefType.MANY2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId;
pi.refEntityInfo2.refType = RefType.ONE2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId2;
updateOwner(pi);
}
else if (pi.refEntityInfo.refType == RefType.MANY2MANY) {
pi.refEntityInfo.refType = RefType.MANY2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId;
pi.refEntityInfo2.refType = RefType.MANY2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId2;
updateOwner(pi);
}
}
//if (hasPrompt == 3) - this is case where we get prompt from both sides -
// and it is possible this is not correct info... so try to adjust it.
if (pi.refEntityInfo.refType == RefType.ONE2ONE) {
if (pi.refEntityInfo2.refType == RefType.ONE2ONE) {
pi.refEntityInfo.refType = RefType.ONE2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.ONE2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
else if (pi.refEntityInfo2.refType == RefType.ONE2MANY) {
pi.refEntityInfo.refType = RefType.MANY2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.ONE2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
}
else if (pi.refEntityInfo.refType == RefType.ONE2MANY) {
if (pi.refEntityInfo2.refType == RefType.ONE2ONE) {
pi.refEntityInfo.refType = RefType.ONE2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.MANY2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
else if (pi.refEntityInfo2.refType == RefType.ONE2MANY) {
pi.refEntityInfo.refType = RefType.MANY2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.MANY2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
}
}
return true;
}
};
ep.setConnector(promptsConnector);
ep.enumEntityPairs();
// prefer other mapping type to ManyToMany, so
// 1)
// first - try to assign other relations
IConnector simpleRelConnector = new IConnector() {
public boolean updateRelation() {
if (pi == null) {
return false;
}
if (pi.refEntityInfo == null || pi.refEntityInfo2 == null) {
return false;
}
if (pi.refEntityInfo.mappedBy == null && pi.refEntityInfo2.mappedBy == null) {
if (pi.refEntityInfo.refType == RefType.ONE2ONE) {
if (pi.refEntityInfo2.refType == RefType.ONE2ONE) {
pi.refEntityInfo.refType = RefType.ONE2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.ONE2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
else if (pi.refEntityInfo2.refType == RefType.ONE2MANY) {
pi.refEntityInfo.refType = RefType.MANY2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.ONE2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
}
else if (pi.refEntityInfo.refType == RefType.ONE2MANY) {
if (pi.refEntityInfo2.refType == RefType.ONE2ONE) {
pi.refEntityInfo.refType = RefType.ONE2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.MANY2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
else if (pi.refEntityInfo2.refType == RefType.MANY2ONE) {
pi.refEntityInfo.refType = RefType.ONE2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.MANY2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
}
else if (pi.refEntityInfo.refType == RefType.MANY2ONE) {
if (pi.refEntityInfo2.refType == RefType.ONE2MANY) {
pi.refEntityInfo.refType = RefType.MANY2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.ONE2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
else if (pi.refEntityInfo2.refType == RefType.MANY2ONE) {
pi.refEntityInfo.refType = RefType.ONE2ONE;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.ONE2ONE;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
}
}
return true;
}
};
ep.setConnector(simpleRelConnector);
ep.enumEntityPairs();
// 2)
// second - try to assign - ManyToMany
// remember - here prefer other mapping type to ManyToMany
IConnector m2mRelConnector = new IConnector() {
public boolean updateRelation() {
if (pi == null) {
return false;
}
if (pi.refEntityInfo == null || pi.refEntityInfo2 == null) {
return false;
}
if (pi.refEntityInfo.mappedBy == null && pi.refEntityInfo2.mappedBy == null) {
if (pi.refEntityInfo.refType == RefType.ONE2MANY) {
if (pi.refEntityInfo2.refType == RefType.ONE2MANY) {
if (pi.refEntityInfo2.mappedBy == null) {
pi.refEntityInfo.refType = RefType.MANY2MANY;
pi.refEntityInfo.mappedBy = pi.fieldId2;
pi.refEntityInfo2.refType = RefType.MANY2MANY;
pi.refEntityInfo2.mappedBy = pi.fieldId;
updateOwner(pi);
}
}
}
}
return true;
}
};
ep.setConnector(m2mRelConnector);
ep.enumEntityPairs();
// 3)
// third - try to assign - "single candidates"
EntitySingleCandidateResolver escr = new EntitySingleCandidateResolver();
escr.enumEntityPairs();
// update import flags
it = mapCUs_Info.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
EntityInfo entryInfo = entry.getValue();
Iterator<Map.Entry<String, RefEntityInfo>> referencesIt =
entryInfo.getReferences().entrySet().iterator();
boolean isOne2One = false;
boolean isOne2Many = false;
boolean isMany2One = false;
boolean isMany2Many = false;
boolean isEnumerated = false;
for ( ; referencesIt.hasNext(); ) {
Map.Entry<String, RefEntityInfo> entry2 = referencesIt.next();
RefEntityInfo refEntityInfo = entry2.getValue();
if (refEntityInfo != null) {
if (refEntityInfo.refType == RefType.ONE2ONE && !refEntityInfo.resolvedAnnotationName) {
isOne2One = true;
}
else if (refEntityInfo.refType == RefType.ONE2MANY && !refEntityInfo.resolvedAnnotationName) {
isOne2Many = true;
}
else if (refEntityInfo.refType == RefType.MANY2ONE && !refEntityInfo.resolvedAnnotationName) {
isMany2One = true;
}
else if (refEntityInfo.refType == RefType.MANY2MANY && !refEntityInfo.resolvedAnnotationName) {
isMany2Many = true;
}
else if (refEntityInfo.refType == RefType.ENUMERATED && !refEntityInfo.resolvedAnnotationName) {
isEnumerated = true;
}
}
}
if (isOne2One) {
entryInfo.addRequiredImport(JPAConst.IMPORT_ONE2ONE);
}
if (isOne2Many) {
entryInfo.addRequiredImport(JPAConst.IMPORT_ONE2MANY);
}
if (isMany2One) {
entryInfo.addRequiredImport(JPAConst.IMPORT_MANY2ONE);
}
if (isMany2Many) {
entryInfo.addRequiredImport(JPAConst.IMPORT_MANY2MANY);
}
if (isEnumerated) {
entryInfo.addRequiredImport(JPAConst.IMPORT_ENUMERATED);
}
}
// re-generate RefFieldInfoMap (for simple process)
it = mapCUs_Info.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
EntityInfo entryInfo = entry.getValue();
entryInfo.generateRefFieldInfoMap();
}
// if the parent has primary id - child should not generate it
it = mapCUs_Info.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
EntityInfo entryInfo = entry.getValue();
adjustParentId(entryInfo);
}
}
public void adjustParentId(EntityInfo ei) {
if (ei == null) {
return;
}
EntityInfo parentEI = mapCUs_Info.get(ei.getJavaProjectName() + "/" + ei.getFullyQualifiedParentName()); //$NON-NLS-1$
adjustParentId(parentEI);
ei.adjustPrimaryId(parentEI);
}
/**
* start to collect information from particular entity class and
* its dependencies
* @param fullyQualifiedName of startup point entity fully qualified name
* example: "org.hibernate.eclipse.jdt.ui.internal.jpa.collect.AllEntitiesInfoCollector"
*/
public void collect(String fullyQualifiedName, String projectName, int depth) {
if (fullyQualifiedName == null || depth < 0) {
return;
}
if (mapCUs_Info.containsKey(projectName + "/" + fullyQualifiedName)) { //$NON-NLS-1$
return;
}
final IJavaProject javaProject = Utils.findJavaProject(projectName);
ICompilationUnit icu = Utils.findCompilationUnit(javaProject, fullyQualifiedName);
collect(icu, depth);
}
/**
* start to collect information from particular entity class and
* its dependencies
* @param icu - startup point entity compilation unit
* @param depth - process depth
*/
public void collect(ICompilationUnit icu, int depth) {
if (icu == null || depth < 0) {
return;
}
org.eclipse.jdt.core.dom.CompilationUnit cu = Utils.getCompilationUnit(icu, true);
if (cu == null) {
return;
}
if (cu.types() == null || cu.types().size() == 0 ) {
return;
}
boolean hasTypeDeclaration = false;
Iterator<?> it = cu.types().iterator();
while (it.hasNext()) {
Object tmp = it.next();
if (tmp instanceof TypeDeclaration) {
hasTypeDeclaration = true;
break;
}
}
if (!hasTypeDeclaration) {
// ignore EnumDeclaration & AnnotationTypeDeclaration
return;
}
IJavaProject javaProject = icu.getJavaProject();
String projectName = (javaProject != null) ? javaProject.getProject().getName() : ""; //$NON-NLS-1$
ArrayList<String> fullyQualifiedNames = new ArrayList<String>();
//TODO: should inspect all types in cu? so next method to get fullyQualifiedName:
if (cu.getTypeRoot() == null || cu.getTypeRoot().findPrimaryType() == null) {
it = cu.types().iterator();
while (it.hasNext()) {
Object tmp = it.next();
if (tmp instanceof TypeDeclaration) {
fullyQualifiedNames.add(((TypeDeclaration)tmp).resolveBinding().getBinaryName());
}
}
} else {
fullyQualifiedNames.add(cu.getTypeRoot().findPrimaryType().getFullyQualifiedName());
}
Iterator<String> itFQNames = fullyQualifiedNames.iterator();
while (itFQNames.hasNext()) {
String fullyQualifiedName = itFQNames.next();
if (!mapCUs_Info.containsKey(projectName + "/" + fullyQualifiedName)) { //$NON-NLS-1$
CollectEntityInfo finder = new CollectEntityInfo(fullyQualifiedName);
cu.accept(finder);
EntityInfo result = finder.getEntityInfo();
if (result != null) {
result.adjustParameters();
result.setJavaProjectName(projectName);
mapCUs_Info.put(projectName + "/" + fullyQualifiedName, result); //$NON-NLS-1$
if (depth > 0) {
Iterator<String> itDep = result.getDependences();
while (itDep.hasNext()) {
String fullyQualifiedNameTmp = itDep.next();
collect(fullyQualifiedNameTmp, projectName, depth - 1);
}
}
}
}
}
}
/**
* collection of processed entities getter
*/
public Map<String, EntityInfo> getMapCUs_Info() {
return mapCUs_Info;
}
public int getNonAbstractCUNumber() {
Iterator<Map.Entry<String, EntityInfo>> it = null;
int nonAbstractCUNumber = 0;
// generate RefFieldInfoMap (for simple process)
it = mapCUs_Info.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
EntityInfo entryInfo = entry.getValue();
if (!entryInfo.isAbstractFlag()) {
nonAbstractCUNumber++;
}
}
return nonAbstractCUNumber;
}
public int getNonInterfaceCUNumber() {
Iterator<Map.Entry<String, EntityInfo>> it = null;
int nonInterfaceCUNumber = 0;
// generate RefFieldInfoMap (for simple process)
it = mapCUs_Info.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, EntityInfo> entry = it.next();
EntityInfo entryInfo = entry.getValue();
if (!entryInfo.isInterfaceFlag()) {
nonInterfaceCUNumber++;
}
}
return nonInterfaceCUNumber;
}
public AnnotStyle getAnnotationStylePreference() {
return annotationStylePreference;
}
}