Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 73357079513b6ba6c1f57b1373e73148ac006311 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
/**
 * <copyright> Copyright (c) 2005, 2006, 2007 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 Davide Marchignoli
 * </copyright> $Id: MappingContext.java,v 1.20 2007/07/18 16:11:45 mtaal Exp $
 */

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.emf.teneo.annotations.mapper.AbstractProcessingContext;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEClass;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEStructuralFeature;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedModel;
import org.eclipse.emf.teneo.annotations.pannotation.SecondaryTable;
import org.eclipse.emf.teneo.annotations.pannotation.Table;
import org.eclipse.emf.teneo.annotations.pannotation.UniqueConstraint;
import org.eclipse.emf.teneo.ecore.EModelResolver;
import org.eclipse.emf.teneo.extension.ExtensionInitializable;
import org.eclipse.emf.teneo.extension.ExtensionManager;
import org.eclipse.emf.teneo.extension.ExtensionManagerAware;
import org.eclipse.emf.teneo.extension.ExtensionPoint;
import org.eclipse.emf.teneo.mapping.strategy.EntityNameStrategy;
import org.eclipse.emf.teneo.mapping.strategy.SQLNameStrategy;
import org.eclipse.emf.teneo.simpledom.Document;
import org.eclipse.emf.teneo.simpledom.Element;

/**
 * Maps a basic attribute with many=true, e.g. list of simpletypes.
 * 
 * @author <a href="mailto:mtaal@elver.org">Martin Taal</a>
 * @version $Revision: 1.20 $
 */
public class MappingContext extends AbstractProcessingContext implements ExtensionPoint, ExtensionInitializable,
		ExtensionManagerAware {

	/** The xml document to which all elements are added */
	private Document mappingDoc;

	/** The current element, normally a class element */
	private Element currentElement;

	/** Mapping from eclass to entity name */
	private Map<EClass, String> entityNames = null;

	/**
	 * Keeps track of the list of featuremapmappers created for the current entity
	 */
	private final List<FeatureMapMapping> featureMapMappers = new ArrayList<FeatureMapMapping>();

	/** The list of eattributes for which a featuremap mapping was created */
	private final List<EAttribute> handledFeatureMapEAttributes = new ArrayList<EAttribute>();

	/** the mapper used for features */
	private FeatureMapper featureMapper;

	/**
	 * Is the current element a mixed or a feature map, in this case all features should be not
	 * required. TODO: check, does this work with embedded components in a feature map?
	 */
	private boolean currentElementFeatureMap = false;

	/** The current table element is set when an entity starts */
	private Table currentTable = null;

	/** The current secondary table being processed. May be null. */
	private SecondaryTable currentSecondaryTable = null;

	/** The current eclass */
	protected EClass currentEClass = null;

	/** The current efeature being processed */
	protected EStructuralFeature currentEFeature = null;

	/** The entity mapper */
	private EntityMapper entityMapper;

	/** The extensionmanager used */
	private ExtensionManager extensionManager;

	/** The option to qualify entity names */
	private EntityNameStrategy entityNameStrategy = null;

	/** Version column name */
	private String versionColumnName = null;

	/** ID column name */
	private String idColumnName = null;

	/** Maximum column name */
	protected int maximumSqlNameLength = -1;

	/** The sql case strategy */
	protected SQLNameStrategy sqlNameStrategy;

	/**
	 * Set force optional, force optional is used in case a subclass is stored in the same table as
	 * its superclass, in this case all properties of the subclass are denoted as optional.
	 */
	private boolean forceOptional = false;

	// Options
	private boolean alwaysVersion;
	private boolean isMapEMapAsTrueMap;
	private String idbagIDColumnName = "ID";

	// The pa model for which this is all done, is set when generation starts
	private PAnnotatedModel paModel = null;

	/** Returns the entitymapper */
	public EntityMapper getEntityMapper() {
		return entityMapper;
	}

	/** Set relevant properties */
	protected void setMappingProperties(PersistenceOptions po) {
		versionColumnName = po.getVersionColumnName();
		idColumnName = po.getIdColumnName();
		maximumSqlNameLength = po.getMaximumSqlNameLength();
		alwaysVersion = po.getAlwaysVersion();
		isMapEMapAsTrueMap = po.isMapEMapAsTrueMap();
		idbagIDColumnName = po.getIDBagIDColumnName();
	}

	/** Return the concrete impl. class */
	protected String getInstanceClassName(EClass eClass) {
		final Class<?> clz = getInstanceClass(eClass);
		if (clz != null) {
			return clz.getName();
		}
		log.debug("Instance class for eclass " + eClass.getName() + " is null ");
		return null;
	}

	/** Return the concrete impl. class, if none is found then null is returned */
	protected Class<?> getInstanceClass(EClassifier eclassifier) {
		return EModelResolver.instance().getJavaClass(eclassifier);
	}

	/**
	 * @return Returns the entity name for the given entity EClass.
	 */
	public String getEntityName(EClass entityEClass) {
		return getEntityName(entityEClass, true);
	}

	/**
	 * @return Returns the entity name for the given entity EClass.
	 */
	public String getEntityName(EClass entityEClass, boolean throwCheckException) {
		String name = entityNames.get(entityEClass);
		if (name == null) {
			final Class<?> implClass = getInstanceClass(entityEClass);
			if (implClass != null) {
				name = implClass.getName();
			}
		}
		if (throwCheckException && name == null) {
			throw new IllegalStateException("An entity name has not been registered for " + entityEClass);
		}
		return name;
	}

	/** Set an entityname for a eclass */
	public void setEntityName(EClass entityEClass, String entityName) {
		entityNames.put(entityEClass, entityName);
	}

	/** Start a document */
	public void beginDocument(Document draft) {
		mappingDoc = draft;
		currentElement = draft.getRoot();
		entityNames = new HashMap<EClass, String>();
	}

	/** Finished creating the document */
	public Document endDocument() {
		Document builtDocument = mappingDoc;
		mappingDoc = null;
		currentElement = null;
		entityNames = null;
		return builtDocument;
	}

	/** The current element to which new elements are added */
	public Element getCurrent() {
		return currentElement;
	}

	/** Set the current element to which new elements are added */
	public void setCurrent(Element newCurrent) {
		this.currentElement = newCurrent;
	}

	/**
	 * Note this call will also clear the current list of featuremappers;
	 * 
	 * @return the featureMapMappers gathered during the entity processing
	 */
	public List<FeatureMapMapping> getClearFeatureMapMappers() {
		final ArrayList<FeatureMapMapping> result = new ArrayList<FeatureMapMapping>(featureMapMappers); // clone
		// the
		// list!
		featureMapMappers.clear();
		return result;
	}

	/**
	 * @param Adds
	 *            a featureMapMapper to the featuremapp mapper list
	 */
	public void addFeatureMapMapper(FeatureMapMapping featureMapMapper) {
		if (!handledFeatureMapEAttributes.contains(featureMapMapper.getEAttribute())) {
			featureMapMappers.add(featureMapMapper);
			handledFeatureMapEAttributes.add(featureMapMapper.getEAttribute());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.teneo.extension.ExtensionInitializable#initializeExtension()
	 */
	public void initializeExtension() {
		featureMapper = createFeatureMapper();
		entityMapper = getExtensionManager().getExtension(EntityMapper.class);
		entityMapper.setHbmContext(this);
	}

	/**
	 * @return The builder used by entity mapped that maps features to hbm.
	 */
	private FeatureMapper createFeatureMapper() {
		final FeatureMapper featureMapper = getExtensionManager().getExtension(FeatureMapper.class);
		featureMapper.setHbmContext(this);

		featureMapper.setBasicMapper(createMapper(BasicMapper.class));
		featureMapper.setManyAttributeMapper(createMapper(ManyAttributeMapper.class));
		featureMapper.setEmbeddedMapper(createMapper(EmbeddedMapper.class));
		featureMapper.setIdMapper(createMapper(IdMapper.class));
		featureMapper.setManyToManyMapper(createMapper(ManyToManyMapper.class));
		featureMapper.setManyToOneMapper(createMapper(ManyToOneMapper.class));
		featureMapper.setOneToManyMapper(createMapper(OneToManyMapper.class));
		featureMapper.setOneToOneMapper(createMapper(OneToOneMapper.class));
		return featureMapper;
	}

	protected <T> T createMapper(Class<T> clz) {
		final T t = getExtensionManager().getExtension(clz);
		((AbstractMapper) t).setHbmContext(this);
		return t;
	}

	/** process the features of the annotated eclass */
	protected void processFeatures(List<PAnnotatedEStructuralFeature> features) {
		for (PAnnotatedEStructuralFeature annotatedEStructuralFeature : features) {
			entityMapper.processFeature(annotatedEStructuralFeature);
		}
	}

	/**
	 * @return the featureMapper
	 */
	public FeatureMapper getFeatureMapper() {
		return featureMapper;
	}

	/**
	 * @return the currentElementFeatureMap
	 */
	public boolean isCurrentElementFeatureMap() {
		return currentElementFeatureMap;
	}

	/**
	 * @param currentElementFeatureMap
	 *            the currentElementFeatureMap to set
	 */
	public void setCurrentElementFeatureMap(boolean currentElementFeatureMap) {
		this.currentElementFeatureMap = currentElementFeatureMap;
	}

	/**
	 * @return the currentTable
	 */
	public Table getCurrentTable() {
		return currentTable;
	}

	/**
	 * @param currentTable
	 *            the currentTable to set
	 */
	public void setCurrentTable(Table currentTable) {
		this.currentTable = currentTable;
	}

	/**
	 * @param currentSecondaryTable
	 */
	public void setCurrentSecondaryTable(SecondaryTable currentSecondaryTable) {
		this.currentSecondaryTable = currentSecondaryTable;
	}

	/** Get unique constraint key. */
	public String getUniqueConstraintKey(String colName) {
		// Obtain UniqueConstraints from secondary or primary table.
		List<UniqueConstraint> uniqueConstraints = null;
		if (currentSecondaryTable != null) {
			uniqueConstraints = currentSecondaryTable.getUniqueConstraints();
		} else if (currentTable != null) {
			uniqueConstraints = currentTable.getUniqueConstraints();
		}
		if (uniqueConstraints == null) {
			return null;
		}

		// NOTE: Hibernate does not support one column being part of multiple
		// unique constraints.
		for (int i = 0, n = uniqueConstraints.size(); i < n; i++) {
			UniqueConstraint uniqueConstraint = uniqueConstraints.get(i);
			if (uniqueConstraint.getColumnNames().contains(colName)) {
				return "c" + i;
			}

		}
		return null;
	}

	/**
	 * @return the versionColumnName
	 */
	public String getVersionColumnName() {
		return versionColumnName;
	}

	/**
	 * @param versionColumnName
	 *            the versionColumnName to set
	 */
	public void setVersionColumnName(String versionColumnName) {
		this.versionColumnName = versionColumnName;
	}

	/**
	 * @return the maximumColumnNameLength
	 */
	public int getMaximumColumnNameLength() {
		return maximumSqlNameLength;
	}

	/** Default is trunc */
	protected String trunc(String name) {
		return trunc(name, true);
	}

	/**
	 * Utility method to truncate a column/table name. This method also repairs the name if an
	 * efeature was inherited and really belongs to another eclass. In this case jointables and join
	 * keys must be renamed to the new eclass. TODO: handle the case that the jointable/columns were
	 * set manually. This procedure will override them (only applies in case of multiple
	 * inheritance/mappedsuperclass).
	 */
	protected String trunc(String truncName, boolean truncPrefix) {
		final String useName;
		// currentEFeature is null in the beginning
		if (currentEFeature != null && currentEFeature.getEContainingClass() != currentEClass &&
				getEntityName(currentEFeature.getEContainingClass(), false) != null &&
				truncName.toUpperCase().startsWith(getEntityName(currentEFeature.getEContainingClass()).toUpperCase())) {
			log.debug("Replacing name of table/joincolumn " + truncName);
			// get rid of the first part
			useName =
					getEntityName(currentEClass) +
							truncName.substring(getEntityName(currentEFeature.getEContainingClass()).length());
			log.debug("with " + useName + " because efeature is inherited");
			log
				.debug("This renaming does not work in case of manually specified joincolumn/table names and mappedsuperclass or multiple inheritance!");
		} else {
			useName = truncName;
		}

		if (useName.indexOf('`') == 0) {
			return getSqlNameStrategy().convert(useName, false);
		}

		return "`" + getSqlNameStrategy().convert(useName, false) + "`";
	}

	/**
	 * @return the idColumnName
	 */
	public String getIdColumnName() {
		return idColumnName;
	}

	/** Return the alwaysversion option */
	public boolean alwaysVersion() {
		return alwaysVersion;
	}

	/** Returns the list of eattrs, note list is updated outside of this object */
	public List<EAttribute> getHandledFeatureMapEAttributes() {
		return handledFeatureMapEAttributes;
	}

	/** Returns the correct property name */
	public String getPropertyName(EStructuralFeature ef) {
		return EModelResolver.instance().getJavaMember(ef);
	}

	/** Return the version property handler */
	public String getVersionPropertyHandlerName() {
		return "org.eclipse.emf.teneo.hibernate.mapping.property.VersionPropertyHandler";
	}

	/** Return the id property handler */
	public String getIdPropertyHandlerName() {
		return "org.eclipse.emf.teneo.hibernate.mapping.identifier.IdentifierPropertyHandler";
	}

	/** Is this a dynamic eclass, i.e. it has no instanceclass */
	public boolean isDynamic(EClassifier eclassifier) {
		return !EModelResolver.instance().hasImplementationClass(eclassifier);
	}

	/**
	 * Use the implementation name as the mapping and never use entity-mapping, always false in this
	 * implementation
	 */
	public boolean forceUseOfInstance(PAnnotatedEClass aclass) {
		return false;
	}

	/**
	 * Returns true if the instance classes have been generated by emf. For Teneo this is always the
	 * case. Overriders can support a different generation strategy.
	 */
	public boolean isGeneratedByEMF() {
		return true;
	}

	/**
	 * There are four cases: EMF generated, EMF Dynamic, Easy EMF Generated, Easy EMF Dynamic public
	 * boolean isEasyEMFGenerated(EClassifier eclassifier) { return
	 * EModelResolver.instance().hasImplementationClass(eclassifier); } public boolean
	 * isEasyEMFDynamic(EClassifier eclassifier) { return !isEasyEMFGenerated(eclassifier) &&
	 * EModelResolver.instance().isRegistered( eclassifier.getEPackage()); } public boolean
	 * isEMFGenerated(EClassifier eclassifier) { return eclassifier.getInstanceClass() != null; }
	 */
	//
	// public boolean isEMFDynamic(EClassifier eclassifier) {
	// return !isEasyEMFDynamic(eclassifier) && !isEMFGenerated(eclassifier);
	// }
	//
	// /** Return the impl class */
	// public Class<?> getImpl(EClassifier eclassifier) {
	// return EModelResolver.instance().getJavaClass(eclassifier);
	// }
	//
	// /** Check if this is an entity (so without an impl class) */
	// public boolean hasImpl(PAnnotatedEStructuralFeature af) {
	// return EModelResolver.instance().hasImplementationClass(
	// af.getAnnotatedEStructuralFeature().getEContainingClass());
	// }
	/** Add a tuplizer element or not */
	public void addTuplizerElement(Element entityElement, PAnnotatedEClass aclass) {
	}

	/** Returns the enumusertype class name */
	public String getEnumUserType() {
		return "org.eclipse.emf.teneo.hibernate.mapping.ENumUserType";
	}

	/** Returns the enum user type integer name */
	public String getEnumIntegerUserType() {
		return "org.eclipse.emf.teneo.hibernate.mapping.ENumUserIntegerType";
	}

	/** Returns the enumusertype class name for the dynamic case */
	public String getDynamicEnumUserType() {
		return "org.eclipse.emf.teneo.hibernate.mapping.DynamicENumUserType";
	}

	/** Returns the enum user type integer name for the dynamic case */
	public String getDynamicEnumIntegerUserType() {
		return "org.eclipse.emf.teneo.hibernate.mapping.DynamicENumUserIntegerType";
	}

	/** Return the default user type */
	public String getDefaultUserType() {
		return "org.eclipse.emf.teneo.hibernate.mapping.DefaultToStringUserType";
	}

	/** Returns the default any type */
	public String getAnytype() {
		return "org.eclipse.emf.teneo.hibernate.mapping.AnyEObjectType";
	}

	/** Returns the usertype used to handle the xsd date */
	public String getXSDDateUserType() {
		return "org.eclipse.emf.teneo.hibernate.mapping.XSDDate";
	}

	/** Returns the usertype used to handle the xsd datetime */
	public String getXSDDateTimeUserType() {
		return "org.eclipse.emf.teneo.hibernate.mapping.XSDDateTime";
	}

	/**
	 * @return the eclassNameStrategy
	 */
	public EntityNameStrategy getEntityNameStrategy() {
		if (entityNameStrategy == null) {
			entityNameStrategy = getExtensionManager().getExtension(EntityNameStrategy.class);
			entityNameStrategy.setPaModel(getPaModel()); // this call is not really required but
			// for safety reasons
		}
		return entityNameStrategy;
	}

	/**
	 * @return the isMapEMapAsTrueMap
	 */
	public boolean isMapEMapAsTrueMap() {
		return isMapEMapAsTrueMap;
	}

	/**
	 * @return the currentEClass
	 */
	public EClass getCurrentEClass() {
		return currentEClass;
	}

	/**
	 * @param currentEClass
	 *            the currentEClass to set
	 */
	public void setCurrentEClass(EClass currentEClass) {
		this.currentEClass = currentEClass;
	}

	/**
	 * @return the currentEFeature
	 */
	public EStructuralFeature getCurrentEFeature() {
		return currentEFeature;
	}

	/**
	 * @param currentEFeature
	 *            the currentEFeature to set
	 */
	public void setCurrentEFeature(EStructuralFeature currentEFeature) {
		this.currentEFeature = currentEFeature;
	}

	/**
	 * @return the idbagIDColumnName
	 */
	public String getIdbagIDColumnName() {
		return idbagIDColumnName;
	}

	/**
	 * @return the forceOptional
	 */
	public boolean isForceOptional() {
		return forceOptional;
	}

	/**
	 * @param forceOptional
	 *            the forceOptional to set
	 */
	public void setForceOptional(boolean forceOptional) {
		this.forceOptional = forceOptional;
	}

	/**
	 * @return the paModel
	 */
	public PAnnotatedModel getPaModel() {
		return paModel;
	}

	/**
	 * @param paModel
	 *            the paModel to set
	 */
	public void setPaModel(PAnnotatedModel paModel) {
		this.paModel = paModel;
	}

	/**
	 * @return the extensionManager
	 */
	public ExtensionManager getExtensionManager() {
		return extensionManager;
	}

	/**
	 * @param extensionManager
	 *            the extensionManager to set
	 */
	public void setExtensionManager(ExtensionManager extensionManager) {
		this.extensionManager = extensionManager;
	}

	/**
	 * @return the sqlNameStrategy
	 */
	public SQLNameStrategy getSqlNameStrategy() {
		if (sqlNameStrategy == null) {
			sqlNameStrategy = getExtensionManager().getExtension(SQLNameStrategy.class);
		}
		return sqlNameStrategy;
	}
}

Back to the top