/**
* <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: BasicMapper.java,v 1.34 2008/12/16 20:40:29 mtaal Exp $
*/
package org.eclipse.emf.teneo.hibernate.mapper;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEAttribute;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEReference;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEStructuralFeature;
import org.eclipse.emf.teneo.annotations.pannotation.Basic;
import org.eclipse.emf.teneo.annotations.pannotation.Column;
import org.eclipse.emf.teneo.annotations.pannotation.FetchType;
import org.eclipse.emf.teneo.annotations.pannotation.ManyToOne;
import org.eclipse.emf.teneo.annotations.pannotation.PannotationFactory;
import org.eclipse.emf.teneo.annotations.pannotation.TemporalType;
import org.eclipse.emf.teneo.extension.ExtensionPoint;
import org.eclipse.emf.teneo.hibernate.hbannotation.Index;
import org.eclipse.emf.teneo.hibernate.hbmodel.HbAnnotatedEAttribute;
import org.eclipse.emf.teneo.hibernate.hbmodel.HbAnnotatedETypeElement;
import org.eclipse.emf.teneo.simpledom.Element;
/**
* Maps a basic element to its mapping Context.
*
* @author <a href="mailto:mtaal at elver.org">Martin Taal</a>
*/
public class BasicMapper extends AbstractMapper implements ExtensionPoint {
/** Log it all */
private static final Log log = LogFactory.getLog(BasicMapper.class);
/**
* Generate hb mapping for the given basic attribute.
*/
public void processBasic(PAnnotatedEAttribute paAttribute) {
log.debug("processBasic " + paAttribute.getModelEAttribute().getName());
final EAttribute eattr = paAttribute.getModelEAttribute();
final String attrName = getHbmContext().getPropertyName(eattr);
final Element propElement = getHbmContext().getCurrent().addElement(
"property").addAttribute("name", attrName);
Basic basic = paAttribute.getBasic();
if (basic == null) {
basic = PannotationFactory.eINSTANCE.createBasic();
}
propElement.addAttribute("lazy", FetchType.LAZY
.equals(basic.getFetch()) ? "true" : "false");
addColumnsAndFormula(propElement, paAttribute, getColumns(paAttribute),
isNullable(basic, paAttribute), true);
// todo check: not-null is also set in the call to addcolumns, decide
// were to do what!
final boolean isNullable = isNullable(basic, paAttribute);
propElement.addAttribute("not-null", isNullable ? "false" : "true");
setType(paAttribute, propElement);
if (((HbAnnotatedEAttribute) paAttribute).getGenerated() != null
&& ((HbAnnotatedEAttribute) paAttribute).getGenerated()
.getValue() != null) {
propElement.addAttribute("generated",
((HbAnnotatedEAttribute) paAttribute).getGenerated()
.getValue().getName().toLowerCase());
}
if (((HbAnnotatedEAttribute) paAttribute).getHbIndex() != null) {
final Index index = ((HbAnnotatedEAttribute) paAttribute)
.getHbIndex();
propElement.addAttribute("index", index.getName());
}
addAccessor(propElement);
addNaturalId((HbAnnotatedEAttribute) paAttribute, propElement);
}
/** Processes an EReference which should be stored as an URI */
public void processExternalEReference(PAnnotatedEReference paReference) {
log.debug("processExternal "
+ paReference.getModelEReference().getName());
final EReference eref = paReference.getModelEReference();
final String propName = getHbmContext().getPropertyName(eref);
final Element propElement = getHbmContext().getCurrent().addElement(
"property").addAttribute("name", propName);
ManyToOne mto = paReference.getManyToOne();
if (mto == null) {
mto = PannotationFactory.eINSTANCE.createManyToOne();
}
propElement.addAttribute("lazy",
FetchType.LAZY.equals(mto.getFetch()) ? "true" : "false");
final boolean isNullable = isNullable(mto, paReference);
addColumnsAndFormula(propElement, paReference, getColumns(paReference),
isNullable, true);
// todo check: not-null is also set in the call to addcolumns, decide
// were to do what!
propElement.addAttribute("not-null", isNullable ? "false" : "true");
setType(paReference, propElement);
if (((HbAnnotatedETypeElement) paReference).getHbIndex() != null) {
final Index index = ((HbAnnotatedETypeElement) paReference)
.getHbIndex();
propElement.addAttribute("index", index.getName());
}
addAccessor(propElement);
}
/**
* Generate hb mapping for the given temporal attribute.
*/
public void processTemporal(PAnnotatedEAttribute paAttribute) {
log.debug("processTemporal "
+ paAttribute.getModelEAttribute().getName());
TemporalType tt = paAttribute.getTemporal().getValue();
final String attrName = getHbmContext().getPropertyName(
paAttribute.getModelEAttribute());
log.debug("addProperty: " + attrName + " temporal " + tt.getName());
final Element propElement = getHbmContext().getCurrent().addElement(
"property").addAttribute("name", attrName);
Basic basic = paAttribute.getBasic();
if (basic == null) {
basic = PannotationFactory.eINSTANCE.createBasic();
}
propElement.addAttribute("lazy", FetchType.LAZY
.equals(basic.getFetch()) ? "true" : "false");
addColumnsAndFormula(propElement, paAttribute, getColumns(paAttribute),
isNullable(basic, paAttribute), true);
// todo check: not-null is also set in the call to addcolumns, decide
// were to do what!
propElement.addAttribute("not-null",
isNullable(basic, paAttribute) ? "false" : "true");
if (((HbAnnotatedEAttribute) paAttribute).getGenerated() != null
&& ((HbAnnotatedEAttribute) paAttribute).getGenerated()
.getValue() != null) {
propElement.addAttribute("generated",
((HbAnnotatedEAttribute) paAttribute).getGenerated()
.getValue().getName().toLowerCase());
}
// #191463
setType(paAttribute, propElement);
addAccessor(propElement);
addNaturalId((HbAnnotatedEAttribute) paAttribute, propElement);
}
/**
* Generate hb mapping for the given lob attribute.
*/
public void processLob(PAnnotatedEAttribute paAttribute) {
final EAttribute eAttribute = paAttribute.getModelEAttribute();
log.debug("processLob " + eAttribute.getName());
final Element propElement = getHbmContext().getCurrent().addElement(
"property");
propElement.addAttribute("name", getHbmContext().getPropertyName(
eAttribute));
Basic basic = paAttribute.getBasic();
if (basic == null) {
basic = PannotationFactory.eINSTANCE.createBasic();
}
propElement.addAttribute("lazy", FetchType.LAZY
.equals(basic.getFetch()) ? "true" : "false");
addColumnsAndFormula(propElement, paAttribute, getColumns(paAttribute),
isNullable(basic, paAttribute), true);
final boolean isNullable = isNullable(basic, paAttribute);
final boolean isNullable2 = isNullable(basic, paAttribute);
propElement.addAttribute("not-null", isNullable ? "false" : "true");
setType(paAttribute, propElement);
addAccessor(propElement);
addNaturalId((HbAnnotatedEAttribute) paAttribute, propElement);
}
/**
* Generate hb mapping for the given enum attribute.
*/
public void processEnum(PAnnotatedEAttribute paAttribute) {
log.debug("processEnum " + paAttribute.getModelEAttribute());
Basic basic = paAttribute.getBasic();
if (basic == null) {
basic = PannotationFactory.eINSTANCE.createBasic();
}
final List<Column> columns = getColumns(paAttribute);
final Element propElement = getHbmContext().getCurrent().addElement(
"property").addAttribute(
"name",
getHbmContext().getPropertyName(
paAttribute.getModelEAttribute()));
propElement.addAttribute("lazy", FetchType.LAZY
.equals(basic.getFetch()) ? "true" : "false");
propElement.addAttribute("not-null",
isNullable(basic, paAttribute) ? "false" : "true");
addColumnsAndFormula(propElement, paAttribute, columns, isNullable(
basic, paAttribute)
|| getHbmContext().isCurrentElementFeatureMap(), true);
setType(paAttribute, propElement);
addAccessor(propElement);
addNaturalId((HbAnnotatedEAttribute) paAttribute, propElement);
}
/**
* Generate hb mapping for the given version attribute.
*/
public void processVersion(PAnnotatedEAttribute paAttribute) {
if (log.isDebugEnabled()) {
log.debug("Generating version for "
+ paAttribute.getModelEAttribute().getName());
}
final EAttribute eAttribute = paAttribute.getModelEAttribute();
final Element propElement = getHbmContext().getCurrent().addElement(
"version").addAttribute("name", eAttribute.getName());
List<Column> columns = getColumns(paAttribute);
if (columns.size() > 1) {
log
.warn("Version has more than one attribute, only using the first one, eclass: "
+ paAttribute.getModelEAttribute()
.getEContainingClass().getName());
}
addColumnsAndFormula(propElement, paAttribute, columns, getHbmContext()
.isCurrentElementFeatureMap(), false);
setType(paAttribute, propElement);
addAccessor(propElement, hbmContext.getVersionPropertyHandlerName());
addNaturalId((HbAnnotatedEAttribute) paAttribute, propElement);
}
protected void addNaturalId(HbAnnotatedEAttribute hbAttr, Element element) {
if (hbAttr.getNaturalId() != null) {
element.addAttribute(HbMapperConstants.NATURAL_ID_ATTR, Boolean
.toString(hbAttr.getNaturalId().isMutable()));
}
}
/**
* Ignore transient attributes.
*/
public void processTransient(PAnnotatedEStructuralFeature paFeature) {
if (log.isDebugEnabled()) {
log.debug("Skipping transient feature for "
+ paFeature.getModelEStructuralFeature().getName());
}
}
/**
* A prop is nullable if the basic is optional or the feature is part of a
* featuremap. The last reason is because featuremapentries will have all
* the features of the featuremap with only one of them filled.
*/
private boolean isNullable(Basic basic, PAnnotatedEAttribute aattr) {
// actually aattr.getColumn() should never be null as the default
// annotator
// always adds columns...
// has been changed from this commented code to the code below because
// of bugzilla: 224536 which gives the column annotation precedence
// over the basis annotation.
// return getHbmContext().isForceOptional() || basic.isOptional() ||
// getHbmContext().isCurrentElementFeatureMap() &&
// (aattr.getColumn() != null || aattr.getColumn().isNullable());
return getHbmContext().isDoForceOptional(aattr)
|| ((aattr.getColumn() == null || !aattr.getColumn()
.isSetNullable()) && basic.isOptional())
|| getHbmContext().isCurrentElementFeatureMap()
|| (aattr.getColumn() != null && aattr.getColumn().isNullable());
}
private boolean isNullable(ManyToOne mto,
PAnnotatedEStructuralFeature paFeature) {
// actually aattr.getColumn() should never be null as the default
// annotator
// always adds columns...
// has been changed from this commented code to the code below because
// of bugzilla: 224536 which gives the column annotation precedence
// over the basis annotation.
// return getHbmContext().isForceOptional() || basic.isOptional() ||
// getHbmContext().isCurrentElementFeatureMap() &&
// (aattr.getColumn() != null || aattr.getColumn().isNullable());
return getHbmContext().isDoForceOptional(paFeature)
|| ((paFeature.getColumn() == null || !paFeature.getColumn()
.isSetNullable()) && mto.isOptional())
|| getHbmContext().isCurrentElementFeatureMap()
|| (paFeature.getColumn() != null && paFeature.getColumn()
.isNullable());
}
}