Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'hibernate/org.eclipse.emf.teneo.hibernate.mapper/src/org/eclipse/emf/teneo/hibernate/mapper/AbstractMapper.java')
-rwxr-xr-xhibernate/org.eclipse.emf.teneo.hibernate.mapper/src/org/eclipse/emf/teneo/hibernate/mapper/AbstractMapper.java971
1 files changed, 971 insertions, 0 deletions
diff --git a/hibernate/org.eclipse.emf.teneo.hibernate.mapper/src/org/eclipse/emf/teneo/hibernate/mapper/AbstractMapper.java b/hibernate/org.eclipse.emf.teneo.hibernate.mapper/src/org/eclipse/emf/teneo/hibernate/mapper/AbstractMapper.java
new file mode 100755
index 000000000..37f536660
--- /dev/null
+++ b/hibernate/org.eclipse.emf.teneo.hibernate.mapper/src/org/eclipse/emf/teneo/hibernate/mapper/AbstractMapper.java
@@ -0,0 +1,971 @@
+/**
+ * <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 Brian
+ * Vetter </copyright> $Id: AbstractMapper.java,v 1.55 2011/03/17 09:21:35 mtaal Exp $
+ */
+
+package org.eclipse.emf.teneo.hibernate.mapper;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.emf.ecore.EModelElement;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
+import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEAttribute;
+import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEClass;
+import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEReference;
+import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEStructuralFeature;
+import org.eclipse.emf.teneo.annotations.pannotation.Column;
+import org.eclipse.emf.teneo.annotations.pannotation.EnumType;
+import org.eclipse.emf.teneo.annotations.pannotation.Enumerated;
+import org.eclipse.emf.teneo.annotations.pannotation.External;
+import org.eclipse.emf.teneo.annotations.pannotation.JoinColumn;
+import org.eclipse.emf.teneo.annotations.pannotation.PannotationFactory;
+import org.eclipse.emf.teneo.annotations.pannotation.TemporalType;
+import org.eclipse.emf.teneo.hibernate.hbannotation.Any;
+import org.eclipse.emf.teneo.hibernate.hbannotation.AnyMetaDef;
+import org.eclipse.emf.teneo.hibernate.hbannotation.Cache;
+import org.eclipse.emf.teneo.hibernate.hbannotation.Filter;
+import org.eclipse.emf.teneo.hibernate.hbannotation.GenerationTime;
+import org.eclipse.emf.teneo.hibernate.hbannotation.HbCascadeType;
+import org.eclipse.emf.teneo.hibernate.hbannotation.HbannotationFactory;
+import org.eclipse.emf.teneo.hibernate.hbannotation.Index;
+import org.eclipse.emf.teneo.hibernate.hbannotation.OnDelete;
+import org.eclipse.emf.teneo.hibernate.hbannotation.Parameter;
+import org.eclipse.emf.teneo.hibernate.hbmodel.HbAnnotatedEAttribute;
+import org.eclipse.emf.teneo.hibernate.hbmodel.HbAnnotatedEDataType;
+import org.eclipse.emf.teneo.hibernate.hbmodel.HbAnnotatedEReference;
+import org.eclipse.emf.teneo.hibernate.hbmodel.HbAnnotatedETypeElement;
+import org.eclipse.emf.teneo.mapping.strategy.EntityNameStrategy;
+import org.eclipse.emf.teneo.simpledom.Element;
+import org.eclipse.emf.teneo.util.EcoreDataTypes;
+import org.eclipse.emf.teneo.util.StoreUtil;
+
+/**
+ * Base class for all mapping classes. Provides access to the hbmcontext.
+ *
+ * @author <a href="mailto:mtaal at elver.org">Martin Taal</a>
+ */
+public abstract class AbstractMapper {
+ /** The list of types which translate to a hibernate types */
+ private static final String[] TEMPORAL_TYPE_NAMES;
+
+ /** Initialize TEMPORAL_TYPE_NAMES */
+ static {
+ TEMPORAL_TYPE_NAMES = new String[TemporalType.VALUES.size()];
+ TEMPORAL_TYPE_NAMES[TemporalType.DATE.getValue()] = "date";
+ TEMPORAL_TYPE_NAMES[TemporalType.TIME.getValue()] = "time";
+ TEMPORAL_TYPE_NAMES[TemporalType.TIMESTAMP.getValue()] = "timestamp";
+ }
+
+ /** Returns the correct temporal type for hibernate */
+ private static String hbType(TemporalType temporalType) {
+ return TEMPORAL_TYPE_NAMES[temporalType != null ? temporalType
+ .getValue() : TemporalType.TIMESTAMP.getValue()];
+ }
+
+ /** logs it all */
+ // private static final Log log = LogFactory.getLog(AbstractMapper.class);
+ /** return the opposite of an association */
+ protected PAnnotatedEReference getOtherSide(PAnnotatedEReference paReference) {
+ // TODO assuming that mappedBy coincide with opposite, check in
+ // validation
+ if (paReference.getModelEReference().getEOpposite() == null) {
+ return null;
+ }
+ return paReference.getPaModel().getPAnnotated(
+ paReference.getModelEReference().getEOpposite());
+ }
+
+ /** The mapping context of this mapping action */
+ protected MappingContext hbmContext;
+
+ /**
+ * @return The mapping context used by this mapper
+ */
+ protected MappingContext getHbmContext() {
+ return hbmContext;
+ }
+
+ /** Set the hbm context */
+ protected void setHbmContext(MappingContext hbmContext) {
+ this.hbmContext = hbmContext;
+ }
+
+ protected void addAccessor(Element element, String propertyHandler) {
+ if (propertyHandler != null && propertyHandler.length() > 0) {
+ element.addAttribute("access", hbmContext.getPropertyHandlerName());
+ }
+ }
+
+ protected void addAccessor(Element element) {
+ addAccessor(element, hbmContext.getPropertyHandlerName());
+ }
+
+ protected void setType(PAnnotatedEStructuralFeature paFeature,
+ Element propElement) {
+ if (paFeature instanceof PAnnotatedEAttribute) {
+ setType((PAnnotatedEAttribute) paFeature, propElement);
+ } else {
+ setType((PAnnotatedEReference) paFeature, propElement);
+ }
+ }
+
+ /** Handles the External annotation */
+ protected void setType(PAnnotatedEReference paReference, Element propElement) {
+ final External external = paReference.getExternal();
+ if (external == null) {
+ throw new MappingException(
+ "External annotation not set on eReference "
+ + StoreUtil.toString(paReference
+ .getModelEReference()));
+ }
+
+ final Element typeElement = propElement.addElement("type");
+ if (external.getType() == null) { // standard external
+ typeElement.addAttribute("name", getHbmContext()
+ .getExternalUserType());
+ } else {
+ typeElement.addAttribute("name", external.getType());
+ }
+ typeElement
+ .addElement("param")
+ .addAttribute("name", HbMapperConstants.ECLASS_NAME_META)
+ .addText(
+ paReference.getModelEReference().getEReferenceType()
+ .getName());
+ typeElement
+ .addElement("param")
+ .addAttribute("name", HbMapperConstants.EPACKAGE_PARAM)
+ .addText(
+ paReference.getModelEReference().getEReferenceType()
+ .getEPackage().getNsURI());
+
+ }
+
+ /** Handles the type or typedef annotations */
+ protected void setType(PAnnotatedEAttribute paAttribute, Element propElement) {
+
+ // handle the type annotation
+ final HbAnnotatedEAttribute hea = (HbAnnotatedEAttribute) paAttribute;
+ final EDataType ed = (EDataType) hea.getModelEAttribute().getEType();
+ final HbAnnotatedEDataType hed = (HbAnnotatedEDataType) hea
+ .getPaModel().getPAnnotated(ed);
+
+ final String name;
+ final List<Parameter> params;
+ if (hea.getHbType() != null) {
+ name = hea.getHbType().getType();
+ params = hea.getHbType().getParameters();
+ } else if (hed != null && hed.getHbType() != null) {
+ name = hed.getHbType().getType();
+ params = hed.getHbType().getParameters();
+ } else if (hed != null && hed.getHbTypeDef() != null) {
+ name = hed.getHbTypeDef().getName();
+ params = null;
+ } else {
+ name = null;
+ params = null;
+ }
+ if (name != null) {
+ if (params == null || params.isEmpty()) {
+ // simple
+ propElement.addAttribute("type", name);
+ } else {
+ final Element typeElement = propElement.addElement("type")
+ .addAttribute("name", name);
+ for (Parameter param : params) {
+ typeElement.addElement("param")
+ .addAttribute("name", param.getName())
+ .addText(param.getValue());
+ }
+ }
+ } else if (paAttribute.getEnumerated() != null) {
+ handleEnumType(paAttribute, propElement);
+ } else if (StoreUtil.isQName(paAttribute.getModelEAttribute())) {
+ propElement.addAttribute("type",
+ "org.eclipse.emf.teneo.hibernate.mapping.QNameUserType");
+ } else {
+ final String hType = hbType(paAttribute);
+ if (hType != null) {
+ propElement.addAttribute("type", hType);
+ } else {
+ final Element typeElement = propElement.addElement("type")
+ .addAttribute("name", hbmContext.getDefaultUserType());
+ typeElement
+ .addElement("param")
+ .addAttribute("name", HbMapperConstants.EDATATYPE_PARAM)
+ .addText(
+ paAttribute.getModelEAttribute()
+ .getEAttributeType().getName());
+ typeElement
+ .addElement("param")
+ .addAttribute("name", HbMapperConstants.EPACKAGE_PARAM)
+ .addText(
+ paAttribute.getModelEAttribute().getEType()
+ .getEPackage().getNsURI());
+ }
+ }
+ }
+
+ /** Handle the enum type */
+ private void handleEnumType(PAnnotatedEAttribute paAttribute,
+ Element propElement) {
+ final Enumerated enumerated = paAttribute.getEnumerated();
+ assert (enumerated != null);
+ final EAttribute eattr = paAttribute.getModelEAttribute();
+ final EClassifier eclassifier = eattr.getEType();
+ if (!getHbmContext().isGeneratedByEMF()
+ && getHbmContext().getInstanceClass(eclassifier) != null) {
+ final Class<?> instanceClass = getHbmContext().getInstanceClass(
+ eclassifier);
+ final Element typeElement = propElement.addElement("type")
+ .addAttribute("name", getEnumUserType(enumerated));
+ typeElement.addElement("param")
+ .addAttribute("name", HbMapperConstants.ENUM_CLASS_PARAM)
+ .addText(instanceClass.getName());
+ typeElement.addElement("param")
+ .addAttribute("name", HbMapperConstants.ECLASSIFIER_PARAM)
+ .addText(eclassifier.getName());
+ typeElement.addElement("param")
+ .addAttribute("name", HbMapperConstants.EPACKAGE_PARAM)
+ .addText(eclassifier.getEPackage().getNsURI());
+ } else if (getHbmContext().isGeneratedByEMF()
+ && eclassifier.getInstanceClass() != null) {
+ final Element typeElement = propElement.addElement("type")
+ .addAttribute("name", getEnumUserType(enumerated));
+ typeElement.addElement("param")
+ .addAttribute("name", HbMapperConstants.ENUM_CLASS_PARAM)
+ .addText(eclassifier.getInstanceClass().getName());
+ typeElement.addElement("param")
+ .addAttribute("name", HbMapperConstants.ECLASSIFIER_PARAM)
+ .addText(eclassifier.getName());
+ typeElement.addElement("param")
+ .addAttribute("name", HbMapperConstants.EPACKAGE_PARAM)
+ .addText(eclassifier.getEPackage().getNsURI());
+ } else { // must be emf dynamic
+ final Element typeElement = propElement.addElement("type")
+ .addAttribute("name", hbDynamicEnumType(enumerated));
+ typeElement.addElement("param")
+ .addAttribute("name", HbMapperConstants.ECLASSIFIER_PARAM)
+ .addText(eclassifier.getName());
+ typeElement.addElement("param")
+ .addAttribute("name", HbMapperConstants.EPACKAGE_PARAM)
+ .addText(eclassifier.getEPackage().getNsURI());
+ }
+ }
+
+ // gather the pafeatures of the supertypes also
+ protected List<PAnnotatedEStructuralFeature> getAllFeatures(
+ PAnnotatedEClass componentAClass) {
+ final ArrayList<PAnnotatedEStructuralFeature> result = new ArrayList<PAnnotatedEStructuralFeature>();
+ result.addAll(componentAClass.getPaEStructuralFeatures());
+ for (EClass eClass : componentAClass.getModelEClass().getESuperTypes()) {
+ final PAnnotatedEClass aSuperClass = componentAClass.getPaModel()
+ .getPAnnotated(eClass);
+ if (aSuperClass != null) {
+ result.addAll(getAllFeatures(aSuperClass));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @return Returns the hibernate name for the given Ecore data type.
+ * @throws MappingException
+ * if no corresponding hb type is defined.
+ */
+ protected String hbType(PAnnotatedEAttribute paAttribute) {
+ final EAttribute eAttribute = paAttribute.getModelEAttribute();
+ final HbAnnotatedEDataType hed = (HbAnnotatedEDataType) paAttribute
+ .getPaModel().getPAnnotated(eAttribute.getEAttributeType());
+ final EDataType eDataType = paAttribute.getModelEAttribute()
+ .getEAttributeType();
+ if (hed != null && hed.getHbTypeDef() != null) {
+ return hed.getHbTypeDef().getName();
+ } else if (paAttribute.getLob() != null) {
+ if (EcoreDataTypes.INSTANCE.isByteArray(eDataType)) {
+ return "binary";
+ } else if (EcoreDataTypes.INSTANCE.isEString(eDataType)) {
+ return "text";
+ } else {
+ throw new MappingException(
+ "Lob annotations can only be used with Strings or byte arrays. "
+ + "Attribute is of type: " + eDataType);
+ }
+ } else if (EcoreDataTypes.INSTANCE.isEWrapper(eDataType)
+ || EcoreDataTypes.INSTANCE.isEPrimitive(eDataType)) {
+ return eDataType.getInstanceClassName();
+ } else if (EcoreDataTypes.INSTANCE.isEString(eDataType)) {
+ return eDataType.getInstanceClassName();
+ } else if (EcoreDataTypes.INSTANCE.isEDateTime(eDataType)
+ || (paAttribute.getTemporal() != null && paAttribute
+ .getTemporal().getValue().getValue() == TemporalType.TIMESTAMP_VALUE)) {
+ return getEDateTimeClass(paAttribute);
+ } else if (EcoreDataTypes.INSTANCE.isETime(eDataType)
+ || (paAttribute.getTemporal() != null && paAttribute
+ .getTemporal().getValue().getValue() == TemporalType.TIME_VALUE)) {
+ return getETimeClass(paAttribute);
+ } else if (EcoreDataTypes.INSTANCE.isEDuration(eDataType)) {
+ return hbmContext.getDurationType();
+ } else if (EcoreDataTypes.INSTANCE.isEDate(eDataType, getHbmContext()
+ .getPersistenceOptions())
+ || (paAttribute.getTemporal() != null && paAttribute
+ .getTemporal().getValue().getValue() == TemporalType.DATE_VALUE)) {
+ return getEDateClass(paAttribute);
+ } else if (eDataType.getInstanceClass() != null
+ && eDataType.getInstanceClass() == Object.class) {
+ // null forces caller to use usertype
+ return null; // "org.eclipse.emf.teneo.hibernate.mapping.DefaultToStringUserType";
+ // } else if (eDataType.getInstanceClass() != null) {
+ // return eDataType.getInstanceClassName();
+ } else {
+ final String result = EcoreDataTypes.INSTANCE
+ .getTargetTypeName(paAttribute);
+ if (result.compareTo(Object.class.getName()) == 0) {
+ // all edatatypes are translatable to a string, done by caller
+ return null; // "org.eclipse.emf.teneo.hibernate.mapping.DefaultToStringUserType";
+ }
+ return result;
+ }
+ }
+
+ /** Returns the type name of a many attribute */
+ protected String getTargetTypeName(PAnnotatedEAttribute aAttribute) {
+ final EAttribute eAttribute = aAttribute.getModelEAttribute();
+ // check on equality on object.class is used for listunion simpleunions
+ final Class<?> instanceClass = eAttribute.getEAttributeType()
+ .getInstanceClass();
+ if (instanceClass != null && !Object.class.equals(instanceClass)
+ && !List.class.equals(instanceClass)) {
+ if (instanceClass.isArray()) {
+ // get rid of the [] at the end
+ return eAttribute
+ .getEType()
+ .getInstanceClassName()
+ .substring(
+ 0,
+ eAttribute.getEType().getInstanceClassName()
+ .length() - 2);
+ }
+ return instanceClass.getName();
+ } else {
+ // the type is hidden somewhere deep get it
+ // the edatatype is the java.util.list
+ // it has an itemType which is the name of the element edatatype
+ // which contains the instanceclass
+ // takes also into account inheritance between datatypes
+ // NOTE the otm.targetentity can consist of a comma delimited list
+ // of target
+ // entities this is required for listunion types but is not
+ // according to the ejb3 spec!
+ ArrayList<EClassifier> eclassifiers = EcoreDataTypes.INSTANCE
+ .getItemTypes((EDataType) eAttribute.getEType());
+ if (eclassifiers.size() > 0) {
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < eclassifiers.size(); i++) {
+ final EClassifier eclassifier = eclassifiers.get(i);
+ if (i > 0) {
+ result.append(",");
+ }
+ result.append(eclassifier.getInstanceClassName());
+ }
+ return result.toString();
+ } else {
+ return Object.class.getName();
+ }
+ }
+ }
+
+ /**
+ * Returns the correct enum primitive hibernate type, for Elver this is a
+ * hibernate user type.
+ */
+ public String getEnumUserType(Enumerated enumerated) {
+ if (EnumType.STRING == enumerated.getValue()) {
+ return getHbmContext().getEnumUserType();
+ } else {
+ return getHbmContext().getEnumIntegerUserType();
+ }
+ }
+
+ /**
+ * Returns the correct enum primitive hibernate type, for Elver this is a
+ * hibernate user type.
+ */
+ protected String hbDynamicEnumType(Enumerated enumerated) {
+ if (EnumType.STRING == enumerated.getValue()) {
+ return getHbmContext().getDynamicEnumUserType();
+ } else {
+ return getHbmContext().getDynamicEnumIntegerUserType();
+ }
+ }
+
+ /*
+ * @return The name of the java class needed to map the date type
+ */
+ public String getEDateClass(PAnnotatedEAttribute paAttribute) {
+ final EDataType eDataType = paAttribute.getModelEAttribute()
+ .getEAttributeType();
+
+ assert (EcoreDataTypes.INSTANCE.isEDate(eDataType, getHbmContext()
+ .getPersistenceOptions()));
+
+ if (XMLTypePackage.eINSTANCE.getDate().equals(eDataType)) {
+ return getHbmContext().getXSDDateUserType();
+ }
+
+ if (paAttribute.getTemporal() != null) {
+ final TemporalType tt = paAttribute.getTemporal().getValue();
+ return hbType(tt);
+ }
+
+ // only override if the user did not specify a more specific class
+ if (EcoreDataTypes.INSTANCE.isEDate(eDataType, getHbmContext()
+ .getPersistenceOptions())) {
+ // EMF returns an XSD Date type as an Object instance. go figure.
+ // note that I would prefer to use the class instance to get the
+ // name
+ // but for other reasons I do not want to have references to the
+ // org.eclipse.emf.teneo.hibernate plugin.
+ return getHbmContext().getXSDDateUserType();
+ }
+
+ // TODO: should it not use the eDataType.getInstanceClass()? Hmm if the
+ // user
+ // really wants a different mapping he/she should use maybe a usertype??
+ return Date.class.getName();
+ }
+
+ /*
+ * @return The name of the java class needed to map the time type
+ */
+ public String getETimeClass(PAnnotatedEAttribute paAttribute) {
+ final EDataType eDataType = paAttribute.getModelEAttribute()
+ .getEAttributeType();
+
+ if (XMLTypePackage.eINSTANCE.getTime().equals(eDataType)) {
+ return getHbmContext().getXSDTimeUserType();
+ }
+
+ if (paAttribute.getTemporal() != null) {
+ final TemporalType tt = paAttribute.getTemporal().getValue();
+ return hbType(tt);
+ }
+
+ // bugzilla 277546
+ if (eDataType.getInstanceClass() != null
+ && Timestamp.class.isAssignableFrom(eDataType
+ .getInstanceClass())) {
+ return eDataType.getInstanceClass().getName();
+ }
+
+ if (EcoreDataTypes.INSTANCE.isETime(eDataType)) {
+ // EMF returns an XSD Date type as an Object instance. go figure.
+ // note that I would prefer to use the class instance to get the
+ // name
+ // but for other reasons I do not want to have references to the
+ // org.eclipse.emf.teneo.hibernate plugin.
+ return getHbmContext().getXSDTimeUserType();
+ }
+
+ // TODO: should it not use the eDataType.getInstanceClass()? Hmm if the
+ // user
+ // really wants a different mapping he/she should use maybe a usertype??
+ return Timestamp.class.getName();
+ }
+
+ /*
+ * @return The name of the java class needed to map the datetime/timestamp
+ * type
+ */
+ public String getEDateTimeClass(PAnnotatedEAttribute paAttribute) {
+ final EDataType eDataType = paAttribute.getModelEAttribute()
+ .getEAttributeType();
+
+ assert (EcoreDataTypes.INSTANCE.isEDateTime(eDataType));
+
+ if (XMLTypePackage.eINSTANCE.getDateTime().equals(eDataType)) {
+ return getHbmContext().getXSDDateTimeUserType();
+ }
+
+ if (paAttribute.getTemporal() != null) {
+ final TemporalType tt = paAttribute.getTemporal().getValue();
+ return hbType(tt);
+ }
+
+ // bugzilla 277546
+ if (eDataType.getInstanceClass() != null
+ && Date.class.isAssignableFrom(eDataType.getInstanceClass())) {
+ return eDataType.getInstanceClass().getName();
+ }
+
+ if (EcoreDataTypes.INSTANCE.isEDateTime(eDataType)) {
+ // EMF returns an XSD Date type as an Object instance. go figure.
+ // note that I would prefer to use the class instance to get the
+ // name
+ // but for other reasons I do not want to have references to the
+ // org.eclipse.emf.teneo.hibernate plugin.
+ return getHbmContext().getXSDDateTimeUserType();
+ }
+
+ // TODO: should it not use the eDataType.getInstanceClass()? Hmm if the
+ // user
+ // really wants a different mapping he/she should use maybe a usertype??
+ return Timestamp.class.getName();
+ }
+
+ /**
+ * Returns the (possibly overridden) JoinColumns annotations for the given
+ * reference or an empty list if no JoinColumns were defined.
+ */
+ protected List<JoinColumn> getJoinColumns(PAnnotatedEReference paReference) {
+ List<JoinColumn> joinColumns = getHbmContext().getAssociationOverrides(
+ paReference);
+ if (joinColumns == null) {
+ joinColumns = paReference.getJoinColumns();
+ }
+ if (joinColumns == null) {
+ return new ArrayList<JoinColumn>();
+ }
+ return joinColumns;
+ }
+
+ /** Adds a cache element */
+ protected void addCacheElement(Element parent, Cache cache) {
+ // translate to hibernate specific notation
+ final String usage = cache.getUsage().getName().toLowerCase()
+ .replaceAll("_", "-");
+
+ Element cacheElement = parent.addElement("cache").addAttribute("usage",
+ usage);
+ if (cache.getRegion() != null) {
+ cacheElement.addAttribute("region", cache.getRegion());
+ }
+ if (cache.getInclude() != null) {
+ cacheElement.addAttribute("include", cache.getInclude());
+ }
+ parent.remove(cacheElement);
+ parent.add(0, cacheElement);
+ }
+
+ /** Same as above only handles multiple columns */
+ protected void addColumnsAndFormula(Element propertyElement,
+ PAnnotatedEStructuralFeature pef, List<Column> columns,
+ boolean isNullable, boolean setColumnAttributesInProperty) {
+ addColumnsAndFormula(propertyElement, pef, columns, isNullable,
+ setColumnAttributesInProperty, false, false);
+ }
+
+ /** Same as above only handles multiple columns */
+ protected void addColumnsAndFormula(Element propertyElement,
+ PAnnotatedEStructuralFeature pef, List<Column> columns,
+ boolean isNullable, boolean setColumnAttributesInProperty,
+ boolean isUnique, boolean isIdProperty) {
+ // if no columns set then use some default
+ final HbAnnotatedETypeElement hbFeature = (HbAnnotatedETypeElement) pef;
+ if (columns.isEmpty() && hbFeature.getFormula() == null) {
+ final Column col = PannotationFactory.eINSTANCE.createColumn();
+ col.setName(getColumnName(pef));
+ col.setNullable(isNullable);
+ if (isIdProperty) {
+ col.setUnique(false);
+ } else {
+ col.setUnique(isUnique);
+ }
+
+ if (pef instanceof HbAnnotatedEAttribute
+ && ((HbAnnotatedEAttribute) pef).getGenerated() != null
+ && ((HbAnnotatedEAttribute) pef).getGenerated().getValue() != null
+ && ((HbAnnotatedEAttribute) pef).getGenerated().getValue() != GenerationTime.NEVER) {
+ col.setInsertable(false);
+ col.setUpdatable(false);
+ }
+
+ columns.add(col);
+ }
+ // if only one id column then it is not nullable!
+ if (isIdProperty && columns.size() == 1
+ && pef.getPaEClass().getIdClass() == null) {
+ columns.get(0).setNullable(false);
+ // set to false, see bugzilla 280169
+ columns.get(0).setUnique(false);
+ }
+
+ for (Column column : columns) {
+ addColumn(propertyElement, pef, column, isNullable,
+ setColumnAttributesInProperty);
+ }
+
+ // do the formula part
+ if (hbFeature.getFormula() != null) {
+ propertyElement.addElement("formula").addText(
+ hbFeature.getFormula().getValue());
+ }
+ }
+
+ protected String getColumnName(PAnnotatedEStructuralFeature pef) {
+ if (getHbmContext().getEmbeddingFeature() != null) { // embedded
+ // TODO: check illegal, embedded component can not really have an id
+ final PAnnotatedEStructuralFeature embeddingFeature = getHbmContext()
+ .getEmbeddingFeature();
+ return getHbmContext().getSqlNameStrategy().getColumnName(pef,
+ embeddingFeature.getModelEStructuralFeature().getName());
+ } else {
+ return getHbmContext().getSqlNameStrategy()
+ .getColumnName(pef, null);
+ }
+ }
+
+ /**
+ * Add a comment element, if the eModelElement has documentation, returns
+ * the comment element
+ */
+ protected Element addCommentElement(EModelElement eModelElement,
+ Element hbmElement) {
+ if (hbmContext.getMaximumCommentLength() == 0) {
+ return null;
+ }
+ final String commentData = EcoreUtil.getDocumentation(eModelElement);
+ if (commentData != null) {
+ final Element comment = hbmElement.addElement("comment");
+ String commentText = commentData.replace('\'', ' ').replace('"',
+ ' ');
+ if (commentText.length() > hbmContext.getMaximumCommentLength()) {
+ commentText = commentText.substring(0,
+ hbmContext.getMaximumCommentLength());
+ }
+ comment.addText(commentText);
+ return comment;
+ }
+ return null;
+ }
+
+ /** Adds anytype columns */
+ protected List<Column> getAnyTypeColumns(String featureName,
+ boolean isNullable) {
+ final ArrayList<Column> result = new ArrayList<Column>();
+ final Column typeColumn = PannotationFactory.eINSTANCE.createColumn();
+ typeColumn.setName(hbmContext.trunc(null, featureName + "_type"));
+ typeColumn.setNullable(isNullable);
+ result.add(typeColumn);
+ final Column idColumn = PannotationFactory.eINSTANCE.createColumn();
+ idColumn.setName(hbmContext.trunc(null, featureName + "_id"));
+ idColumn.setNullable(isNullable);
+ result.add(idColumn);
+ return result;
+ }
+
+ /**
+ * Returns the (possibly overridden) columns annotation for the given
+ * attribute.
+ */
+ protected List<Column> getColumns(PAnnotatedEStructuralFeature paFeature) {
+ final Column defaultColumn = paFeature.getColumn();
+ final Column oc = getHbmContext().getAttributeOverride(paFeature);
+
+ if (oc != null) {
+ final ArrayList<Column> result = new ArrayList<Column>();
+ result.add(oc);
+ return result;
+ }
+ // try multiple columns
+ final HbAnnotatedETypeElement hae = (HbAnnotatedETypeElement) paFeature;
+ if (hae.getHbColumns().size() > 0) {
+ return hae.getHbColumns();
+ }
+ final ArrayList<Column> result = new ArrayList<Column>();
+ if (defaultColumn != null) {
+ result.add(defaultColumn);
+ }
+ return result;
+ }
+
+ /** Sets property attributes on the basis of the column */
+ private void addColumn(Element propertyElement,
+ PAnnotatedEStructuralFeature pef, Column column,
+ boolean isNullable, boolean setColumnAttributesInProperty) {
+ if (column != null) {
+ if (setColumnAttributesInProperty) {
+ // this is not the nicest place to do this
+ if (propertyElement.getName().compareTo("property") == 0
+ || propertyElement.getName().compareTo("many-to-one") == 0) {
+ propertyElement.addAttribute("insert",
+ column.isInsertable() ? "true" : "false");
+ propertyElement.addAttribute("update",
+ column.isUpdatable() ? "true" : "false");
+ }
+ // MT: I think that the column nullability should not be used
+ // for setting not-null
+ // on the property, this is already specified by the optional
+ // attribute on the
+ // basic annotation. Maybe a check can be used instead to detect
+ // inconsistenties
+ // in the column attributes and the basic ann.
+ // Note that the ejb3 spec says that optional should be
+ // disregarded for primitive
+ // types which I
+ // do not understand.
+ // I disabled it for now to ignore for the test cases.
+ // MT05032006: After some more thought the column nullability
+ // can be used in case of
+ // single table inheritance mapping
+ if (!propertyElement.getName().equals("any")) {
+ propertyElement.addAttribute("not-null", isNullable
+ || column.isNullable() ? "false" : "true");
+ }
+ propertyElement.addAttribute("unique",
+ column.isUnique() ? "true" : "false");
+ }
+ addColumnElement(propertyElement, pef, column, isNullable);
+ }
+ }
+
+ protected void mapFilter(Element parentElement, List<Filter> filters) {
+ for (Filter filter : filters) {
+ final Element filterElement = parentElement.addElement("filter");
+ filterElement.addAttribute("name", filter.getName());
+ if (filter.getCondition() != null) {
+ filterElement.addAttribute("condition", filter.getCondition());
+ }
+ }
+ }
+
+ /**
+ * Creates cascades for onetoone/manytoone, they differ from many relations
+ * because no delete-orphan is supported.
+ *
+ * @param associationElement
+ * : the element to which the cascades are added.
+ * @param cascade
+ * : list of cascade annotation types
+ * @param addDeleteOrphan
+ * : if true then delete-orphan is added in case of cascade all
+ */
+ protected void addCascades(Element associationElement,
+ List<HbCascadeType> cascades, boolean addDeleteOrphan) {
+ if (!cascades.isEmpty()) {
+ StringBuffer sb = new StringBuffer();
+ for (HbCascadeType cascade : cascades) {
+ if (cascade == HbCascadeType.ALL) {
+ sb.append("all,"); // assuming all appears alone
+ if (addDeleteOrphan) {
+ // note comma at the end is trimmed off below
+ sb.append("delete-orphan,");
+ }
+ break;
+ } else if (cascade == HbCascadeType.PERSIST) {
+ sb.append("persist,");
+ } else if (cascade == HbCascadeType.MERGE) {
+ sb.append("merge,");
+ } else if (cascade == HbCascadeType.REFRESH) {
+ sb.append("refresh,");
+ } else if (cascade == HbCascadeType.REMOVE) {
+ sb.append("delete,");
+ } else if (cascade == HbCascadeType.DELETE) {
+ sb.append("delete,");
+ } else if (cascade == HbCascadeType.DELETE_ORPHAN) {
+ sb.append("delete-orphan,");
+ } else if (cascade == HbCascadeType.EVICT) {
+ sb.append("evict,");
+ } else if (cascade == HbCascadeType.LOCK) {
+ sb.append("lock,");
+ } else if (cascade == HbCascadeType.REPLICATE) {
+ sb.append("replicate,");
+ } else if (cascade == HbCascadeType.SAVE_UPDATE) {
+ sb.append("save-update,");
+ } else {
+ throw new MappingException("Cascade " + cascade.getName()
+ + " not supported");
+ }
+ }
+ associationElement.addAttribute("cascade",
+ sb.substring(0, sb.length() - 1));
+ }
+ }
+
+ /**
+ * Create an any Element
+ */
+ public Element createAny(String name,
+ PAnnotatedEStructuralFeature paFeature, Any any,
+ AnyMetaDef anyMetaDef, boolean isMany) {
+
+ final AnyMetaDef localAnyMetaDef;
+ if (anyMetaDef == null) {
+ localAnyMetaDef = HbannotationFactory.eINSTANCE.createAnyMetaDef();
+ localAnyMetaDef.setIdType("long");
+ } else {
+ localAnyMetaDef = anyMetaDef;
+ }
+ final Any localAny;
+ if (any == null) {
+ localAny = HbannotationFactory.eINSTANCE.createAny();
+ } else {
+ localAny = any;
+ }
+
+ final String tagName;
+ if (isMany) {
+ tagName = "many-to-any";
+ } else {
+ tagName = "any";
+ }
+
+ // don't know how to create an element, so add an remove it...
+ final Element anyElement = getHbmContext().getCurrent()
+ .addElement(tagName)
+ .addAttribute("id-type", localAnyMetaDef.getIdType())
+ .addAttribute("meta-type", localAnyMetaDef.getMetaType());
+ getHbmContext().getCurrent().remove(anyElement);
+
+ if (!isMany) {
+ anyElement.addAttribute("name", name);
+ final List<HbCascadeType> cascades = new ArrayList<HbCascadeType>();
+ if (paFeature instanceof HbAnnotatedEReference) {
+ if (((HbAnnotatedEReference) paFeature).getHbCascade() == null) {
+ cascades.add(HbCascadeType.ALL);
+ } else {
+ cascades.addAll(((HbAnnotatedEReference) paFeature)
+ .getHbCascade().getValue());
+ }
+ } else {
+ cascades.add(HbCascadeType.ALL);
+ }
+ addCascades(anyElement, cascades, isMany);
+ }
+
+ final List<Column> columns = new ArrayList<Column>();
+ if (localAny.getMetaColumn() != null) {
+ columns.add(localAny.getMetaColumn());
+ } else {
+ final Column typeColumn = PannotationFactory.eINSTANCE
+ .createColumn();
+ // bugzilla 294201, trunc is also done later in addColumn
+ // typeColumn.setName(hbmContext.trunc(paFeature.getModelEStructuralFeature().getName()
+ // + "_type"));
+ typeColumn.setName(paFeature.getModelEStructuralFeature().getName()
+ + "_type");
+ typeColumn.setNullable(localAny.isOptional());
+ columns.add(typeColumn);
+ }
+
+ if (paFeature.getColumn() != null) {
+ columns.add(paFeature.getColumn());
+ } else {
+ final Column idColumn = PannotationFactory.eINSTANCE.createColumn();
+ // bugzilla 294201, trunc is also done later in addColumn
+ // idColumn.setName(hbmContext.trunc(paFeature.getModelEStructuralFeature().getName()
+ // + "_id"));
+ idColumn.setName(paFeature.getModelEStructuralFeature().getName()
+ + "_id");
+ idColumn.setNullable(localAny.isOptional());
+ columns.add(idColumn);
+ }
+ addColumnsAndFormula(anyElement, paFeature, columns, paFeature
+ .getModelEStructuralFeature().isRequired(), false);
+ return anyElement;
+ }
+
+ /**
+ * Add a columnelement to the property, takes into account length, precision
+ * etc. forceNullable is set when the feature belongs to a featuremap
+ */
+ private void addColumnElement(Element propertyElement,
+ PAnnotatedEStructuralFeature pef, Column column,
+ boolean forceNullable) {
+ if (column != null) {
+ Element columnElement = propertyElement
+ .addElement("column")
+ .addAttribute(
+ "not-null",
+ column.isNullable() || forceNullable ? "false"
+ : "true")
+ .addAttribute("unique",
+ column.isUnique() ? "true" : "false");
+ final String name;
+ if (column.getName() != null) {
+ name = column.getName();
+ } else {
+ if (getHbmContext().getEmbeddingFeature() != null) { // embedded
+ // TODO: check illegal, embedded component can not really
+ // have an id
+ final PAnnotatedEStructuralFeature embeddingFeature = getHbmContext()
+ .getEmbeddingFeature();
+ name = getHbmContext().getSqlNameStrategy().getColumnName(
+ pef,
+ embeddingFeature.getModelEStructuralFeature()
+ .getName());
+ } else {
+ name = getHbmContext().getSqlNameStrategy().getColumnName(
+ pef, null);
+ }
+ }
+ if (column.getUniqueKey() != null) {
+ columnElement.addAttribute("unique-key", column.getUniqueKey());
+ }
+ columnElement.addAttribute("name",
+ getHbmContext().trunc(column, name));
+ if (column.isSetLength()) {
+ columnElement.addAttribute("length",
+ Integer.toString(column.getLength()));
+ }
+ if (column.isSetPrecision()) {
+ columnElement.addAttribute("precision",
+ Integer.toString(column.getPrecision()));
+ }
+ if (column.isSetScale()) {
+ columnElement.addAttribute("scale",
+ Integer.toString(column.getScale()));
+ }
+ if (column.getColumnDefinition() != null) {
+ columnElement.addAttribute("sql-type",
+ column.getColumnDefinition());
+ }
+ final String uc = getHbmContext().getUniqueConstraintKey(name);
+ if (uc != null) {
+ columnElement.addAttribute("unique-key", uc);
+ }
+ if (pef instanceof HbAnnotatedETypeElement
+ && ((HbAnnotatedETypeElement) pef).getHbIndex() != null) {
+ final Index index = ((HbAnnotatedETypeElement) pef)
+ .getHbIndex();
+ columnElement.addAttribute("index", index.getName());
+ }
+
+ // --- JJH, adapted by MT
+ addCommentElement(pef.getModelElement(), columnElement);
+ // --- JJH
+ }
+ }
+
+ /** Add the ondelete mapping to the key */
+ protected void handleOndelete(Element keyElement, OnDelete onDelete) {
+ // if (true || onDelete == null) {
+ // return;
+ // }
+ //
+ // if (onDelete.getAction().equals(OnDeleteAction.CASCADE)) {
+ // keyElement.addAttribute("on-delete", "cascade");
+ // } else {
+ // keyElement.addAttribute("on-delete", "noaction");
+ // }
+ }
+
+ /** Returns true if the target is the general EObject type */
+ protected boolean isEObject(String typeName) {
+ if (typeName == null) {
+ return false;
+ }
+ return typeName.compareTo(EntityNameStrategy.EOBJECT_ECLASS_NAME) == 0;
+ }
+} \ No newline at end of file

Back to the top