/**
* Copyright (C) 2001-2005 France Telecom R&D
*/
package org.objectweb.speedo.generation.mivisitor.jdo;
import java.util.HashMap;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.api.SpeedoProperties;
import org.objectweb.speedo.generation.mivisitor.AbstractMetaInfoVisitor;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.metadata.SpeedoCollection;
import org.objectweb.speedo.metadata.SpeedoColumn;
import org.objectweb.speedo.metadata.SpeedoDiscriminator;
import org.objectweb.speedo.metadata.SpeedoExtension;
import org.objectweb.speedo.metadata.SpeedoField;
import org.objectweb.speedo.metadata.SpeedoInheritance;
import org.objectweb.speedo.metadata.SpeedoMap;
import org.objectweb.speedo.metadata.SpeedoTable;
import org.objectweb.util.monolog.api.BasicLevel;
/**
* Translates JDO extension dedicated for the mapping into normal meta
* information (non extension meta object).
*
* @author S.Chassande-Barrioz
*/
public class MappingExtension2Jdo
extends AbstractMetaInfoVisitor
implements SpeedoProperties {
public MappingExtension2Jdo(Personality p) {
super(p);
}
private void deprecate(String ext, String msg) {
logger.log(BasicLevel.INFO,
"Extension '" + ext + " is deprecated: " + msg);
}
public void visitExtension(SpeedoExtension se) throws SpeedoException {
logger.log(BasicLevel.DEBUG, "Extension '" + se.key + "=" + se.value);
if (se.owner instanceof SpeedoClass) {
SpeedoClass sc = (SpeedoClass) se.owner;
//Main table name
if (SQL_NAME.equals(se.key)) {
sc.mainTable = new SpeedoTable();
sc.mainTable.name = se.value;
sc.mainTable.catalog = null;
sc.mainTable.schema = null;
} else if (INHERITANCE_FILTER.equals(se.key)) {
setDiscriminatorElement(sc, se.value);
} else if (INHERITANCE_KEY.equals(se.key)) {
if (sc.inheritance == null) {
sc.inheritance = new SpeedoInheritance(sc);
}
if (sc.inheritance.discriminatorValues == null) {
sc.inheritance.discriminatorValues = new HashMap();
}
SpeedoDiscriminator sd = sc.inheritance.discriminator;
if (sd == null || !sd.hasDiscriminator()) {
//find the discriminator
SpeedoClass current = sc;
while (current != null && sd == null) {
if (current.inheritance != null
&& current.inheritance.discriminator != null
&& current.inheritance.discriminator.hasDiscriminator()) {
sd = current.inheritance.discriminator;
} else {
String f = current.getExtensionValueByKey(INHERITANCE_FILTER);
if (f != null) {
sd = setDiscriminatorElement(current, f);
}
}
if (sd == null) {
current = current.getSuper();
}
}
if (sd == null || !sd.hasDiscriminator()) {
throw new SpeedoException("Extension '"
+ INHERITANCE_KEY
+ "' specified without filter definition in the "
+ sc.getSourceDesc());
}
}
if (sd.expression == null) {
sc.inheritance.discriminatorValues.put(sd.elements.get(0), se.value);
} else {
sc.inheritance.discriminatorValues.put(sd.expression, se.value);
}
}
} else if (se.owner instanceof SpeedoField) {
SpeedoField sf = (SpeedoField) se.owner;
if (SQL_NAME.equals(se.key)) {
if (sf.getReferencedClass() == null) {
initColumnField(sf);
try {
sf.columns[0].name = se.value;
} catch (RuntimeException e) {
logger.log(BasicLevel.WARN, sf.getSourceDesc() + ", cols=" + sf.columns[0], e);
logger.log(BasicLevel.WARN, "se.value" + se.value);
throw e;
}
deprecate(SQL_NAME,"use the 'column' attribut of the tag 'field'.");
} else {
logger.log(BasicLevel.WARN,
"Extension 'sql-name' cannot be specified for a non primitive field: " + sf.getSourceDesc());
}
} else if (SQL_TYPE.equals(se.key)) {
if (sf.getReferencedClass() == null) {
initColumnField(sf);
sf.columns[0].sqlType = se.value;
deprecate(SQL_TYPE,"use the 'sql-type' attribut of the tag 'field'.");
} else {
logger.log(BasicLevel.WARN,
"Extension 'sql-type' cannot be specified for a non primitive field: " + sf.getSourceDesc());
}
} else if (SIZE.equals(se.key)) {
if (sf.getReferencedClass() == null) {
initColumnField(sf);
sf.columns[0].length = Integer.parseInt(se.value);
deprecate(SIZE,"use the 'size' attribut of the tag 'field'.");
} else {
logger.log(BasicLevel.WARN,
"Extension 'size' cannot be specified for a non primitive field: " + sf.getSourceDesc());
}
} else if (SCALE.equals(se.key)) {
if (sf.getReferencedClass() == null) {
initColumnField(sf);
sf.columns[0].scale = Integer.parseInt(se.value);
deprecate(SCALE,"use the 'scale' attribut of the tag 'field'.");
} else {
logger.log(BasicLevel.WARN,
"Extension 'scale' cannot be specified for a non primitive field: " + sf.getSourceDesc());
}
} else if (REVERSE_FIELD.equals(se.key)) {
//@see org.objectweb.speedo.generation.mivisitor.ReverseFieldAdder
} else if (ELEMENT.equals(se.key)) {
if (sf.jdoTuple != null && sf.getReferencedClass() == null) {
initColumnField(sf);
sf.columns[0].name = se.value;
deprecate(ELEMENT,"use the 'column' attribut of the tag 'field'.");
} else {
logger.log(BasicLevel.WARN,
"Extension 'element-sql-name' cannot be specified for a field which is not a collection of primitive element: " + sf.getSourceDesc());
}
} else if (ELEMENT_TYPE.equals(se.key)) {
if (sf.jdoTuple != null && sf.getReferencedClass() == null) {
initColumnField(sf);
sf.columns[0].sqlType = se.value;
deprecate(ELEMENT_TYPE,"use the 'column' attribut of the tag 'field'.");
} else {
logger.log(BasicLevel.WARN,
"Extension 'element-sql-type' cannot be specified for a field which is not a collection of primitive element: " + sf.getSourceDesc());
}
} else if (INDEX.equals(se.key)) {
if (sf.jdoTuple instanceof SpeedoCollection) {
initCollectionIndexColumn(
(SpeedoCollection) sf.jdoTuple).name = se.value;
} else if (sf.jdoTuple instanceof SpeedoMap) {
initMapKeyColumn((SpeedoMap) sf.jdoTuple).name = se.value;
} else {
logger.log(BasicLevel.WARN,
"Extension 'index-sql-name' cannot be specified for a field which is not a collection or a map: " + sf.getSourceDesc());
}
} else if (INDEX_TYPE.equals(se.key)) {
if (sf.jdoTuple instanceof SpeedoCollection) {
initCollectionIndexColumn(
(SpeedoCollection) sf.jdoTuple).sqlType = se.value;
} else if (sf.jdoTuple instanceof SpeedoMap) {
initMapKeyColumn((SpeedoMap) sf.jdoTuple).sqlType = se.value;
} else {
logger.log(BasicLevel.WARN,
"Extension 'index-sql-type' cannot be specified for a field which is not a collection or a map: " + sf.getSourceDesc());
}
}
}
super.visitExtension(se);
}
//public
/**
* If no column is specified for the field, a new one is created. By
* default a field is map over a single column.
*
* @param sf is the SpeedoField which the column must be initialized if not
* already done.
*/
private void initColumnField(SpeedoField sf) {
if (sf.columns == null || sf.columns.length == 0) {
//
sf.columns = new SpeedoColumn[]{ new SpeedoColumn()};
if (sf.moClass.mainTable != null) {
sf.columns[0].table = sf.moClass.mainTable;
}
}
}
private SpeedoColumn initCollectionIndexColumn(SpeedoCollection sc) {
if (sc.indexColumns == null) {
sc.indexColumns = new SpeedoColumn();
if (sc.moField.join != null && sc.moField.join.extTable != null) {
sc.indexColumns.table = sc.moField.join.extTable;
}
}
return sc.indexColumns;
}
private SpeedoColumn initMapKeyColumn(SpeedoMap sm) {
if (sm.keyColumns == null) {
sm.keyColumns = new SpeedoColumn();
if (sm.moField.join != null && sm.moField.join.extTable != null) {
sm.keyColumns.table = sm.moField.join.extTable;
}
}
return sm.keyColumns;
}
private SpeedoDiscriminator setDiscriminatorElement(SpeedoClass sc, String value) {
if (sc.inheritance == null) {
sc.inheritance = new SpeedoInheritance();
}
if (sc.inheritance.discriminator == null) {
sc.inheritance.discriminator = new SpeedoDiscriminator();
}
SpeedoDiscriminator sd = sc.inheritance.discriminator;
sd.strategy = SpeedoDiscriminator.STRATEGY_MAP_VALUE;
SpeedoField sf = sc.getField(value);
if (sf == null) {
sd.expression = value;
} else if (!sd.elements.contains(sf)) {
sd.elements.add(sf);
}
return sd;
}
}