/**
* <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 - Initial API and implementation
*
* </copyright>
*
* $Id: ClassicSQLNameStrategy.java,v 1.14 2008/03/17 19:30:14 mtaal Exp $
*/
package org.eclipse.emf.teneo.mapping.strategy.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.teneo.PersistenceOptions;
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.pamodel.PAnnotatedModel;
import org.eclipse.emf.teneo.extension.ExtensionManager;
import org.eclipse.emf.teneo.extension.ExtensionManagerAware;
import org.eclipse.emf.teneo.mapping.strategy.EntityNameStrategy;
import org.eclipse.emf.teneo.mapping.strategy.SQLNameStrategy;
import org.eclipse.emf.teneo.mapping.strategy.StrategyUtil;
import org.eclipse.emf.teneo.util.AssertUtil;
/**
* Implements the sql naming strategy of older versions of Teneo. This implementation is driven by
* the options set in the PersistenceOptions.
*
* @author <a href="mtaal@elver.org">Martin Taal</a>
* @version $Revision: 1.14 $
*/
public class ClassicSQLNameStrategy implements SQLNameStrategy, ExtensionManagerAware {
// The logger
protected static final Log log = LogFactory.getLog(ClassicSQLNameStrategy.class);
// The local members for several options
protected String optionJoinTableNamingStrategy;
protected String optionJoinColumnNamingStrategy;
protected int optionMaximumSqlLength;
protected EntityNameStrategy entityNameStrategy;
protected PersistenceOptions persistenceOptions;
protected boolean optionSQLUpperCase = false;
protected boolean optionSQLLowerCase = false;
private ExtensionManager extensionManager;
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getPrimaryKeyJoinColumnName(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEClass,
* java.lang.String)
*/
public String getPrimaryKeyJoinColumnName(PAnnotatedEClass aSuperClass, String idFeature) {
return convert(getEntityName(aSuperClass.getPaModel(), aSuperClass.getModelEClass()) + "_" + idFeature, true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getSecondaryTablePrimaryKeyJoinColumnName(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEStructuralFeature)
*/
public String getSecondaryTablePrimaryKeyJoinColumnName(PAnnotatedEStructuralFeature iddef) {
return convert(iddef.getModelEStructuralFeature().getName());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getTableName(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEClass)
*/
public String getTableName(PAnnotatedEClass aClass) {
return convert(getEntityName(aClass.getPaModel(), aClass.getModelEClass()));
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getColumnName(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEStructuralFeature)
*/
public String getColumnName(PAnnotatedEStructuralFeature aStructuralFeature, String prefix) {
if (prefix != null) {
return convert(prefix + "_" + aStructuralFeature.getModelEStructuralFeature().getName());
}
return convert(aStructuralFeature.getModelEStructuralFeature().getName());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getForeignKeyName(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEStructuralFeature)
*/
public String getForeignKeyName(PAnnotatedEStructuralFeature aFeature) {
final PAnnotatedEClass aClass = aFeature.getPaEClass();
return convert(getEntityName(aClass.getPaModel(), aClass.getModelEClass()) + "_" +
aFeature.getModelEStructuralFeature().getName(), true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getManyToOneJoinColumnNames(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEReference)
*/
public List<String> getManyToOneJoinColumnNames(PAnnotatedEReference aReference) {
final EReference eref = aReference.getModelEReference();
// isTransient occurs for computed featuremap features, these are ignored
// later on
assert (eref.isTransient() || !eref.isMany()); // otherwise this should have been a mtm
// in case of many-to-one to qualify use the name of the class to which is refered
// this is just there for backward compatibility, see the case of
// the manytoone and onetoone below.
final PAnnotatedEClass aClass;
if (eref.getEOpposite() == null) {
aClass = aReference.getAReferenceType();
} else {
// the aclass is just the class of the structuralfeature itself.
// this is the most common case the name of the join column reflects
// the owner of the one-to-many
aClass = aReference.getPaEClass();
}
final String typeName = aClass.getModelEClass().getName();
final String featureName = eref.getName();
final List<String> result = new ArrayList<String>();
final List<String> names =
StrategyUtil.getIDFeaturesNames(aClass, persistenceOptions.getDefaultIDFeatureName());
final boolean simpleNaming = optionJoinColumnNamingStrategy.compareTo("simple") == 0;
for (String name : names) {
final String postFix;
if (names.size() == 1 && simpleNaming) {
postFix = "";
} else {
postFix = "_" + name;
}
final String jcName;
if (simpleNaming) {
jcName = featureName + postFix;
} else { // backward compatibility
jcName = typeName + "_" + featureName + postFix;
}
result.add(convert(jcName, true));
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getOneToManyEAttributeJoinColumns(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEAttribute)
*/
public List<String> getOneToManyEAttributeJoinColumns(PAnnotatedEAttribute aAttribute) {
final PAnnotatedEClass aClass = aAttribute.getPaEClass();
final String typeName = aClass.getModelEClass().getName();
final String featureName = aAttribute.getModelEAttribute().getName();
final List<String> result = new ArrayList<String>();
final List<String> names =
StrategyUtil.getIDFeaturesNames(aClass, persistenceOptions.getDefaultIDFeatureName());
final boolean simpleNaming = optionJoinColumnNamingStrategy.compareTo("simple") == 0;
for (String name : names) {
final String postFix;
if (names.size() == 1 && simpleNaming) {
postFix = "";
} else {
postFix = "_" + name;
}
final String jcName = typeName + "_" + featureName + postFix;
result.add(convert(jcName, true));
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getOneToManyEReferenceJoinColumns(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEReference)
*/
public List<String> getOneToManyEReferenceJoinColumns(PAnnotatedEReference aReference) {
final PAnnotatedEClass aClass = aReference.getPaEClass();
final String typeName;
final String featureName;
// for backwards compatibility if the other side is there then use the name
// of the other side for the typeName and featureName. The many-to-one determines
// the naming
if (aReference.getModelEReference().getEOpposite() != null) {
typeName = aReference.getAReferenceType().getModelEClass().getName();
featureName = aReference.getModelEReference().getEOpposite().getName();
} else {
typeName = aClass.getModelEClass().getName();
featureName = aReference.getModelEReference().getName();
}
final List<String> result = new ArrayList<String>();
final List<String> names =
StrategyUtil.getIDFeaturesNames(aClass, persistenceOptions.getDefaultIDFeatureName());
final boolean simpleNaming = optionJoinColumnNamingStrategy.compareTo("simple") == 0;
for (String name : names) {
final String postFix;
if (names.size() == 1 && simpleNaming) {
postFix = "";
} else {
postFix = "_" + name;
}
final String jcName = typeName + "_" + featureName + postFix;
result.add(convert(jcName, true));
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getJoinTableJoinColumns(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEReference,
* boolean)
*/
public List<String> getJoinTableJoinColumns(PAnnotatedEReference aReference, boolean inverse) {
final PAnnotatedEClass aClass;
final String typeName;
String featureName;
if (inverse) {
aClass = aReference.getAReferenceType();
if (aReference.getModelEReference().getEOpposite() != null) {
typeName = aReference.getAReferenceType().getModelEClass().getName();
featureName = "_" + aReference.getModelEReference().getEOpposite().getName();
} else {
typeName = aReference.getAReferenceType().getModelEClass().getName();
featureName = "";
}
} else {
aClass = aReference.getPaEClass();
typeName = aClass.getModelEClass().getName();
featureName = "_" + aReference.getModelEReference().getName();
}
// for backward compatibility, only use featurename if the reference is
// to itself
if (aReference.getAReferenceType() != aReference.getPaEClass()) {
featureName = "";
}
final List<String> result = new ArrayList<String>();
final List<String> names =
StrategyUtil.getIDFeaturesNames(aClass, persistenceOptions.getDefaultIDFeatureName());
final boolean simpleNaming = optionJoinColumnNamingStrategy.compareTo("simple") == 0;
for (String name : names) {
final String postFix;
if (names.size() == 1 && simpleNaming) {
postFix = "";
} else {
postFix = "_" + name;
}
final String jcName = typeName + featureName + postFix;
result.add(convert(jcName, true));
}
return result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getJoinTableName(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEAttribute)
*/
public String getJoinTableName(PAnnotatedEAttribute aAttribute) {
// note for array the isMany is false, so disable this check
// assert (aAttribute.getModelEAttribute().isMany());
final PAnnotatedEClass aClass = aAttribute.getPaEClass();
return convert(getEntityName(aClass.getPaModel(), aClass.getModelEClass()) + "_" +
aAttribute.getModelEAttribute().getName(), true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getJoinTableName(org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEReference)
*/
public String getJoinTableName(PAnnotatedEReference aReference) {
final EReference eReference = aReference.getModelEReference();
final boolean isEObject = eReference.getEType() == ClassicEntityNameStrategy.EOBJECT_ECLASS;
final String jTableName;
EReference eOpposite = eReference.getEOpposite();
if (aReference.getManyToMany() != null && aReference.getManyToMany().isIndexed()) {
// In case the reference is not indexed then one join table can be
// used for both sides
// If indexed then separate join tables should be used.
eOpposite = null; // trick to force a specific naming
}
if (!isEObject && optionJoinTableNamingStrategy.compareToIgnoreCase("ejb3") == 0) {
// table name is the entityname of the eclass of the reference and entityname of
// the eclass of the refered to
final String thisEntityName = getEntityName(aReference.getPaModel(), eReference.getEContainingClass());
final String thatEntityName = getEntityName(aReference.getPaModel(), eReference.getEReferenceType());
if (eOpposite != null && eOpposite.isMany() && compareNames(eReference, eOpposite)) {
jTableName = thatEntityName + "_" + thisEntityName;
} else {
jTableName = thisEntityName + "_" + thatEntityName;
}
} else {
AssertUtil.assertTrue("option optionJoinTableNamingStrategy " + optionJoinTableNamingStrategy +
" not supported", isEObject || optionJoinTableNamingStrategy.compareToIgnoreCase("unique") == 0);
if (eOpposite != null && eOpposite.isMany() && compareNames(eReference, eOpposite)) {
final String thatEntityName = getEntityName(aReference.getPaModel(), eOpposite.getEContainingClass());
jTableName = thatEntityName + "_" + eOpposite.getName();
} else {
final String thisEntityName = getEntityName(aReference.getPaModel(), eReference.getEContainingClass());
jTableName = thisEntityName + "_" + eReference.getName();
}
}
return convert(jTableName);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getDiscriminatorColumnName()
*/
public String getDiscriminatorColumnName() {
return convert("DTYPE"); // replace with constant somewhere
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getVersionColumnName()
*/
public String getVersionColumnName() {
return convert(persistenceOptions.getVersionColumnName());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getIdBagIDColumn()
*/
public String getIdBagIDColumn() {
return convert(persistenceOptions.getIDBagIDColumnName());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getSyntheticIDColumnName()
*/
public String getSyntheticIDColumnName() {
return convert(persistenceOptions.getIdColumnName());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#setPersistenceOptions(org.eclipse.emf.teneo.PersistenceOptions)
*/
public void setPersistenceOptions(PersistenceOptions po) {
optionMaximumSqlLength = po.getMaximumSqlNameLength();
optionJoinTableNamingStrategy = po.getJoinTableNamingStrategy();
optionJoinColumnNamingStrategy = po.getJoinColumnNamingStrategy();
final String optionSQLCaseStrategy = po.getSQLCaseStrategy();
if (optionSQLCaseStrategy.toLowerCase().compareTo("lowercase") == 0) {
optionSQLLowerCase = true;
} else if (optionSQLCaseStrategy.toLowerCase().compareTo("uppercase") == 0) {
optionSQLUpperCase = true;
}
persistenceOptions = po;
}
// Returns the entityname of the refered to entity
private String getEntityName(PAnnotatedModel paModel, EClass eClass) {
return StrategyUtil.getEntityName(getEntityNameStrategy(), persistenceOptions, paModel, eClass);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#convert(java.lang.String)
*/
public String convert(String name) {
return convert(name, false);
}
public String convert(String name, boolean truncPrefix) {
final String result = trunc(optionMaximumSqlLength, name, truncPrefix);
if (optionSQLLowerCase) {
return result.toLowerCase();
} else if (optionSQLUpperCase) {
return result.toUpperCase();
} else {
return result;
}
}
/**
* Determines where to place a certain annotation/characteristic, this is done by comparing
* names..
*/
private boolean compareNames(EReference here, EReference there) {
final String nameHere = here.getEContainingClass().getName() + here.getName();
final String nameThere = there.getEContainingClass().getName() + there.getName();
assert (nameHere.compareTo(nameThere) != 0);
return nameHere.compareTo(nameThere) > 0;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getExtensionManager()
*/
public ExtensionManager getExtensionManager() {
return extensionManager;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#setExtensionManager(org.eclipse.emf.teneo.extension.ExtensionManager)
*/
public void setExtensionManager(ExtensionManager extensionManager) {
this.extensionManager = extensionManager;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.teneo.mapping.strategy.SqlNameStrategy#getEntityNameStrategy()
*/
public EntityNameStrategy getEntityNameStrategy() {
if (entityNameStrategy == null) {
entityNameStrategy = getExtensionManager().getExtension(EntityNameStrategy.class);
}
return entityNameStrategy;
}
/**
* Utility method to truncate a column/table name, the truncPrefix determines if the part before
* the _ (the prefix) or after the _ (the suffix) is truncated. A _ often occurs in a jointable
* name.
*/
protected String trunc(int optionMaximumSqlLength, String truncName, boolean truncPrefix) {
final String correctedName = truncName.replace('.', '_');
if (optionMaximumSqlLength == -1) {
return correctedName;
}
if (correctedName.length() < optionMaximumSqlLength) {
return correctedName;
}
if (!truncPrefix) { // this truncs away the suffix
return correctedName.substring(0, optionMaximumSqlLength);
}
// truncate the part before the last _ because this is often the suffix
final int underscore = correctedName.lastIndexOf('_');
if (underscore != -1 && underscore > 0) {
final String usStr = correctedName.substring(underscore);
if ((optionMaximumSqlLength - usStr.length()) < 0) {
return correctedName;
}
return correctedName.substring(0, optionMaximumSqlLength - usStr.length()) + usStr;
}
return correctedName.substring(0, optionMaximumSqlLength);
}
}