Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 3f1d2bf2cfd23eb2f29545f1c7efa8218b2df963 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
 * <copyright>
 *
 * Copyright (c) 2005, 2006, 2007, 2008 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
 * </copyright>
 *
 * $Id: BidirectionalManyToManyAnnotator.java,v 1.10 2009/03/30 07:53:04 mtaal Exp $
 */

package org.eclipse.emf.teneo.annotations.mapper;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEReference;
import org.eclipse.emf.teneo.annotations.pannotation.JoinTable;
import org.eclipse.emf.teneo.annotations.pannotation.ManyToMany;
import org.eclipse.emf.teneo.extension.ExtensionPoint;

/**
 * Annotates a bidirectional many-to-many ereference.
 * 
 * @author <a href="mailto:mtaal@elver.org">Martin Taal</a>
 * @version $Revision: 1.10 $
 */

public class BidirectionalManyToManyAnnotator extends BaseEFeatureAnnotator implements
		ExtensionPoint {

	// The logger
	protected static final Log log = LogFactory.getLog(BidirectionalManyToManyAnnotator.class);

	/** Process the features of the eclass */
	public void annotate(PAnnotatedEReference aReference) {
		final String featureLogStr = aReference.getModelEReference().getName() + "/"
				+ aReference.getModelEReference().getEContainingClass().getName();

		if (aReference.getOneToMany() != null || aReference.getOneToOne() != null
				|| aReference.getManyToOne() != null) {
			throw new StoreMappingException("The feature/eclass " + featureLogStr
					+ " should be a ManyToMany but "
					+ "it already has a OneToMany, OneToOne or ManyToOne annotation");
		}

		final EReference eReference = (EReference) aReference.getModelElement();
		final EReference eOpposite = eReference.getEOpposite();
		assert (eOpposite != null && eOpposite.isMany());

		ManyToMany mtm = aReference.getManyToMany();
		final boolean mtmWasSet = mtm != null; // mtm was set manually
		if (mtm == null) {
			if (log.isDebugEnabled()) {
				log.debug("Adding manytomany annotations to ereference: " + featureLogStr);
			}
			mtm = getFactory().createManyToMany();
			aReference.setManyToMany(mtm);
			mtm.setEModelElement(eReference);
		} else if (log.isDebugEnabled()) {
			log.debug("ManyToMany present check if default information should be added");
		}

		if (eReference.isContainment() || getPersistenceOptions().isSetDefaultCascadeOnNonContainment()) {
			setCascade(mtm.getCascade(), eReference.isContainment());
		}

		if (mtm.getTargetEntity() == null) {
			mtm.setTargetEntity(getEntityName(eReference.getEReferenceType()));
		}

		if (getPersistenceOptions().isSetForeignKeyNames() && aReference.getForeignKey() == null) {
			aReference.setForeignKey(createFK(aReference));
		}

		// determine where to place the jointable annotation and where to place
		// the mappedby
		// use a certain logic to determine as each is only set on one side
		// note that the join is always set on the other side of mapped by!
		// note that we can not do setJoinHere = !setMappedByHere because there
		// are situations
		// that even for mtm no mappedby is set on either side, nl. in case of
		// containment

		// also check if the other side has a (manual) manytomany with mappedby
		// set
		// bugzilla: 164808
		final PAnnotatedEReference otherPA = aReference.getPaModel().getPAnnotated(eOpposite);
		if (mtm.getMappedBy() == null && setMappedBy(eReference)
				&& (otherPA.getManyToMany() == null || otherPA.getManyToMany().getMappedBy() == null)) {
			mtm.setMappedBy(eOpposite.getName());
		}

		JoinTable joinTable = aReference.getJoinTable();
		if (joinTable == null) {
			joinTable = getFactory().createJoinTable();
			aReference.setJoinTable(joinTable);
		}
		joinTable.setEModelElement(eReference);

		// set unique and indexed
		// disabled because indexed = false now for mtm,
		// to overcome this the user has to explicitly set a mtm annotation.
		if (!mtmWasSet) {
			log.debug("Setting indexed and unique from ereference.isOrdered/isUnique "
					+ "because mtm was not set manually!");
			mtm.setIndexed(!getPersistenceOptions().alwaysMapListAsBag() && eReference.isOrdered());
		}

		// NOTE that the ejb3 spec states that the jointable should be the
		// concatenation of the
		// tablenames of the owning entities with an underscore, this will
		// quickly lead to nameclashes
		// in the case there is more than one relation between two classes. This
		// can be pretty likely
		// if the inheritance strategy is single_table.
		// now possibility to use a different naming strategy
		if (joinTable.getName() == null) {
			joinTable.setName(getSqlNameStrategy().getJoinTableName(aReference));
		}
		if (joinTable.getJoinColumns().size() == 0) {
			final List<String> names = getSqlNameStrategy().getJoinTableJoinColumns(aReference, false);
			joinTable.getJoinColumns().addAll(getJoinColumns(names, false, true, mtm));
		}
		if (joinTable.getInverseJoinColumns().size() == 0) {
			final List<String> names = getSqlNameStrategy().getJoinTableJoinColumns(aReference, true);
			joinTable.getInverseJoinColumns().addAll(getJoinColumns(names, false, true, mtm));
		}
	}
}

Back to the top