/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
*
* Contact: speedo@objectweb.org
*
* Authors: S.Chassande-Barrioz.
*
*/
package org.objectweb.speedo.generation.parser.jdo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.generation.api.SpeedoXMLError;
import org.objectweb.speedo.generation.parser.AbstractParser;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoArray;
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.SpeedoElement;
import org.objectweb.speedo.metadata.SpeedoExtension;
import org.objectweb.speedo.metadata.SpeedoFetchGroup;
import org.objectweb.speedo.metadata.SpeedoField;
import org.objectweb.speedo.metadata.SpeedoIdentity;
import org.objectweb.speedo.metadata.SpeedoIndex;
import org.objectweb.speedo.metadata.SpeedoInheritance;
import org.objectweb.speedo.metadata.SpeedoJoin;
import org.objectweb.speedo.metadata.SpeedoJoinColumn;
import org.objectweb.speedo.metadata.SpeedoMap;
import org.objectweb.speedo.metadata.SpeedoNullValue;
import org.objectweb.speedo.metadata.SpeedoPackage;
import org.objectweb.speedo.metadata.SpeedoPredefinedQuery;
import org.objectweb.speedo.metadata.SpeedoTable;
import org.objectweb.speedo.metadata.SpeedoVersion;
import org.objectweb.speedo.metadata.SpeedoXMLDescriptor;
import org.objectweb.speedo.sequence.jdo.JDOSequence;
import org.objectweb.speedo.sequence.lib.SpeedoSequence;
import org.objectweb.util.monolog.api.BasicLevel;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* @author S.Chassande-Barrioz
*/
public class JDOParser
extends AbstractParser {
public JDOParser() {
super(Personality.JDO);
}
protected String getLoggerName() {
return "jdo";
}
protected Object treatDocument(Node node, Object mo) throws SpeedoException {
//o is the descriptor of the root node
mo = treatNode(node, mo);
//list of child node
List children = getChildren(node, mo);
for (int i = 0; i < children.size(); i++) {
//create a descriptor for the child
treatDocument((Node) children.get(i), mo);
}
return mo;
}
private List getChildren(Node node, Object mo) {
NodeList nl = node.getChildNodes();
int size = nl.getLength();
if (size == 0) {
return Collections.EMPTY_LIST;
}
ArrayList children = new ArrayList(size);
for (int i = 0; i < size; i++) {
children.add(nl.item(i));
}
sortChildren(children, mo);
return children;
}
private void sortChildren(List children, Object mo) {
if (mo instanceof SpeedoClass) {
//sort the children
}
}
// PRIVATE METHODS //
//-----------------//
/**
* This methods creates the object descriptor for describing a tag of the
* XML file.
* It returns the descriptor for the root tag.
* It throws an exception if an attribute is missing.
* @param node node which will be described.
* @param o default descriptor to return.
* @return node descriptor.
* @exception SpeedoException if a compulsory attribute is missing for
* the current tag.
*/
private Object treatNode(Node node, Object mo) throws SpeedoException {
if (node.getNodeType() != Node.ELEMENT_NODE) {
return mo;
}
String tag = node.getNodeName();
logger.log(BasicLevel.DEBUG, "Parse tag: " + tag);
if (tag.equals("jdo")) {//tag jdo
return mo;
} else if (tag.equals("package")) {
return treatPackage(node, mo);
} else if (tag.equals("class")) {
return treatClassNode(node, mo);
} else if (tag.equals("sequence")) {
return treatSequenceNode(node, mo);
} else if (tag.equals("inheritance")) {
return treatInheritance(node, mo);
} else if (tag.equals("field")) {
return treatFieldNode(node, mo);
} else if (tag.equals("datastore-identity")) {
return treatDataStoreId(node, mo);
} else if (tag.equals("collection")) { // field.collection
return treatCollection(node, mo);
} else if (tag.equals("element")) { // field.collection.element, field.array.element
return treatXXXElement(node, mo);
} else if (tag.equals("map")) { // field.map
return treatMap(node, mo);
} else if (tag.equals("key")) { //field.key
return treatMapKey(node, mo);
} else if (tag.equals("value")) { //field.value
return treatMapValue(node, mo);
} else if (tag.equals("array")) { //field.array
return treatArray(node, mo);
} else if (tag.equals("version")) { //class.version
return treatVersion(node, mo);
} else if (tag.equals("extension")) { //*.extension
return treatExtension(node, mo);
} else if (tag.equals("fetch-group")) { //field.fetch-group
return treatFetchGroup(node, mo);
} else if (tag.equals("query")) {
return treatQuery(node, mo);
} else if (tag.equals("declare")) { //query.declare
return treatQueryDeclare(node, mo);
} else if (tag.equals("result")) { //query.result
return treatQueryResult(node, mo);
} else if (tag.equals("join")) { //class.join | field.join | inheritance.join
return treatJoin(node, mo);
} else if (tag.equals("discriminator")) { //inheritance.discriminator
return treatDiscriminator(node, mo);
} else if (tag.equals("column")) { //field.discriminator
return treatColumn(node, mo);
} else
return mo;
}
private Object treatClassNode(Node node, Object mo) throws SpeedoException {
SpeedoClass c = new SpeedoClass();
Node n = null;
//attribute name (compulsory)
n = node.getAttributes().getNamedItem("name");
if (n == null)
throw new SpeedoXMLError("Attribute name for tag class requested.");
c.name = c.nameForQuery = n.getNodeValue();
//attribute identity-type
n = node.getAttributes().getNamedItem("identity-type");
if (n != null)
c.setIdentityType(SpeedoIdentity.getStrategy(n.getNodeValue()));
//attribute object-id
n = node.getAttributes().getNamedItem("objectid-class");
if (n != null) {
c.identity.objectidClass = n.getNodeValue();
c.setIdentityType(SpeedoIdentity.USER_ID);
}
//attribute requires-extent is not taking in account
//attribute detachable
n = node.getAttributes().getNamedItem("detachable");
if (n != null)
c.isDetachable = Boolean.valueOf(n.getNodeValue()).booleanValue();
//attribute persistence-capable-superclass
n = node.getAttributes().getNamedItem("persistence-capable-superclass");
if (n != null) {
if (c.inheritance == null) {
c.inheritance = new SpeedoInheritance();
}
c.inheritance.superClassName = n.getNodeValue();
}
//attribute table
n = node.getAttributes().getNamedItem("table");
if (n != null) {
c.mainTable = new SpeedoTable();
c.mainTable.name = n.getNodeValue();
}
logger.log(BasicLevel.DEBUG, "New class: "
+ "name=" + c.name
+ " / id = " + c.getIdentityType()
+ " / idClass = " + c.identity.objectidClass
+ " / detachable = " + c.isDetachable
);
((SpeedoPackage) mo).addClass(c, true, logger);
return c;
}
private Object treatDataStoreId(Node node, Object mo) throws SpeedoException {
SpeedoIdentity ident = new SpeedoIdentity(); //default strategy is native
//attribute strategy
Node n = node.getAttributes().getNamedItem("strategy");
if (n == null)
throw new SpeedoXMLError("Attribute strategy for tag datastore-identity requested.");
ident.strategy = SpeedoIdentity.getStrategy(n.getNodeValue());
//attribute sequence
n = node.getAttributes().getNamedItem("sequence");
if (n != null)
ident.sequenceName = n.getNodeValue();
if (debug) {
logger.log(BasicLevel.DEBUG, "New datastore-identity: "
+ "identity=" + ident);
}
((SpeedoClass) mo).identity = ident;
return ident;
}
private Object treatFieldNode(Node node, Object mo) throws SpeedoException {
SpeedoField f = new SpeedoField();
Node n = null;
//attribut name (compulsory)
n = node.getAttributes().getNamedItem("name");
if (n == null)
throw new SpeedoXMLError("Attribute name for tag field requested.");
String name = n.getNodeValue();
if(name.indexOf(".") != -1){
}
f.name = n.getNodeValue();
//attribute persistence-modifier
n = node.getAttributes().getNamedItem("persistence-modifier");
if (n != null)
f.persistenceStatus = SpeedoField.parsePersistenceStatus(n.getNodeValue());
//attribute primary-key
n = node.getAttributes().getNamedItem("primary-key");
if (n != null)
f.primaryKey = Boolean.valueOf(n.getNodeValue()).booleanValue();
//attribute null-value
n = node.getAttributes().getNamedItem("null-value");
if (n != null) {
f.nullValue = SpeedoNullValue.toByte(n.getNodeValue());
}
//attribute default-fetch-group
n = node.getAttributes().getNamedItem("default-fetch-group");
if (n != null)
f.defaultFetchGroup = Boolean.valueOf(n.getNodeValue()).booleanValue();
//attribute fetch-group
n = node.getAttributes().getNamedItem("fetch-group");
if (n != null)
f.fetchGroup = n.getNodeValue();
//attribute depth
n = node.getAttributes().getNamedItem("depth");
if (n != null)
f.depth = Integer.valueOf(n.getNodeValue()).intValue();
//attribute embbedded
n = node.getAttributes().getNamedItem("embedded");
if (n != null)
f.embedded = Boolean.valueOf(n.getNodeValue()).booleanValue();
//attribute value-strategy
n = node.getAttributes().getNamedItem("value-strategy");
if (n != null)
f.valueStrategy = n.getNodeValue();
//attribute sequence
n = node.getAttributes().getNamedItem("sequence");
if (n != null)
f.sequence = n.getNodeValue();
//attribute column
n = node.getAttributes().getNamedItem("table");
SpeedoTable st = null;
if (n != null) {
st = new SpeedoTable();
}
//attribute column
n = node.getAttributes().getNamedItem("column");
if (n != null) {
SpeedoColumn sc = new SpeedoColumn();
sc.name = n.getNodeValue();
if (st != null) {
sc.table = st;
}
f.addColumn(sc);
logger.log(BasicLevel.DEBUG, "specify column " + sc.name
+ " to the field " + f.name + ": " + f.columns);
}
if (debug) {
logger.log(BasicLevel.DEBUG, "New field: "
+ "name=" + f.name
+ " / persistenceModifier = " + f.persistenceStatus
+ " / primaryKey = " + f.primaryKey
+ " / nullValue = " + f.nullValue
+ " / defaultFetchGroup = " + f.defaultFetchGroup
+ " / embedded = " + f.embedded
+ " / depth = " + f.depth
+ " / valueStrategy = " + f.valueStrategy
+ " / sequence = " + f.sequence
);
}
if (mo instanceof SpeedoClass) {
((SpeedoClass) mo).add(f, true, logger);
} else if (mo instanceof SpeedoFetchGroup) {
SpeedoFetchGroup sfg = (SpeedoFetchGroup) mo;
if (logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "add field '" + f.name
+ "' into the fetchgroup '" + sfg.name +"'");
}
sfg.addField(f);
}
return f;
}
private Object treatMap(Node node, Object mo) throws SpeedoException {
SpeedoField f = (SpeedoField) mo;
SpeedoMap m = (SpeedoMap) f.jdoTuple;
if (m == null) {
m = new SpeedoMap();
}
f.jdoTuple = m;
m.moField = f;
//attribut key-type
Node n = node.getAttributes().getNamedItem("key-type");
if (n != null)
m.keyType = n.getNodeValue();
//attribut embedded-key
n = node.getAttributes().getNamedItem("embedded-key");
if (n != null)
m.embeddedKey = Boolean.valueOf(n.getNodeValue()).booleanValue();
//attribute value-type
n = node.getAttributes().getNamedItem("value-type");
if (n != null)
m.valueType = n.getNodeValue();
//attribute embedded-value
n = node.getAttributes().getNamedItem("embedded-value");
if (n != null)
m.embeddedValue = Boolean.valueOf(n.getNodeValue()).booleanValue();
logger.log(BasicLevel.DEBUG, "New map: "
+ "keyType=" + m.keyType
+ " / embeddedKey = " + m.embeddedKey
+ " / valueType = " + m.valueType
+ " / embeddedValue = " + m.embeddedValue
);
return m;
}
private Object treatMapKey(Node node, Object mo) throws SpeedoException {
SpeedoField f = (SpeedoField) mo;
SpeedoColumn col = null;
Node n = node.getAttributes().getNamedItem("column");
if (n != null) {
col = new SpeedoColumn();
col.name = n.getNodeValue();
//in the same table than map value
if (f.columns != null && f.columns.length > 0) {
col.table = f.columns[0].table;
}
}
if (!(f.jdoTuple instanceof SpeedoMap)) {
throw new SpeedoException(
"key element must be used for map field only: "
+ f.getSourceDesc());
}
SpeedoMap m = (SpeedoMap) f.jdoTuple;
if (col != null) {
m.keyColumns = col;
}
return m;
}
private Object treatMapValue(Node node, Object mo) throws SpeedoException {
SpeedoField f = (SpeedoField) mo;
if (!(f.jdoTuple instanceof SpeedoMap)) {
throw new SpeedoException(
"Value element must be used for map field only: "
+ f.getSourceDesc());
}
Node n = node.getAttributes().getNamedItem("column");
if (n != null) {
SpeedoColumn col = null;
if (f.columns == null || f.columns.length == 0) {
//create the new meta object for the column description
col = new SpeedoColumn();
// column definition of the value is the hold by SpeedoField meta
// object.
f.addColumn(col);
//Table will be defined later
} else {
col = f.columns[0];
}
col.name = n.getNodeValue();
}
return f.jdoTuple;
}
private Object treatCollection(Node node, Object mo) throws SpeedoException {
SpeedoField f = (SpeedoField) mo;
SpeedoCollection co = (SpeedoCollection) f.jdoTuple;
if (co == null) {
co = new SpeedoCollection();
}
f.jdoTuple = co;
co.moField = f;
//attribute element-type
Node n = node.getAttributes().getNamedItem("element-type");
if (n != null)
co.elementType = n.getNodeValue();
//attribute embedded-element
n = node.getAttributes().getNamedItem("embedded-element");
if (n != null)
co.embeddedElement = Boolean.valueOf(n.getNodeValue()).booleanValue();
if (debug) {
logger.log(BasicLevel.DEBUG, "New collection: "
+ "elementType=" + co.elementType
+ " / embeddedElement = " + co.embeddedElement
);
}
return co;
}
private Object treatXXXElement(Node node, Object mo) throws SpeedoException {
SpeedoField f = (SpeedoField) mo;
Node n = node.getAttributes().getNamedItem("column");
SpeedoColumn col = null;
if (n != null) {
col = new SpeedoColumn();
col.name = n.getNodeValue();
}
if (f.jdoTuple instanceof SpeedoCollection) {
if (col != null) {
((SpeedoCollection) f.jdoTuple).indexColumns = col;
}
} else if (f.jdoTuple instanceof SpeedoArray) {
//TODO: support array
}
return f.jdoTuple;
}
private Object treatArray(Node node, Object mo) throws SpeedoException {
SpeedoArray a = new SpeedoArray();
//attribute embedded-element
Node n = node.getAttributes().getNamedItem("embedded-element");
if (n != null)
a.embeddedElement = Boolean.valueOf(n.getNodeValue()).booleanValue();
logger.log(BasicLevel.DEBUG, "New array: "
+ "embeddedElement=" + a.embeddedElement
);
((SpeedoField) mo).jdoTuple = a;
a.moField = (SpeedoField) mo;
return a;
}
private Object treatVersion(Node node, Object mo) throws SpeedoException {
SpeedoVersion v = new SpeedoVersion();
//attribute embedded-element
Node n = node.getAttributes().getNamedItem("strategy");
v.strategy = SpeedoVersion.toByte(n.getNodeValue());
((SpeedoClass) mo).version = v;
logger.log(BasicLevel.DEBUG, "New version: "
+ "strategy=" + v.strategy);
return v;
}
private Object treatQuery(Node node, Object mo) throws SpeedoException {
SpeedoPredefinedQuery spq = new SpeedoPredefinedQuery();
spq.name = getStringAttributeValue(node, "name", null);
spq.language = getStringAttributeValue(node, "language", null);
spq.filter = getStringAttributeValue(node, "filter", null);
spq.ordering = getStringAttributeValue(node, "ordering", null);
spq.sql = getStringAttributeValue(node, "sql", null);
spq.ignoreCache = getBooleanAttributeValue(node, "ignore-cache", false);
spq.includeSubclasses = getBooleanAttributeValue(node, "include-subclasses", true);
String range = getStringAttributeValue(node, "range", null);
if (range != null) {
StringTokenizer st = new StringTokenizer(range, ",.;:/#", false);
if (st.hasMoreTokens()) {
spq.rangeFirst = Integer.valueOf(st.nextToken()).intValue();
if (st.hasMoreTokens()) {
spq.rangeLast = Integer.valueOf(st.nextToken()).intValue();
}
if (st.hasMoreTokens()) {
logger.log(BasicLevel.WARN,
"Query range contains too values, first="
+ spq.rangeFirst + ", last=" + spq.rangeLast
+ ", query=" + spq.name + ", range: " + range);
}
} else {
logger.log(BasicLevel.WARN,
"Query range value malformed (ignored), query:"
+ spq.name + ", range: " + range);
}
}
((SpeedoClass) mo).name2query.put(spq.name, spq);
return spq;
}
private Object treatQueryDeclare(Node node, Object mo) throws SpeedoException {
SpeedoPredefinedQuery spq = (SpeedoPredefinedQuery) mo;
spq.declareImports = getStringAttributeValue(node, "imports", null);
spq.declareParameters = getStringAttributeValue(node, "parameters", null);
spq.declareVariables = getStringAttributeValue(node, "variables", null);
return spq;
}
private Object treatQueryResult(Node node, Object mo) throws SpeedoException {
SpeedoPredefinedQuery spq = (SpeedoPredefinedQuery) mo;
spq.resultGrouping = getStringAttributeValue(node, "grouping", null);
spq.resultClass = getStringAttributeValue(node, "class", null);
spq.resultUnique = getBooleanAttributeValue(node, "unique", false);
return spq;
}
private Object treatFetchGroup(Node node, Object mo) throws SpeedoException {
SpeedoFetchGroup fg = new SpeedoFetchGroup();
//attribute name
Node n = node.getAttributes().getNamedItem("name");
fg.name = n.getNodeValue();
//attribute post-load
n = node.getAttributes().getNamedItem("post-load");
if (n != null){
fg.postLoad = Boolean.valueOf(n.getNodeValue()).booleanValue();
} else {
if (fg.name.equals("default")) {
fg.postLoad = true;
} else {
fg.postLoad = false;
}
}
if (mo instanceof SpeedoClass) {
SpeedoClass sc = (SpeedoClass) mo;
if (logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "add fetchgroup '" + fg.name +
"' into the class '" + sc.getFQName() +"'");
}
sc.addFetchGroup(fg);
} else if (mo instanceof SpeedoFetchGroup) {
SpeedoFetchGroup pfg = (SpeedoFetchGroup) mo;
if (logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "add fetchgroup '" + fg.name +
"' into the fetchgroup '" + pfg.name +"'");
}
pfg.addFetchGroup(fg);
}
return fg;
}
private Object treatExtension(Node node, Object mo) throws SpeedoException {
SpeedoExtension e = new SpeedoExtension();
//attribute vendor-name
Node n = node.getAttributes().getNamedItem("vendor-name");
e.vendorName = n.getNodeValue();
//attribute key
n = node.getAttributes().getNamedItem("key");
if (n != null) {
e.key = n.getNodeValue();
}
//attribute value
n = node.getAttributes().getNamedItem("value");
if (n != null) {
e.value = n.getNodeValue();
}
((SpeedoElement) mo).addExtension(e);
e.owner = (SpeedoElement) mo;
return e;
}
private Object treatPackage(Node node, Object mo) throws SpeedoException {
SpeedoPackage p = new SpeedoPackage();
//attribute name (compulsory)
Node n = node.getAttributes().getNamedItem("name");
if (n == null)
throw new SpeedoXMLError("Attribute name for tag package requested.");
p.name = n.getNodeValue();
((SpeedoXMLDescriptor) mo).add(p, true, logger);
logger.log(BasicLevel.DEBUG, "New package: name= " + p.name);
return p;
}
private Object treatInheritance(Node node, Object mo) throws SpeedoException {
SpeedoClass sc = (SpeedoClass) mo;
if (sc.inheritance == null) {
sc.inheritance = new SpeedoInheritance();
}
Node n = node.getAttributes().getNamedItem("strategy");
if (n == null) {
sc.inheritance.strategy =
SpeedoInheritance.parseStrategy(n.getNodeValue());
logger.log(BasicLevel.DEBUG, "defines the strategy '"
+ SpeedoInheritance.strategy2str(sc.inheritance.strategy));
}
return sc.inheritance;
}
private Object treatDiscriminator(Node node, Object mo) throws SpeedoException {
SpeedoInheritance si = (SpeedoInheritance) mo;
si.discriminator = new SpeedoDiscriminator();
Node n = node.getAttributes().getNamedItem("strategy");
if (n == null) {
si.discriminator.strategy =
SpeedoDiscriminator.parseStrategy(n.getNodeValue());
}
n = node.getAttributes().getNamedItem("value");
if (n == null) {
String val = n.getNodeValue();
n = node.getAttributes().getNamedItem("column");
if (n == null) {
logger.log(BasicLevel.ERROR,
"No column defined for the discriminator");
}
String col = n.getNodeValue();
si.discriminatorValues.put(col, val);
}
return si.discriminator;
/*
<!ATTLIST discriminator column CDATA #IMPLIED>
<!ATTLIST discriminator value CDATA #IMPLIED>
<!ATTLIST discriminator indexed (true|false|unique) #IMPLIED>
*/
}
private Object treatJoin(Node node, Object mo) throws SpeedoException {
SpeedoJoin j = new SpeedoJoin();
Node n = node.getAttributes().getNamedItem("delete-action");
if (n == null) {
String v = n.getNodeValue();
if ("restrict".equals(v)) {
j.deleteAction = SpeedoJoin.ACTION_RESTRICT;
} else if ("cascade".equals(v)) {
j.deleteAction = SpeedoJoin.ACTION_CASCADE;
} else if ("null".equals(v)) {
j.deleteAction = SpeedoJoin.ACTION_NULL;
} else if ("none".equals(v)) {
j.deleteAction = SpeedoJoin.ACTION_NONE;
} else if ("default".equals(v)) {
j.deleteAction = SpeedoJoin.ACTION_DEFAULT;
} else {
j.deleteAction = SpeedoJoin.ACTION_DEFAULT;
}
}
j.setUnique(getBooleanAttributeValue(node, "unique", j.getUnique()));
j.setIndexed(getBooleanAttributeValue(node, "indexed", j.getIndexed()));
j.setOuter(getBooleanAttributeValue(node, "indexed", j.getOuter()));
n = node.getAttributes().getNamedItem("column");
if (n == null) {
SpeedoColumn col = new SpeedoColumn();
col.name = n.getNodeValue();
SpeedoJoinColumn sjc = new SpeedoJoinColumn();
sjc.column = col;
j.columns.add(sjc);
}
n = node.getAttributes().getNamedItem("table");
String tableName = null;
if (n == null) {
tableName = n.getNodeValue();
}
if (mo instanceof SpeedoClass) {
addJoinToClass(j, tableName, (SpeedoClass) mo);
//define an external/secondary table
} else if (mo instanceof SpeedoInheritance) {
//define a join to the super class (vertical mapping)
((SpeedoInheritance) mo).join = j;
} else if (mo instanceof SpeedoField) {
//define an external/secondary table used by a particular field
((SpeedoField) mo).join = j;
addJoinToClass(j, tableName, ((SpeedoField) mo).moClass);
}
return j;
}
private Object treatSequenceNode(Node node, Object mo) throws SpeedoException {
SpeedoSequence s = new JDOSequence();
Node n = null;
//attribute name (compulsory)
n = node.getAttributes().getNamedItem("name");
if (n == null)
throw new SpeedoXMLError("Attribute name for tag sequence requested.");
s.name = n.getNodeValue();
//attribute datastore-sequence
n = node.getAttributes().getNamedItem("datastore-sequence");
if (n != null)
s.datastoreName = n.getNodeValue();
//attribute factory-class
n = node.getAttributes().getNamedItem("factory-class");
if (n != null) {
s.factoryClass = n.getNodeValue();
}
//attribute strategy (compulsory)
n = node.getAttributes().getNamedItem("strategy");
if (n == null) {
throw new SpeedoXMLError("Attribute strategy for tag sequence requested.");
}
s.strategy = SpeedoSequence.strategyToByte(n.getNodeValue());
((SpeedoPackage) mo).addSequence(s);
if (debug) {
logger.log(BasicLevel.DEBUG, "New sequence: "
+ "name=" + s.name
+ " / datastoreName = " + s.datastoreName
+ " / factoryClass = " + s.factoryClass
+ " / strategy = " + s.strategy
);
}
return s;
}
private void addJoinToClass(SpeedoJoin j, String joinTableName, SpeedoClass sc) {
sc.addJoin(j);
if (sc.mainTable != null) {
j.mainTable = sc.mainTable;
}
if (joinTableName != null) {
j.extTable = new SpeedoTable();
j.extTable.name = joinTableName;
j.extTable.join = j;
}
}
private Object treatColumn(Node node, Object mo) throws SpeedoException {
SpeedoColumn c = new SpeedoColumn();
Node n = node.getAttributes().getNamedItem("name");
if (n == null) {
c.name = n.getNodeValue();
}
n = node.getAttributes().getNamedItem("target");
if (n == null) {
c.targetColumn = n.getNodeValue();
}
n = node.getAttributes().getNamedItem("target-field");
if (n == null) {
c.targetField = n.getNodeValue();
}
n = node.getAttributes().getNamedItem("jdbc-type");
if (n == null) {
c.jdbcType = n.getNodeValue();
}
n = node.getAttributes().getNamedItem("sql-type");
if (n == null) {
c.sqlType = n.getNodeValue();
}
n = node.getAttributes().getNamedItem("length");
if (n == null) {
c.length = Integer.parseInt(n.getNodeValue());
}
n = node.getAttributes().getNamedItem("scale");
if (n == null) {
c.scale = Integer.parseInt(n.getNodeValue());
}
c.allowNull = getBooleanAttributeValue(node, "allows-null", c.allowNull);
n = node.getAttributes().getNamedItem("default-value");
if (n == null) {
c.defaultValue = n.getNodeValue();
}
if (mo instanceof SpeedoJoin) {
SpeedoJoin j = (SpeedoJoin) mo;
if (j.extTable != null) {
c.table = j.extTable;
}
SpeedoJoinColumn sjc = new SpeedoJoinColumn();
sjc.column = c;
j.columns.add(sjc);
logger.log(BasicLevel.DEBUG, "add column " + c.name + " to a join");
} else if (mo instanceof SpeedoField) { //class.field.column
SpeedoField f = (SpeedoField) mo;
f.addColumn(c);
logger.log(BasicLevel.DEBUG, "add column " + c.name + " to the field " + f.name);
} else if (mo instanceof SpeedoMap) {
SpeedoMap m = (SpeedoMap) mo;
String parentNodeName = node.getParentNode().getNodeName();
if ("key".equals(parentNodeName)) {
//class.field.key.column
m.keyColumns = c;
if (c.table == null
&& m.moField.columns != null
&& m.moField.columns.length > 0) {
//use the same table than the value of the map.
c.table = m.moField.columns[0].table;
}
logger.log(BasicLevel.DEBUG, "add column " + c.name
+ " to the key of map field " + m.moField.name);
} else if ("value".equals(parentNodeName)) {
if (m.moField.columns == null || m.moField.columns.length == 0) {
m.moField.addColumn(c);
} else if (m.moField.columns.length == 1) {
m.moField.columns[0].merge(c);
} else {
logger.log(BasicLevel.WARN, "Column '" + c.name
+ "' definition ignored (several column already defined for the field "
+ m.moField.getSourceDesc());
}
logger.log(BasicLevel.DEBUG, "add column " + c.name
+ " to the value of map field " + m.moField.name);
}
} else if (mo instanceof SpeedoCollection) {
((SpeedoCollection) mo).moField.addColumn(c);
logger.log(BasicLevel.DEBUG, "add column " + c.name
+ " to the collection field "
+ ((SpeedoCollection) mo).moField.name);
} else if (mo instanceof SpeedoArray) {
((SpeedoArray) mo).moField.addColumn(c);
logger.log(BasicLevel.DEBUG, "add column " + c.name
+ " to the array field "
+ ((SpeedoArray) mo).moField.name);
} else if (mo instanceof SpeedoDiscriminator) {
((SpeedoDiscriminator) mo).elements.add(c);
} else if (mo instanceof SpeedoIndex) {
SpeedoIndex si = (SpeedoIndex) mo;
si.columnNames.add(c.name);
if (si.table == null && c.table != null) {
si.table = c.table.name;
}
logger.log(BasicLevel.DEBUG, "add column " + c.name + " to an index");
} else if (mo instanceof SpeedoVersion) {
//TODO: non visible column is not suported
} else if (mo instanceof SpeedoIdentity) {
//TODO: non visible column is not suported
}
//TODO: foreign-key.column
//TODO: order.column
//TODO: unique.column
return c;
}
private static String getStringAttributeValue(Node node, String attribName, String defaultValue) {
Node n = node.getAttributes().getNamedItem(attribName);
if (n != null) {
return n.getNodeValue();
} else {
return defaultValue;
}
}
private static boolean getBooleanAttributeValue(Node node, String attribName, boolean defaultValue) {
Node n = node.getAttributes().getNamedItem(attribName);
if (n != null) {
return Boolean.valueOf(n.getNodeValue()).booleanValue();
} else {
return defaultValue;
}
}
}