/** * <copyright> * * Copyright (c) 2009, 2010 Springsite BV (The Netherlands) and others * All rights reserved. This program and the accompanying materials * are 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 * * Contributors: * Martin Taal - Initial API and implementation * * </copyright> * * $Id: EReferenceORMAnnotator.java,v 1.20 2011/08/26 05:34:12 mtaal Exp $ */ package org.eclipse.emf.texo.orm.annotator; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.texo.generator.Annotator; import org.eclipse.emf.texo.generator.GeneratorUtils; import org.eclipse.emf.texo.modelgenerator.annotator.GenUtils; import org.eclipse.emf.texo.modelgenerator.modelannotations.EReferenceModelGenAnnotation; import org.eclipse.emf.texo.modelgenerator.modelannotations.ModelcodegeneratorPackage; import org.eclipse.emf.texo.orm.annotations.model.orm.AccessType; import org.eclipse.emf.texo.orm.annotations.model.orm.CollectionTable; import org.eclipse.emf.texo.orm.annotations.model.orm.ElementCollection; import org.eclipse.emf.texo.orm.annotations.model.orm.Embedded; import org.eclipse.emf.texo.orm.annotations.model.orm.JoinColumn; import org.eclipse.emf.texo.orm.annotations.model.orm.JoinTable; import org.eclipse.emf.texo.orm.annotations.model.orm.ManyToMany; import org.eclipse.emf.texo.orm.annotations.model.orm.ManyToOne; import org.eclipse.emf.texo.orm.annotations.model.orm.MapKeyColumn; import org.eclipse.emf.texo.orm.annotations.model.orm.OneToMany; import org.eclipse.emf.texo.orm.annotations.model.orm.OneToOne; import org.eclipse.emf.texo.orm.annotations.model.orm.OrderColumn; import org.eclipse.emf.texo.orm.annotations.model.orm.OrmFactory; import org.eclipse.emf.texo.orm.annotations.model.orm.UniqueConstraint; import org.eclipse.emf.texo.orm.ormannotations.EClassORMAnnotation; import org.eclipse.emf.texo.orm.ormannotations.EPackageORMAnnotation; import org.eclipse.emf.texo.orm.ormannotations.EReferenceORMAnnotation; import org.eclipse.emf.texo.orm.ormannotations.OrmannotationsPackage; import org.eclipse.emf.texo.utils.ModelUtils; /** * Responsible for creating the {@link EReferenceORMAnnotation}. * * @author <a href="mailto:mtaal@elver.org">Martin Taal</a> * @version $Revision: 1.20 $ */ public class EReferenceORMAnnotator extends EStructuralFeatureORMAnnotator implements Annotator<EReferenceORMAnnotation> { /* * (non-Javadoc) * * @see org.eclipse.emf.texo.generator.Annotator#annotate(org.eclipse.emf.texo.annotations.annotationsmodel * .ENamedElementAnnotation) */ public void setAnnotationFeatures(EReferenceORMAnnotation annotation) { // don't do anything anymore if transient if (annotation.getTransient() != null) { if (GeneratorUtils.isEmptyOrNull(annotation.getTransient().getName())) { annotation.getTransient().setName(getName(annotation.getEReference())); } return; } final EReference eReference = annotation.getEReference(); final EClass eClass = eReference.getEContainingClass(); if (GenUtils.isDocumentRoot(eClass)) { return; } final EPackage ePackage = eReference.getEContainingClass().getEPackage(); final EPackageORMAnnotation ePackageORMAnnotation = (EPackageORMAnnotation) getAnnotationManager().getAnnotation( ePackage, OrmannotationsPackage.eINSTANCE.getEPackageORMAnnotation()); final EReferenceModelGenAnnotation eReferenceModelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eReference, ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); // features which are part of a featuremap are never mapped as many features final boolean isPartOfFeatureMap = GeneratorUtils.isPartOfGroup(annotation.getEReference()); final EReference eOpposite = eReference.getEOpposite(); if (!isPartOfFeatureMap && eReference.isMany()) { if (doAddConverter(eReferenceModelGenAnnotation) || annotation.getEmbedded() != null) { addElementCollection(annotation); } else if (annotation.getElementCollection() != null) { annotateElementCollection(annotation); } else if (ModelUtils.isEMap(annotation.getEReference().getEReferenceType())) { mapMap(annotation); } else if (eOpposite != null && eOpposite.isMany()) { annotateManyToMany(annotation); } else if (eOpposite != null && !eOpposite.isMany()) { annotateOneToMany(annotation); } else if (eReference.isContainment() || annotation.getOneToMany() != null || !ePackageORMAnnotation.isUseJoinTablesForNonContainment()) { annotateOneToMany(annotation); } else { annotateManyToMany(annotation); } } else { final EClass referencedEClass = eReference.getEReferenceType(); final EClassORMAnnotation referencedEClassORMAnnotation = (EClassORMAnnotation) getAnnotationManager() .getAnnotation(referencedEClass, OrmannotationsPackage.eINSTANCE.getEClassORMAnnotation()); if (doAddConverter(eReferenceModelGenAnnotation)) { // an object map as a basic... annotation.setBasic(OrmFactory.eINSTANCE.createBasic()); annotation.getBasic().setConvert(ORMUtils.OBJECT_CONVERTER_NAME); } else if (annotation.getEmbedded() != null || referencedEClassORMAnnotation.getEmbeddable() != null && referencedEClassORMAnnotation.getEntity() == null) { annotateEmbedded(annotation); } else if (eOpposite != null && !eOpposite.isMany()) { annotateOneToOne(annotation); } else { annotateManyToOne(annotation); } } } /* * (non-Javadoc) * * @see org.eclipse.emf.texo.generator.Annotator#postAnnotating(org.eclipse.emf.texo.annotations. * annotationsmodel.ENamedElementAnnotation) */ public void postAnnotating(EReferenceORMAnnotation annotation) { } protected void annotateElementCollection(EReferenceORMAnnotation annotation) { final EReference eReference = annotation.getEReference(); final EPackage ePackage = eReference.getEContainingClass().getEPackage(); final ORMNamingStrategy namingStrategy = getOrmNamingStrategy(ePackage); final EReferenceModelGenAnnotation eReferenceModelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eReference, ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); // clear the embedded, we can only have one of the two... if (annotation.getEmbedded() != null) { annotation.getElementCollection().getAttributeOverride().addAll(annotation.getEmbedded().getAttributeOverride()); annotation.getElementCollection().getAssociationOverride() .addAll(annotation.getEmbedded().getAssociationOverride()); annotation.getElementCollection().setAttributeType(annotation.getEmbedded().getAttributeType()); annotation.setEmbedded(null); } final ElementCollection elementCollection = annotation.getElementCollection(); // make the access field if not changeable, as there won't be a setter if (!eReference.isChangeable()) { elementCollection.setAccess(AccessType.FIELD); } else if (GeneratorUtils.setPropertyAccess(annotation.getAnnotatedEFeature())) { elementCollection.setAccess(AccessType.PROPERTY); } if (GeneratorUtils.isEmptyOrNull(elementCollection.getName())) { elementCollection.setName(getName(eReference)); } if (doAddConverter(eReferenceModelGenAnnotation)) { elementCollection.setConvert(ORMUtils.OBJECT_CONVERTER_NAME); } if (!ModelUtils.isEMap(eReference.getEReferenceType()) && elementCollection.getOrderColumn() == null && eReferenceModelGenAnnotation.isUseList()) { final OrderColumn orderColumn = OrmFactory.eINSTANCE.createOrderColumn(); if (namingStrategy.isGenerateAllDBSchemaNames()) { orderColumn.setName(namingStrategy.getIndexColumnName(eReference)); } elementCollection.setOrderColumn(orderColumn); } if (elementCollection.getCollectionTable() == null && namingStrategy.isGenerateAllDBSchemaNames()) { final CollectionTable collectionTable = OrmFactory.eINSTANCE.createCollectionTable(); elementCollection.setCollectionTable(collectionTable); } if (eReference.isContainment()) { elementCollection.setCascadeOnDelete(true); } if (namingStrategy.isGenerateAllDBSchemaNames()) { if (elementCollection.getCollectionTable() != null) { if (GeneratorUtils.isEmptyOrNull(elementCollection.getCollectionTable().getName())) { elementCollection.getCollectionTable().setName(namingStrategy.getJoinTableName(eReference)); } } if (elementCollection.getOrderColumn() != null && GeneratorUtils.isEmptyOrNull(elementCollection.getOrderColumn().getName())) { elementCollection.getOrderColumn().setName(namingStrategy.getIndexColumnName(eReference)); } } } protected void annotateOneToMany(EReferenceORMAnnotation annotation) { final EReference eReference = annotation.getEReference(); final EPackage ePackage = eReference.getEContainingClass().getEPackage(); final ORMNamingStrategy namingStrategy = getOrmNamingStrategy(ePackage); final EPackageORMAnnotation ePackageORMAnnotation = (EPackageORMAnnotation) getAnnotationManager().getAnnotation( ePackage, OrmannotationsPackage.eINSTANCE.getEPackageORMAnnotation()); final OneToMany oneToMany; if (annotation.getOneToMany() != null) { oneToMany = annotation.getOneToMany(); } else { oneToMany = OrmFactory.eINSTANCE.createOneToMany(); annotation.setOneToMany(oneToMany); } // copy any join columns/jointable over if (oneToMany.getJoinColumn().isEmpty()) { for (JoinColumn jc : annotation.getJoinColumn()) { oneToMany.getJoinColumn().add(EcoreUtil.copy(jc)); } } if (oneToMany.getJoinTable() == null) { oneToMany.setJoinTable(annotation.getJoinTable()); } // make the access field if not changeable, as there won't be a setter if (!eReference.isChangeable()) { oneToMany.setAccess(AccessType.FIELD); } else if (GeneratorUtils.setPropertyAccess(annotation.getAnnotatedEFeature())) { oneToMany.setAccess(AccessType.PROPERTY); } if (oneToMany.getCascade() == null) { if (eReference.isContainment()) { oneToMany.setCascade(EcoreUtil.copy(ePackageORMAnnotation.getDefaultCascadeContainment())); } else { oneToMany.setCascade(EcoreUtil.copy(ePackageORMAnnotation.getDefaultCascadeNonContainment())); } // no defaults set, do something smart... if (oneToMany.getCascade() == null) { oneToMany.setCascade(OrmFactory.eINSTANCE.createCascadeType()); if (eReference.isContainment()) { oneToMany.getCascade().setCascadeAll(OrmFactory.eINSTANCE.createEmptyType()); } else { oneToMany.getCascade().setCascadeMerge(OrmFactory.eINSTANCE.createEmptyType()); oneToMany.getCascade().setCascadePersist(OrmFactory.eINSTANCE.createEmptyType()); oneToMany.getCascade().setCascadeRefresh(OrmFactory.eINSTANCE.createEmptyType()); } } } if (GeneratorUtils.isEmptyOrNull(oneToMany.getName())) { oneToMany.setName(getName(eReference)); } // the map entry value is an entity if (ModelUtils.isEMap(eReference.getEReferenceType())) { // for maps we always need a join table otherwise eclipselink will fail with a NPE if (oneToMany.getJoinTable() == null) { final JoinTable joinTable = OrmFactory.eINSTANCE.createJoinTable(); oneToMany.setJoinTable(joinTable); } // explicitly set the join table name // is needed because otherwise eclipselink fails with a npe if (oneToMany.getJoinTable() != null && GeneratorUtils.isEmptyOrNull(oneToMany.getJoinTable().getName())) { oneToMany.getJoinTable().setName(namingStrategy.getJoinTableName(eReference)); } if (namingStrategy.isGenerateAllDBSchemaNames()) { addColumnsToJoinTable(namingStrategy, oneToMany.getJoinTable(), annotation); } // note mapkeyclass not needed as we generate // fully parameterized types // final EStructuralFeature eFeature = eReference.getEReferenceType().getEStructuralFeature("key"); //$NON-NLS-1$ // final EClassifier referedClassifier = eFeature.getEType(); // final EClassifierModelGenAnnotation modelGenAnnotation = (EClassifierModelGenAnnotation) getAnnotationManager() // .getAnnotation(referedClassifier, ModelcodegeneratorPackage.eINSTANCE.getEClassifierModelGenAnnotation()); // if (oneToMany.getMapKeyClass() == null) { // final MapKeyClass mapKeyClass = OrmFactory.eINSTANCE.createMapKeyClass(); // mapKeyClass.setClass(modelGenAnnotation.getQualifiedClassName()); // oneToMany.setMapKeyClass(mapKeyClass); // } if (oneToMany.getMapKeyColumn() == null) { final MapKeyColumn mapKeyColumn = OrmFactory.eINSTANCE.createMapKeyColumn(); mapKeyColumn.setTable(oneToMany.getJoinTable().getName()); if (namingStrategy.isGenerateAllDBSchemaNames()) { mapKeyColumn.setName(namingStrategy.getIndexColumnName(eReference)); } oneToMany.setMapKeyColumn(mapKeyColumn); } // no need to do the rest return; } final EReferenceModelGenAnnotation eReferenceModelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eReference, ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); if (doAddConverter(eReferenceModelGenAnnotation)) { oneToMany.setConverter(ORMUtils.createDefaultConverter()); } // set the order column, is always set on this side if (!ModelUtils.isEMap(eReference.getEReferenceType()) && oneToMany.getOrderBy() == null && ePackageORMAnnotation.isAddOrderColumnToListMappings() && eReferenceModelGenAnnotation.isUseList() && oneToMany.getOrderColumn() == null) { final OrderColumn orderColumn = OrmFactory.eINSTANCE.createOrderColumn(); if (namingStrategy.isGenerateAllDBSchemaNames()) { orderColumn.setName(namingStrategy.getIndexColumnName(eReference)); } oneToMany.setOrderColumn(orderColumn); } final boolean isOwner = eReferenceModelGenAnnotation.isUseList() || isOwner(eReference); // set mapped by // if a list then set the mapped by on the other side if (!isOwner && eReference.getEOpposite() != null && GeneratorUtils.isEmptyOrNull(oneToMany.getMappedBy())) { oneToMany.setMappedBy(getMappedBy(eReference)); } // set target entity // not needed we generate fully qualified/parameterised code // if (GeneratorUtils.isEmptyOrNull(oneToMany.getTargetEntity())) { // oneToMany.setTargetEntity(getTargetEntity(eReference)); // } // now work on jointable or joincolumn if (isOwner && oneToMany.getJoinColumn().isEmpty() && oneToMany.getJoinTable() == null) { if (eReference.isContainment()) { if (ePackageORMAnnotation.isUseJoinTablesForContainment()) { final JoinTable joinTable = OrmFactory.eINSTANCE.createJoinTable(); oneToMany.setJoinTable(joinTable); } else if (namingStrategy.isGenerateAllDBSchemaNames()) { final JoinColumn joinColumn = OrmFactory.eINSTANCE.createJoinColumn(); oneToMany.getJoinColumn().add(joinColumn); } } else { if (ePackageORMAnnotation.isUseJoinTablesForNonContainment()) { // if there is an opposite let the jointable be set on the other side final JoinTable joinTable = OrmFactory.eINSTANCE.createJoinTable(); oneToMany.setJoinTable(joinTable); } else if (namingStrategy.isGenerateAllDBSchemaNames()) { final JoinColumn joinColumn = OrmFactory.eINSTANCE.createJoinColumn(); oneToMany.getJoinColumn().add(joinColumn); } } } if (namingStrategy.isGenerateAllDBSchemaNames()) { if (oneToMany.getJoinTable() != null) { // set a unique name if (GeneratorUtils.isEmptyOrNull(oneToMany.getJoinTable().getName())) { oneToMany.getJoinTable().setName(namingStrategy.getJoinTableName(eReference)); } addColumnsToJoinTable(namingStrategy, oneToMany.getJoinTable(), annotation); } if (oneToMany.getOrderColumn() != null && GeneratorUtils.isEmptyOrNull(oneToMany.getOrderColumn().getName())) { oneToMany.getOrderColumn().setName(namingStrategy.getIndexColumnName(eReference)); } for (JoinColumn jc : oneToMany.getJoinColumn()) { if (GeneratorUtils.isEmptyOrNull(jc.getName())) { jc.setName(namingStrategy.getJoinColumnName(eReference)); } } } } protected void mapMap(EReferenceORMAnnotation annotation) { final EClass mapEClass = annotation.getEReference().getEReferenceType(); final EStructuralFeature valueEFeature = mapEClass.getEStructuralFeature("value"); //$NON-NLS-1$ if (valueEFeature instanceof EReference) { annotateOneToMany(annotation); } else { addElementCollection(annotation); } } protected void addElementCollection(EReferenceORMAnnotation annotation) { final ElementCollection elementCollection; if (annotation.getElementCollection() == null) { elementCollection = OrmFactory.eINSTANCE.createElementCollection(); annotation.setElementCollection(elementCollection); } else { elementCollection = annotation.getElementCollection(); } annotation.setElementCollection(elementCollection); annotateElementCollection(annotation); } protected void annotateEmbedded(EReferenceORMAnnotation annotation) { final EReference eReference = annotation.getEReference(); final Embedded embedded; if (annotation.getEmbedded() != null) { embedded = annotation.getEmbedded(); } else { embedded = OrmFactory.eINSTANCE.createEmbedded(); annotation.setEmbedded(embedded); } if (GeneratorUtils.isEmptyOrNull(embedded.getName())) { embedded.setName(getName(eReference)); } } protected void annotateOneToOne(EReferenceORMAnnotation annotation) { final EReference eReference = annotation.getEReference(); final EPackage ePackage = eReference.getEContainingClass().getEPackage(); final EPackageORMAnnotation ePackageORMAnnotation = (EPackageORMAnnotation) getAnnotationManager().getAnnotation( ePackage, OrmannotationsPackage.eINSTANCE.getEPackageORMAnnotation()); boolean generatedOneToOne = false; final OneToOne oneToOne; if (annotation.getOneToOne() != null) { oneToOne = annotation.getOneToOne(); } else { oneToOne = OrmFactory.eINSTANCE.createOneToOne(); annotation.setOneToOne(oneToOne); generatedOneToOne = true; } // make the access field if not changeable, as there won't be a setter if (!eReference.isChangeable()) { oneToOne.setAccess(AccessType.FIELD); } else if (GeneratorUtils.setPropertyAccess(annotation.getAnnotatedEFeature())) { oneToOne.setAccess(AccessType.PROPERTY); } if (GeneratorUtils.isEmptyOrNull(oneToOne.getName())) { oneToOne.setName(getName(eReference)); } if (oneToOne.getCascade() == null) { if (eReference.isContainment()) { oneToOne.setCascade(EcoreUtil.copy(ePackageORMAnnotation.getDefaultCascadeContainment())); } else { oneToOne.setCascade(EcoreUtil.copy(ePackageORMAnnotation.getDefaultCascadeNonContainment())); } // no defaults set, do something smart... if (oneToOne.getCascade() == null) { oneToOne.setCascade(OrmFactory.eINSTANCE.createCascadeType()); if (eReference.isContainment()) { oneToOne.getCascade().setCascadeAll(OrmFactory.eINSTANCE.createEmptyType()); } else { oneToOne.getCascade().setCascadeMerge(OrmFactory.eINSTANCE.createEmptyType()); oneToOne.getCascade().setCascadePersist(OrmFactory.eINSTANCE.createEmptyType()); oneToOne.getCascade().setCascadeRefresh(OrmFactory.eINSTANCE.createEmptyType()); } } } // set mapped by if (generatedOneToOne && !isOwner(eReference)) { oneToOne.setMappedBy(getMappedBy(eReference)); } // set target entity // not needed we generate fully qualified/parameterised code // if (GeneratorUtils.isEmptyOrNull(oneToOne.getTargetEntity())) { // oneToOne.setTargetEntity(getTargetEntity(eReference)); // } // copy any join columns over removes them from the annotation oneToOne.getJoinColumn().addAll(annotation.getJoinColumn()); if (oneToOne.getJoinTable() == null) { oneToOne.setJoinTable(annotation.getJoinTable()); } final ORMNamingStrategy namingStrategy = getOrmNamingStrategy(eReference.getEContainingClass().getEPackage()); if (oneToOne.getJoinColumn().isEmpty() && namingStrategy.isGenerateAllDBSchemaNames()) { oneToOne.getJoinColumn().add(OrmFactory.eINSTANCE.createJoinColumn()); } if (namingStrategy.isGenerateAllDBSchemaNames()) { if (oneToOne.getJoinTable() != null) { if (GeneratorUtils.isEmptyOrNull(oneToOne.getJoinTable().getName())) { oneToOne.getJoinTable().setName(namingStrategy.getJoinTableName(eReference)); } addColumnsToJoinTable(namingStrategy, oneToOne.getJoinTable(), annotation); } for (JoinColumn jc : oneToOne.getJoinColumn()) { if (GeneratorUtils.isEmptyOrNull(jc.getName())) { jc.setName(namingStrategy.getForeignKeyColumnName(eReference)); } } } if (!GeneratorUtils.isOptional(eReference)) { oneToOne.setOptional(false); } } protected void annotateManyToOne(EReferenceORMAnnotation annotation) { final EReference eReference = annotation.getEReference(); final EPackage ePackage = eReference.getEContainingClass().getEPackage(); final EPackageORMAnnotation ePackageORMAnnotation = (EPackageORMAnnotation) getAnnotationManager().getAnnotation( ePackage, OrmannotationsPackage.eINSTANCE.getEPackageORMAnnotation()); final EClassORMAnnotation eClassORMAnnotation = (EClassORMAnnotation) getAnnotationManager().getAnnotation( eReference.getEContainingClass(), OrmannotationsPackage.eINSTANCE.getEClassORMAnnotation()); final ORMNamingStrategy namingStrategy = getOrmNamingStrategy(eReference.getEContainingClass().getEPackage()); final ManyToOne manyToOne; if (annotation.getManyToOne() != null) { manyToOne = annotation.getManyToOne(); } else { manyToOne = OrmFactory.eINSTANCE.createManyToOne(); annotation.setManyToOne(manyToOne); } if (GeneratorUtils.isEmptyOrNull(manyToOne.getName())) { manyToOne.setName(getName(eReference)); } // make the access field if not changeable, as there won't be a setter if (!eReference.isChangeable()) { manyToOne.setAccess(AccessType.FIELD); } else if (GeneratorUtils.setPropertyAccess(annotation.getAnnotatedEFeature())) { manyToOne.setAccess(AccessType.PROPERTY); } if (manyToOne.getCascade() == null) { if (eReference.isContainment()) { manyToOne.setCascade(EcoreUtil.copy(ePackageORMAnnotation.getDefaultCascadeContainment())); } else { manyToOne.setCascade(EcoreUtil.copy(ePackageORMAnnotation.getDefaultCascadeNonContainment())); } // no defaults set, do something smart... if (manyToOne.getCascade() == null) { manyToOne.setCascade(OrmFactory.eINSTANCE.createCascadeType()); if (eReference.isContainment()) { manyToOne.getCascade().setCascadeAll(OrmFactory.eINSTANCE.createEmptyType()); } else { manyToOne.getCascade().setCascadeMerge(OrmFactory.eINSTANCE.createEmptyType()); manyToOne.getCascade().setCascadePersist(OrmFactory.eINSTANCE.createEmptyType()); manyToOne.getCascade().setCascadeRefresh(OrmFactory.eINSTANCE.createEmptyType()); } } } // set target entity // not needed we generate fully qualified/parameterised code // if (GeneratorUtils.isEmptyOrNull(manyToOne.getTargetEntity())) { // manyToOne.setTargetEntity(getTargetEntity(eReference)); // } if (!GeneratorUtils.isOptional(eReference)) { manyToOne.setOptional(false); } // copy any join columns/table over, remove from the annotation manyToOne.getJoinColumn().addAll(annotation.getJoinColumn()); if (manyToOne.getJoinTable() == null) { manyToOne.setJoinTable(annotation.getJoinTable()); } // now work on jointable or joincolumn if (manyToOne.getJoinColumn().isEmpty() && manyToOne.getJoinTable() == null) { // if the opposite is containment final EReference eOpposite = eReference.getEOpposite(); if (eOpposite != null) { // if the opposite is a list then don't do anything final EReferenceModelGenAnnotation eOppositeModelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eOpposite, ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); final boolean isOwner = !eOppositeModelGenAnnotation.isUseList() && isOwner(eReference); if (isOwner) { if (eOpposite.isContainment()) { if (ePackageORMAnnotation.isUseJoinTablesForContainment()) { final JoinTable joinTable = OrmFactory.eINSTANCE.createJoinTable(); manyToOne.setJoinTable(joinTable); } else if (namingStrategy.isGenerateAllDBSchemaNames()) { final JoinColumn joinColumn = OrmFactory.eINSTANCE.createJoinColumn(); manyToOne.getJoinColumn().add(joinColumn); } } else if (ePackageORMAnnotation.isUseJoinTablesForNonContainment()) { final JoinTable joinTable = OrmFactory.eINSTANCE.createJoinTable(); manyToOne.setJoinTable(joinTable); } else if (namingStrategy.isGenerateAllDBSchemaNames()) { final JoinColumn joinColumn = OrmFactory.eINSTANCE.createJoinColumn(); manyToOne.getJoinColumn().add(joinColumn); } } else if (eOppositeModelGenAnnotation.isUseList()) { final JoinColumn joinColumn = OrmFactory.eINSTANCE.createJoinColumn(); manyToOne.getJoinColumn().add(joinColumn); } } else if (namingStrategy.isGenerateAllDBSchemaNames()) { final JoinColumn joinColumn = OrmFactory.eINSTANCE.createJoinColumn(); manyToOne.getJoinColumn().add(joinColumn); } } // set a unique name if (namingStrategy.isGenerateAllDBSchemaNames()) { if (manyToOne.getJoinTable() != null) { if (GeneratorUtils.isEmptyOrNull(manyToOne.getJoinTable().getName())) { manyToOne.getJoinTable().setName(namingStrategy.getJoinTableName(eReference)); } addColumnsToJoinTable(namingStrategy, manyToOne.getJoinTable(), annotation); } for (JoinColumn jc : manyToOne.getJoinColumn()) { if (GeneratorUtils.isEmptyOrNull(jc.getName())) { jc.setName(namingStrategy.getForeignKeyColumnName(eReference)); } } } // force nullable/optional if stored in another table if (!hasItsOwnTable(eClassORMAnnotation)) { if (manyToOne.getJoinColumn().isEmpty()) { if (!manyToOne.isOptional()) { manyToOne.setOptional(true); } } else { for (JoinColumn jc : manyToOne.getJoinColumn()) { jc.setNullable(true); } } } } protected void annotateManyToMany(EReferenceORMAnnotation annotation) { final EReference eReference = annotation.getEReference(); final EPackage ePackage = eReference.getEContainingClass().getEPackage(); final EPackageORMAnnotation ePackageORMAnnotation = (EPackageORMAnnotation) getAnnotationManager().getAnnotation( ePackage, OrmannotationsPackage.eINSTANCE.getEPackageORMAnnotation()); final ORMNamingStrategy namingStrategy = getOrmNamingStrategy(ePackage); final ManyToMany manyToMany; if (annotation.getManyToMany() != null) { manyToMany = annotation.getManyToMany(); } else { manyToMany = OrmFactory.eINSTANCE.createManyToMany(); annotation.setManyToMany(manyToMany); } // make the access field if not changeable, as there won't be a setter if (!eReference.isChangeable()) { manyToMany.setAccess(AccessType.FIELD); } else if (GeneratorUtils.setPropertyAccess(annotation.getAnnotatedEFeature())) { manyToMany.setAccess(AccessType.PROPERTY); } if (GeneratorUtils.isEmptyOrNull(manyToMany.getName())) { manyToMany.setName(getName(eReference)); } if (manyToMany.getCascade() == null) { if (eReference.isContainment()) { manyToMany.setCascade(EcoreUtil.copy(ePackageORMAnnotation.getDefaultCascadeContainment())); } else { manyToMany.setCascade(EcoreUtil.copy(ePackageORMAnnotation.getDefaultCascadeNonContainment())); } // no defaults set, do something smart... if (manyToMany.getCascade() == null) { manyToMany.setCascade(OrmFactory.eINSTANCE.createCascadeType()); if (eReference.isContainment()) { manyToMany.getCascade().setCascadeAll(OrmFactory.eINSTANCE.createEmptyType()); } else { manyToMany.getCascade().setCascadeMerge(OrmFactory.eINSTANCE.createEmptyType()); manyToMany.getCascade().setCascadePersist(OrmFactory.eINSTANCE.createEmptyType()); manyToMany.getCascade().setCascadeRefresh(OrmFactory.eINSTANCE.createEmptyType()); } } } // set target entity // not needed we generate fully qualified/parameterised code // if (GeneratorUtils.isEmptyOrNull(manyToMany.getTargetEntity())) { // manyToMany.setTargetEntity(getTargetEntity(eReference)); // } // different cases: // 1) both sides are lists: 2 separate join tables // 2) one side is a list and one side a set: the list side is the owner // 3) both sides use a set, choose the owner final EReferenceModelGenAnnotation eReferenceModelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eReference, ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); if (doAddConverter(eReferenceModelGenAnnotation)) { manyToMany.setConverter(ORMUtils.createDefaultConverter()); } // if the annotation has a jointable use it here if (manyToMany.getJoinTable() == null) { manyToMany.setJoinTable(annotation.getJoinTable()); } if (eReference.getEOpposite() != null) { final EReferenceModelGenAnnotation eOppositeModelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eReference.getEOpposite(), ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); // if both sides have a list then use 2 join tables // or this is the owner if (eReferenceModelGenAnnotation.isUseList()) { if (manyToMany.getJoinTable() == null) { final JoinTable joinTable = OrmFactory.eINSTANCE.createJoinTable(); manyToMany.setJoinTable(joinTable); } if (ePackageORMAnnotation.isAddOrderColumnToListMappings() && eReferenceModelGenAnnotation.isUseList() && manyToMany.getOrderColumn() == null && manyToMany.getOrderBy() == null) { final OrderColumn orderColumn = OrmFactory.eINSTANCE.createOrderColumn(); if (namingStrategy.isGenerateAllDBSchemaNames()) { orderColumn.setName(namingStrategy.getIndexColumnName(eReference)); } manyToMany.setOrderColumn(orderColumn); } } else if (eOppositeModelGenAnnotation.isUseList()) { // opposite is the owner manyToMany.setMappedBy(getMappedBy(eReference)); } else if (!isOwner(eReference)) { // opposite is the owner manyToMany.setMappedBy(getMappedBy(eReference)); } } else { if (manyToMany.getJoinTable() == null && namingStrategy.isGenerateAllDBSchemaNames()) { // create a join table final JoinTable joinTable = OrmFactory.eINSTANCE.createJoinTable(); manyToMany.setJoinTable(joinTable); } if (ePackageORMAnnotation.isAddOrderColumnToListMappings() && eReferenceModelGenAnnotation.isUseList() && manyToMany.getOrderBy() == null && manyToMany.getOrderColumn() == null) { final OrderColumn orderColumn = OrmFactory.eINSTANCE.createOrderColumn(); if (namingStrategy.isGenerateAllDBSchemaNames()) { orderColumn.setName(namingStrategy.getIndexColumnName(eReference)); } manyToMany.setOrderColumn(orderColumn); } } // set a unique name if (namingStrategy.isGenerateAllDBSchemaNames()) { if (manyToMany.getJoinTable() != null) { if (GeneratorUtils.isEmptyOrNull(manyToMany.getJoinTable().getName())) { manyToMany.getJoinTable().setName(namingStrategy.getJoinTableName(eReference)); } addColumnsToJoinTable(namingStrategy, manyToMany.getJoinTable(), annotation); } if (manyToMany.getOrderColumn() != null && GeneratorUtils.isEmptyOrNull(manyToMany.getOrderColumn().getName())) { manyToMany.getOrderColumn().setName(namingStrategy.getIndexColumnName(eReference)); } } } private void addColumnsToJoinTable(ORMNamingStrategy namingStrategy, JoinTable joinTable, EReferenceORMAnnotation annotation) { EReference eReference = annotation.getEReference(); final EReferenceModelGenAnnotation eReferenceModelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eReference, ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); final boolean isOwner = eReferenceModelGenAnnotation.isUseList() || isOwner(eReference); // build the join columns from the other side if (!isOwner) { eReference = eReference.getEOpposite(); } if (joinTable.getJoinColumn().isEmpty() && namingStrategy.isGenerateAllDBSchemaNames()) { joinTable.getJoinColumn().add(OrmFactory.eINSTANCE.createJoinColumn()); joinTable.getJoinColumn().get(0).setName(namingStrategy.getJoinColumnName(eReference)); } if (joinTable.getInverseJoinColumn().isEmpty() && namingStrategy.isGenerateAllDBSchemaNames()) { joinTable.getInverseJoinColumn().add(OrmFactory.eINSTANCE.createJoinColumn()); joinTable.getInverseJoinColumn().get(0).setName(namingStrategy.getInverseJoinColumnName(eReference)); } if (eReference.isUnique()) { final UniqueConstraint uniqueConstraint = OrmFactory.eINSTANCE.createUniqueConstraint(); for (JoinColumn joinColumn : joinTable.getJoinColumn()) { uniqueConstraint.getColumnName().add(joinColumn.getName()); } for (JoinColumn joinColumn : joinTable.getInverseJoinColumn()) { uniqueConstraint.getColumnName().add(joinColumn.getName()); } // TODO: add uniqueconstraint naming } } // makes sure that always the same side of an association is considered to be the owner. private boolean isOwner(EReference eReference) { final EReference eOpposite = eReference.getEOpposite(); if (eOpposite == null) { return true; } // the many side of a bi-directional many-to-one/one-to-many is the owner if (!eReference.isMany() && eOpposite.isMany()) { return true; } if (eReference.isMany() && !eOpposite.isMany()) { return false; } if (eOpposite.isContainment()) { return false; } if (eReference.isContainment()) { return true; } final String sideOne = eReference.getEContainingClass().getEPackage().getName() + "_" //$NON-NLS-1$ + eReference.getEContainingClass().getName() + "_" + eReference.getName(); //$NON-NLS-1$ final String sideTwo = eOpposite.getEContainingClass().getEPackage().getName() + "_" //$NON-NLS-1$ + eOpposite.getEContainingClass().getName() + "_" + eOpposite.getName(); //$NON-NLS-1$ return sideOne.compareTo(sideTwo) > 0; } // for later usage // private String getTargetEntity(EReference eReference) { // final EClassModelGenAnnotation targetEntityModelGen = (EClassModelGenAnnotation) getAnnotationManager() // .getAnnotation(eReference.getEReferenceType(), // ModelcodegeneratorPackage.eINSTANCE.getEClassModelGenAnnotation()); // return targetEntityModelGen.getQualifiedClassName(); // } private String getMappedBy(EReference eReference) { final EReferenceModelGenAnnotation oppositeModelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eReference.getEOpposite(), ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); return oppositeModelGenAnnotation.getValidJavaMemberName(); } private String getName(EReference eReference) { final EReferenceModelGenAnnotation modelGenAnnotation = (EReferenceModelGenAnnotation) getAnnotationManager() .getAnnotation(eReference, ModelcodegeneratorPackage.eINSTANCE.getEReferenceModelGenAnnotation()); return modelGenAnnotation.getValidJavaMemberName(); } /* * (non-Javadoc) * * @see org.eclipse.emf.texo.generator.Annotator#getAnnotationEClass() */ public EClass getAnnotationEClass() { return OrmannotationsPackage.eINSTANCE.getEReferenceORMAnnotation(); } }