001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: *
021: *
022: * Contact: speedo@objectweb.org
023: *
024: * Authors: S.Chassande-Barrioz.
025: *
026: */package org.objectweb.speedo.generation.parser.jdo;
027:
028: import java.util.ArrayList;
029: import java.util.Collections;
030: import java.util.List;
031: import java.util.StringTokenizer;
032:
033: import org.objectweb.speedo.api.SpeedoException;
034: import org.objectweb.speedo.generation.api.SpeedoXMLError;
035: import org.objectweb.speedo.generation.parser.AbstractParser;
036: import org.objectweb.speedo.lib.Personality;
037: import org.objectweb.speedo.metadata.SpeedoArray;
038: import org.objectweb.speedo.metadata.SpeedoClass;
039: import org.objectweb.speedo.metadata.SpeedoCollection;
040: import org.objectweb.speedo.metadata.SpeedoColumn;
041: import org.objectweb.speedo.metadata.SpeedoDiscriminator;
042: import org.objectweb.speedo.metadata.SpeedoElement;
043: import org.objectweb.speedo.metadata.SpeedoExtension;
044: import org.objectweb.speedo.metadata.SpeedoFetchGroup;
045: import org.objectweb.speedo.metadata.SpeedoField;
046: import org.objectweb.speedo.metadata.SpeedoIdentity;
047: import org.objectweb.speedo.metadata.SpeedoIndex;
048: import org.objectweb.speedo.metadata.SpeedoInheritance;
049: import org.objectweb.speedo.metadata.SpeedoJoin;
050: import org.objectweb.speedo.metadata.SpeedoJoinColumn;
051: import org.objectweb.speedo.metadata.SpeedoMap;
052: import org.objectweb.speedo.metadata.SpeedoNullValue;
053: import org.objectweb.speedo.metadata.SpeedoPackage;
054: import org.objectweb.speedo.metadata.SpeedoPredefinedQuery;
055: import org.objectweb.speedo.metadata.SpeedoTable;
056: import org.objectweb.speedo.metadata.SpeedoVersion;
057: import org.objectweb.speedo.metadata.SpeedoXMLDescriptor;
058: import org.objectweb.speedo.sequence.jdo.JDOSequence;
059: import org.objectweb.speedo.sequence.lib.SpeedoSequence;
060: import org.objectweb.util.monolog.api.BasicLevel;
061: import org.w3c.dom.Node;
062: import org.w3c.dom.NodeList;
063:
064: /**
065: * @author S.Chassande-Barrioz
066: */
067: public class JDOParser extends AbstractParser {
068:
069: public JDOParser() {
070: super (Personality.JDO);
071: }
072:
073: protected String getLoggerName() {
074: return "jdo";
075: }
076:
077: protected Object treatDocument(Node node, Object mo)
078: throws SpeedoException {
079: //o is the descriptor of the root node
080: mo = treatNode(node, mo);
081: //list of child node
082: List children = getChildren(node, mo);
083: for (int i = 0; i < children.size(); i++) {
084: //create a descriptor for the child
085: treatDocument((Node) children.get(i), mo);
086: }
087: return mo;
088: }
089:
090: private List getChildren(Node node, Object mo) {
091: NodeList nl = node.getChildNodes();
092: int size = nl.getLength();
093: if (size == 0) {
094: return Collections.EMPTY_LIST;
095: }
096: ArrayList children = new ArrayList(size);
097: for (int i = 0; i < size; i++) {
098: children.add(nl.item(i));
099: }
100: sortChildren(children, mo);
101: return children;
102: }
103:
104: private void sortChildren(List children, Object mo) {
105: if (mo instanceof SpeedoClass) {
106: //sort the children
107: }
108: }
109:
110: // PRIVATE METHODS //
111: //-----------------//
112:
113: /**
114: * This methods creates the object descriptor for describing a tag of the
115: * XML file.
116: * It returns the descriptor for the root tag.
117: * It throws an exception if an attribute is missing.
118: * @param node node which will be described.
119: * @param o default descriptor to return.
120: * @return node descriptor.
121: * @exception SpeedoException if a compulsory attribute is missing for
122: * the current tag.
123: */
124: private Object treatNode(Node node, Object mo)
125: throws SpeedoException {
126: if (node.getNodeType() != Node.ELEMENT_NODE) {
127: return mo;
128: }
129: String tag = node.getNodeName();
130: logger.log(BasicLevel.DEBUG, "Parse tag: " + tag);
131: if (tag.equals("jdo")) {//tag jdo
132: return mo;
133: } else if (tag.equals("package")) {
134: return treatPackage(node, mo);
135: } else if (tag.equals("class")) {
136: return treatClassNode(node, mo);
137: } else if (tag.equals("sequence")) {
138: return treatSequenceNode(node, mo);
139: } else if (tag.equals("inheritance")) {
140: return treatInheritance(node, mo);
141: } else if (tag.equals("field")) {
142: return treatFieldNode(node, mo);
143: } else if (tag.equals("datastore-identity")) {
144: return treatDataStoreId(node, mo);
145: } else if (tag.equals("collection")) { // field.collection
146: return treatCollection(node, mo);
147: } else if (tag.equals("element")) { // field.collection.element, field.array.element
148: return treatXXXElement(node, mo);
149: } else if (tag.equals("map")) { // field.map
150: return treatMap(node, mo);
151: } else if (tag.equals("key")) { //field.key
152: return treatMapKey(node, mo);
153: } else if (tag.equals("value")) { //field.value
154: return treatMapValue(node, mo);
155: } else if (tag.equals("array")) { //field.array
156: return treatArray(node, mo);
157: } else if (tag.equals("version")) { //class.version
158: return treatVersion(node, mo);
159: } else if (tag.equals("extension")) { //*.extension
160: return treatExtension(node, mo);
161: } else if (tag.equals("fetch-group")) { //field.fetch-group
162: return treatFetchGroup(node, mo);
163: } else if (tag.equals("query")) {
164: return treatQuery(node, mo);
165: } else if (tag.equals("declare")) { //query.declare
166: return treatQueryDeclare(node, mo);
167: } else if (tag.equals("result")) { //query.result
168: return treatQueryResult(node, mo);
169: } else if (tag.equals("join")) { //class.join | field.join | inheritance.join
170: return treatJoin(node, mo);
171: } else if (tag.equals("discriminator")) { //inheritance.discriminator
172: return treatDiscriminator(node, mo);
173: } else if (tag.equals("column")) { //field.discriminator
174: return treatColumn(node, mo);
175: } else
176: return mo;
177: }
178:
179: private Object treatClassNode(Node node, Object mo)
180: throws SpeedoException {
181: SpeedoClass c = new SpeedoClass();
182: Node n = null;
183: //attribute name (compulsory)
184: n = node.getAttributes().getNamedItem("name");
185: if (n == null)
186: throw new SpeedoXMLError(
187: "Attribute name for tag class requested.");
188: c.name = c.nameForQuery = n.getNodeValue();
189:
190: //attribute identity-type
191: n = node.getAttributes().getNamedItem("identity-type");
192: if (n != null)
193: c.setIdentityType(SpeedoIdentity.getStrategy(n
194: .getNodeValue()));
195:
196: //attribute object-id
197: n = node.getAttributes().getNamedItem("objectid-class");
198: if (n != null) {
199: c.identity.objectidClass = n.getNodeValue();
200: c.setIdentityType(SpeedoIdentity.USER_ID);
201: }
202:
203: //attribute requires-extent is not taking in account
204:
205: //attribute detachable
206: n = node.getAttributes().getNamedItem("detachable");
207: if (n != null)
208: c.isDetachable = Boolean.valueOf(n.getNodeValue())
209: .booleanValue();
210:
211: //attribute persistence-capable-superclass
212: n = node.getAttributes().getNamedItem(
213: "persistence-capable-superclass");
214: if (n != null) {
215: if (c.inheritance == null) {
216: c.inheritance = new SpeedoInheritance();
217: }
218: c.inheritance.super ClassName = n.getNodeValue();
219: }
220: //attribute table
221: n = node.getAttributes().getNamedItem("table");
222: if (n != null) {
223: c.mainTable = new SpeedoTable();
224: c.mainTable.name = n.getNodeValue();
225: }
226:
227: logger.log(BasicLevel.DEBUG, "New class: " + "name=" + c.name
228: + " / id = " + c.getIdentityType() + " / idClass = "
229: + c.identity.objectidClass + " / detachable = "
230: + c.isDetachable);
231: ((SpeedoPackage) mo).addClass(c, true, logger);
232: return c;
233: }
234:
235: private Object treatDataStoreId(Node node, Object mo)
236: throws SpeedoException {
237: SpeedoIdentity ident = new SpeedoIdentity(); //default strategy is native
238: //attribute strategy
239: Node n = node.getAttributes().getNamedItem("strategy");
240: if (n == null)
241: throw new SpeedoXMLError(
242: "Attribute strategy for tag datastore-identity requested.");
243: ident.strategy = SpeedoIdentity.getStrategy(n.getNodeValue());
244:
245: //attribute sequence
246: n = node.getAttributes().getNamedItem("sequence");
247: if (n != null)
248: ident.sequenceName = n.getNodeValue();
249:
250: if (debug) {
251: logger.log(BasicLevel.DEBUG, "New datastore-identity: "
252: + "identity=" + ident);
253: }
254: ((SpeedoClass) mo).identity = ident;
255: return ident;
256: }
257:
258: private Object treatFieldNode(Node node, Object mo)
259: throws SpeedoException {
260: SpeedoField f = new SpeedoField();
261: Node n = null;
262:
263: //attribut name (compulsory)
264: n = node.getAttributes().getNamedItem("name");
265: if (n == null)
266: throw new SpeedoXMLError(
267: "Attribute name for tag field requested.");
268: String name = n.getNodeValue();
269: if (name.indexOf(".") != -1) {
270:
271: }
272: f.name = n.getNodeValue();
273:
274: //attribute persistence-modifier
275: n = node.getAttributes().getNamedItem("persistence-modifier");
276: if (n != null)
277: f.persistenceStatus = SpeedoField.parsePersistenceStatus(n
278: .getNodeValue());
279:
280: //attribute primary-key
281: n = node.getAttributes().getNamedItem("primary-key");
282: if (n != null)
283: f.primaryKey = Boolean.valueOf(n.getNodeValue())
284: .booleanValue();
285:
286: //attribute null-value
287: n = node.getAttributes().getNamedItem("null-value");
288: if (n != null) {
289: f.nullValue = SpeedoNullValue.toByte(n.getNodeValue());
290: }
291:
292: //attribute default-fetch-group
293: n = node.getAttributes().getNamedItem("default-fetch-group");
294: if (n != null)
295: f.defaultFetchGroup = Boolean.valueOf(n.getNodeValue())
296: .booleanValue();
297:
298: //attribute fetch-group
299: n = node.getAttributes().getNamedItem("fetch-group");
300: if (n != null)
301: f.fetchGroup = n.getNodeValue();
302:
303: //attribute depth
304: n = node.getAttributes().getNamedItem("depth");
305: if (n != null)
306: f.depth = Integer.valueOf(n.getNodeValue()).intValue();
307:
308: //attribute embbedded
309: n = node.getAttributes().getNamedItem("embedded");
310: if (n != null)
311: f.embedded = Boolean.valueOf(n.getNodeValue())
312: .booleanValue();
313:
314: //attribute value-strategy
315: n = node.getAttributes().getNamedItem("value-strategy");
316: if (n != null)
317: f.valueStrategy = n.getNodeValue();
318:
319: //attribute sequence
320: n = node.getAttributes().getNamedItem("sequence");
321: if (n != null)
322: f.sequence = n.getNodeValue();
323:
324: //attribute column
325: n = node.getAttributes().getNamedItem("table");
326: SpeedoTable st = null;
327: if (n != null) {
328: st = new SpeedoTable();
329: }
330: //attribute column
331: n = node.getAttributes().getNamedItem("column");
332: if (n != null) {
333: SpeedoColumn sc = new SpeedoColumn();
334: sc.name = n.getNodeValue();
335: if (st != null) {
336: sc.table = st;
337: }
338: f.addColumn(sc);
339: logger.log(BasicLevel.DEBUG, "specify column " + sc.name
340: + " to the field " + f.name + ": " + f.columns);
341: }
342: if (debug) {
343: logger.log(BasicLevel.DEBUG, "New field: " + "name="
344: + f.name + " / persistenceModifier = "
345: + f.persistenceStatus + " / primaryKey = "
346: + f.primaryKey + " / nullValue = " + f.nullValue
347: + " / defaultFetchGroup = " + f.defaultFetchGroup
348: + " / embedded = " + f.embedded + " / depth = "
349: + f.depth + " / valueStrategy = "
350: + f.valueStrategy + " / sequence = " + f.sequence);
351: }
352: if (mo instanceof SpeedoClass) {
353: ((SpeedoClass) mo).add(f, true, logger);
354: } else if (mo instanceof SpeedoFetchGroup) {
355: SpeedoFetchGroup sfg = (SpeedoFetchGroup) mo;
356: if (logger.isLoggable(BasicLevel.DEBUG)) {
357: logger.log(BasicLevel.DEBUG, "add field '" + f.name
358: + "' into the fetchgroup '" + sfg.name + "'");
359: }
360: sfg.addField(f);
361: }
362: return f;
363: }
364:
365: private Object treatMap(Node node, Object mo)
366: throws SpeedoException {
367: SpeedoField f = (SpeedoField) mo;
368: SpeedoMap m = (SpeedoMap) f.jdoTuple;
369: if (m == null) {
370: m = new SpeedoMap();
371: }
372: f.jdoTuple = m;
373: m.moField = f;
374:
375: //attribut key-type
376: Node n = node.getAttributes().getNamedItem("key-type");
377: if (n != null)
378: m.keyType = n.getNodeValue();
379:
380: //attribut embedded-key
381: n = node.getAttributes().getNamedItem("embedded-key");
382: if (n != null)
383: m.embeddedKey = Boolean.valueOf(n.getNodeValue())
384: .booleanValue();
385:
386: //attribute value-type
387: n = node.getAttributes().getNamedItem("value-type");
388: if (n != null)
389: m.valueType = n.getNodeValue();
390:
391: //attribute embedded-value
392: n = node.getAttributes().getNamedItem("embedded-value");
393: if (n != null)
394: m.embeddedValue = Boolean.valueOf(n.getNodeValue())
395: .booleanValue();
396:
397: logger.log(BasicLevel.DEBUG, "New map: " + "keyType="
398: + m.keyType + " / embeddedKey = " + m.embeddedKey
399: + " / valueType = " + m.valueType
400: + " / embeddedValue = " + m.embeddedValue);
401: return m;
402: }
403:
404: private Object treatMapKey(Node node, Object mo)
405: throws SpeedoException {
406: SpeedoField f = (SpeedoField) mo;
407: SpeedoColumn col = null;
408: Node n = node.getAttributes().getNamedItem("column");
409: if (n != null) {
410: col = new SpeedoColumn();
411: col.name = n.getNodeValue();
412: //in the same table than map value
413: if (f.columns != null && f.columns.length > 0) {
414: col.table = f.columns[0].table;
415: }
416: }
417: if (!(f.jdoTuple instanceof SpeedoMap)) {
418: throw new SpeedoException(
419: "key element must be used for map field only: "
420: + f.getSourceDesc());
421: }
422: SpeedoMap m = (SpeedoMap) f.jdoTuple;
423: if (col != null) {
424: m.keyColumns = col;
425: }
426: return m;
427: }
428:
429: private Object treatMapValue(Node node, Object mo)
430: throws SpeedoException {
431: SpeedoField f = (SpeedoField) mo;
432: if (!(f.jdoTuple instanceof SpeedoMap)) {
433: throw new SpeedoException(
434: "Value element must be used for map field only: "
435: + f.getSourceDesc());
436: }
437: Node n = node.getAttributes().getNamedItem("column");
438: if (n != null) {
439: SpeedoColumn col = null;
440: if (f.columns == null || f.columns.length == 0) {
441: //create the new meta object for the column description
442: col = new SpeedoColumn();
443: // column definition of the value is the hold by SpeedoField meta
444: // object.
445: f.addColumn(col);
446: //Table will be defined later
447: } else {
448: col = f.columns[0];
449: }
450: col.name = n.getNodeValue();
451: }
452: return f.jdoTuple;
453: }
454:
455: private Object treatCollection(Node node, Object mo)
456: throws SpeedoException {
457: SpeedoField f = (SpeedoField) mo;
458: SpeedoCollection co = (SpeedoCollection) f.jdoTuple;
459: if (co == null) {
460: co = new SpeedoCollection();
461: }
462: f.jdoTuple = co;
463: co.moField = f;
464: //attribute element-type
465: Node n = node.getAttributes().getNamedItem("element-type");
466: if (n != null)
467: co.elementType = n.getNodeValue();
468:
469: //attribute embedded-element
470: n = node.getAttributes().getNamedItem("embedded-element");
471: if (n != null)
472: co.embeddedElement = Boolean.valueOf(n.getNodeValue())
473: .booleanValue();
474:
475: if (debug) {
476: logger.log(BasicLevel.DEBUG, "New collection: "
477: + "elementType=" + co.elementType
478: + " / embeddedElement = " + co.embeddedElement);
479: }
480: return co;
481: }
482:
483: private Object treatXXXElement(Node node, Object mo)
484: throws SpeedoException {
485: SpeedoField f = (SpeedoField) mo;
486: Node n = node.getAttributes().getNamedItem("column");
487: SpeedoColumn col = null;
488: if (n != null) {
489: col = new SpeedoColumn();
490: col.name = n.getNodeValue();
491: }
492: if (f.jdoTuple instanceof SpeedoCollection) {
493: if (col != null) {
494: ((SpeedoCollection) f.jdoTuple).indexColumns = col;
495: }
496: } else if (f.jdoTuple instanceof SpeedoArray) {
497: //TODO: support array
498: }
499: return f.jdoTuple;
500: }
501:
502: private Object treatArray(Node node, Object mo)
503: throws SpeedoException {
504: SpeedoArray a = new SpeedoArray();
505: //attribute embedded-element
506: Node n = node.getAttributes().getNamedItem("embedded-element");
507: if (n != null)
508: a.embeddedElement = Boolean.valueOf(n.getNodeValue())
509: .booleanValue();
510:
511: logger.log(BasicLevel.DEBUG, "New array: " + "embeddedElement="
512: + a.embeddedElement);
513: ((SpeedoField) mo).jdoTuple = a;
514: a.moField = (SpeedoField) mo;
515: return a;
516: }
517:
518: private Object treatVersion(Node node, Object mo)
519: throws SpeedoException {
520: SpeedoVersion v = new SpeedoVersion();
521: //attribute embedded-element
522: Node n = node.getAttributes().getNamedItem("strategy");
523: v.strategy = SpeedoVersion.toByte(n.getNodeValue());
524: ((SpeedoClass) mo).version = v;
525: logger.log(BasicLevel.DEBUG, "New version: " + "strategy="
526: + v.strategy);
527: return v;
528: }
529:
530: private Object treatQuery(Node node, Object mo)
531: throws SpeedoException {
532: SpeedoPredefinedQuery spq = new SpeedoPredefinedQuery();
533: spq.name = getStringAttributeValue(node, "name", null);
534: spq.language = getStringAttributeValue(node, "language", null);
535: spq.filter = getStringAttributeValue(node, "filter", null);
536: spq.ordering = getStringAttributeValue(node, "ordering", null);
537: spq.sql = getStringAttributeValue(node, "sql", null);
538: spq.ignoreCache = getBooleanAttributeValue(node,
539: "ignore-cache", false);
540: spq.includeSubclasses = getBooleanAttributeValue(node,
541: "include-subclasses", true);
542: String range = getStringAttributeValue(node, "range", null);
543: if (range != null) {
544: StringTokenizer st = new StringTokenizer(range, ",.;:/#",
545: false);
546: if (st.hasMoreTokens()) {
547: spq.rangeFirst = Integer.valueOf(st.nextToken())
548: .intValue();
549: if (st.hasMoreTokens()) {
550: spq.rangeLast = Integer.valueOf(st.nextToken())
551: .intValue();
552: }
553: if (st.hasMoreTokens()) {
554: logger.log(BasicLevel.WARN,
555: "Query range contains too values, first="
556: + spq.rangeFirst + ", last="
557: + spq.rangeLast + ", query="
558: + spq.name + ", range: " + range);
559: }
560: } else {
561: logger.log(BasicLevel.WARN,
562: "Query range value malformed (ignored), query:"
563: + spq.name + ", range: " + range);
564: }
565: }
566: ((SpeedoClass) mo).name2query.put(spq.name, spq);
567: return spq;
568: }
569:
570: private Object treatQueryDeclare(Node node, Object mo)
571: throws SpeedoException {
572: SpeedoPredefinedQuery spq = (SpeedoPredefinedQuery) mo;
573: spq.declareImports = getStringAttributeValue(node, "imports",
574: null);
575: spq.declareParameters = getStringAttributeValue(node,
576: "parameters", null);
577: spq.declareVariables = getStringAttributeValue(node,
578: "variables", null);
579: return spq;
580: }
581:
582: private Object treatQueryResult(Node node, Object mo)
583: throws SpeedoException {
584: SpeedoPredefinedQuery spq = (SpeedoPredefinedQuery) mo;
585: spq.resultGrouping = getStringAttributeValue(node, "grouping",
586: null);
587: spq.resultClass = getStringAttributeValue(node, "class", null);
588: spq.resultUnique = getBooleanAttributeValue(node, "unique",
589: false);
590: return spq;
591: }
592:
593: private Object treatFetchGroup(Node node, Object mo)
594: throws SpeedoException {
595: SpeedoFetchGroup fg = new SpeedoFetchGroup();
596: //attribute name
597: Node n = node.getAttributes().getNamedItem("name");
598: fg.name = n.getNodeValue();
599:
600: //attribute post-load
601: n = node.getAttributes().getNamedItem("post-load");
602: if (n != null) {
603: fg.postLoad = Boolean.valueOf(n.getNodeValue())
604: .booleanValue();
605: } else {
606: if (fg.name.equals("default")) {
607: fg.postLoad = true;
608: } else {
609: fg.postLoad = false;
610: }
611: }
612: if (mo instanceof SpeedoClass) {
613: SpeedoClass sc = (SpeedoClass) mo;
614: if (logger.isLoggable(BasicLevel.DEBUG)) {
615: logger.log(BasicLevel.DEBUG, "add fetchgroup '"
616: + fg.name + "' into the class '"
617: + sc.getFQName() + "'");
618: }
619: sc.addFetchGroup(fg);
620: } else if (mo instanceof SpeedoFetchGroup) {
621: SpeedoFetchGroup pfg = (SpeedoFetchGroup) mo;
622: if (logger.isLoggable(BasicLevel.DEBUG)) {
623: logger.log(BasicLevel.DEBUG, "add fetchgroup '"
624: + fg.name + "' into the fetchgroup '"
625: + pfg.name + "'");
626: }
627: pfg.addFetchGroup(fg);
628: }
629: return fg;
630: }
631:
632: private Object treatExtension(Node node, Object mo)
633: throws SpeedoException {
634: SpeedoExtension e = new SpeedoExtension();
635: //attribute vendor-name
636: Node n = node.getAttributes().getNamedItem("vendor-name");
637: e.vendorName = n.getNodeValue();
638: //attribute key
639: n = node.getAttributes().getNamedItem("key");
640: if (n != null) {
641: e.key = n.getNodeValue();
642: }
643: //attribute value
644: n = node.getAttributes().getNamedItem("value");
645: if (n != null) {
646: e.value = n.getNodeValue();
647: }
648: ((SpeedoElement) mo).addExtension(e);
649: e.owner = (SpeedoElement) mo;
650: return e;
651: }
652:
653: private Object treatPackage(Node node, Object mo)
654: throws SpeedoException {
655: SpeedoPackage p = new SpeedoPackage();
656: //attribute name (compulsory)
657: Node n = node.getAttributes().getNamedItem("name");
658: if (n == null)
659: throw new SpeedoXMLError(
660: "Attribute name for tag package requested.");
661: p.name = n.getNodeValue();
662: ((SpeedoXMLDescriptor) mo).add(p, true, logger);
663: logger.log(BasicLevel.DEBUG, "New package: name= " + p.name);
664: return p;
665: }
666:
667: private Object treatInheritance(Node node, Object mo)
668: throws SpeedoException {
669: SpeedoClass sc = (SpeedoClass) mo;
670: if (sc.inheritance == null) {
671: sc.inheritance = new SpeedoInheritance();
672: }
673: Node n = node.getAttributes().getNamedItem("strategy");
674: if (n == null) {
675: sc.inheritance.strategy = SpeedoInheritance.parseStrategy(n
676: .getNodeValue());
677: logger.log(BasicLevel.DEBUG, "defines the strategy '"
678: + SpeedoInheritance
679: .strategy2str(sc.inheritance.strategy));
680: }
681: return sc.inheritance;
682: }
683:
684: private Object treatDiscriminator(Node node, Object mo)
685: throws SpeedoException {
686: SpeedoInheritance si = (SpeedoInheritance) mo;
687: si.discriminator = new SpeedoDiscriminator();
688: Node n = node.getAttributes().getNamedItem("strategy");
689: if (n == null) {
690: si.discriminator.strategy = SpeedoDiscriminator
691: .parseStrategy(n.getNodeValue());
692: }
693: n = node.getAttributes().getNamedItem("value");
694: if (n == null) {
695: String val = n.getNodeValue();
696: n = node.getAttributes().getNamedItem("column");
697: if (n == null) {
698: logger.log(BasicLevel.ERROR,
699: "No column defined for the discriminator");
700: }
701: String col = n.getNodeValue();
702: si.discriminatorValues.put(col, val);
703: }
704: return si.discriminator;
705:
706: /*
707: <!ATTLIST discriminator column CDATA #IMPLIED>
708: <!ATTLIST discriminator value CDATA #IMPLIED>
709: <!ATTLIST discriminator indexed (true|false|unique) #IMPLIED>
710:
711: */
712: }
713:
714: private Object treatJoin(Node node, Object mo)
715: throws SpeedoException {
716: SpeedoJoin j = new SpeedoJoin();
717: Node n = node.getAttributes().getNamedItem("delete-action");
718: if (n == null) {
719: String v = n.getNodeValue();
720: if ("restrict".equals(v)) {
721: j.deleteAction = SpeedoJoin.ACTION_RESTRICT;
722: } else if ("cascade".equals(v)) {
723: j.deleteAction = SpeedoJoin.ACTION_CASCADE;
724: } else if ("null".equals(v)) {
725: j.deleteAction = SpeedoJoin.ACTION_NULL;
726: } else if ("none".equals(v)) {
727: j.deleteAction = SpeedoJoin.ACTION_NONE;
728: } else if ("default".equals(v)) {
729: j.deleteAction = SpeedoJoin.ACTION_DEFAULT;
730: } else {
731: j.deleteAction = SpeedoJoin.ACTION_DEFAULT;
732: }
733: }
734: j.setUnique(getBooleanAttributeValue(node, "unique", j
735: .getUnique()));
736: j.setIndexed(getBooleanAttributeValue(node, "indexed", j
737: .getIndexed()));
738: j.setOuter(getBooleanAttributeValue(node, "indexed", j
739: .getOuter()));
740: n = node.getAttributes().getNamedItem("column");
741: if (n == null) {
742: SpeedoColumn col = new SpeedoColumn();
743: col.name = n.getNodeValue();
744: SpeedoJoinColumn sjc = new SpeedoJoinColumn();
745: sjc.column = col;
746: j.columns.add(sjc);
747: }
748: n = node.getAttributes().getNamedItem("table");
749: String tableName = null;
750: if (n == null) {
751: tableName = n.getNodeValue();
752: }
753: if (mo instanceof SpeedoClass) {
754: addJoinToClass(j, tableName, (SpeedoClass) mo);
755: //define an external/secondary table
756: } else if (mo instanceof SpeedoInheritance) {
757: //define a join to the super class (vertical mapping)
758: ((SpeedoInheritance) mo).join = j;
759:
760: } else if (mo instanceof SpeedoField) {
761: //define an external/secondary table used by a particular field
762: ((SpeedoField) mo).join = j;
763: addJoinToClass(j, tableName, ((SpeedoField) mo).moClass);
764: }
765: return j;
766: }
767:
768: private Object treatSequenceNode(Node node, Object mo)
769: throws SpeedoException {
770: SpeedoSequence s = new JDOSequence();
771: Node n = null;
772:
773: //attribute name (compulsory)
774: n = node.getAttributes().getNamedItem("name");
775: if (n == null)
776: throw new SpeedoXMLError(
777: "Attribute name for tag sequence requested.");
778: s.name = n.getNodeValue();
779:
780: //attribute datastore-sequence
781: n = node.getAttributes().getNamedItem("datastore-sequence");
782: if (n != null)
783: s.datastoreName = n.getNodeValue();
784:
785: //attribute factory-class
786: n = node.getAttributes().getNamedItem("factory-class");
787: if (n != null) {
788: s.factoryClass = n.getNodeValue();
789: }
790:
791: //attribute strategy (compulsory)
792: n = node.getAttributes().getNamedItem("strategy");
793: if (n == null) {
794: throw new SpeedoXMLError(
795: "Attribute strategy for tag sequence requested.");
796: }
797: s.strategy = SpeedoSequence.strategyToByte(n.getNodeValue());
798:
799: ((SpeedoPackage) mo).addSequence(s);
800: if (debug) {
801: logger.log(BasicLevel.DEBUG, "New sequence: " + "name="
802: + s.name + " / datastoreName = " + s.datastoreName
803: + " / factoryClass = " + s.factoryClass
804: + " / strategy = " + s.strategy);
805: }
806:
807: return s;
808: }
809:
810: private void addJoinToClass(SpeedoJoin j, String joinTableName,
811: SpeedoClass sc) {
812: sc.addJoin(j);
813: if (sc.mainTable != null) {
814: j.mainTable = sc.mainTable;
815: }
816: if (joinTableName != null) {
817: j.extTable = new SpeedoTable();
818: j.extTable.name = joinTableName;
819: j.extTable.join = j;
820: }
821: }
822:
823: private Object treatColumn(Node node, Object mo)
824: throws SpeedoException {
825: SpeedoColumn c = new SpeedoColumn();
826: Node n = node.getAttributes().getNamedItem("name");
827: if (n == null) {
828: c.name = n.getNodeValue();
829: }
830: n = node.getAttributes().getNamedItem("target");
831: if (n == null) {
832: c.targetColumn = n.getNodeValue();
833: }
834: n = node.getAttributes().getNamedItem("target-field");
835: if (n == null) {
836: c.targetField = n.getNodeValue();
837: }
838: n = node.getAttributes().getNamedItem("jdbc-type");
839: if (n == null) {
840: c.jdbcType = n.getNodeValue();
841: }
842: n = node.getAttributes().getNamedItem("sql-type");
843: if (n == null) {
844: c.sqlType = n.getNodeValue();
845: }
846: n = node.getAttributes().getNamedItem("length");
847: if (n == null) {
848: c.length = Integer.parseInt(n.getNodeValue());
849: }
850: n = node.getAttributes().getNamedItem("scale");
851: if (n == null) {
852: c.scale = Integer.parseInt(n.getNodeValue());
853: }
854: c.allowNull = getBooleanAttributeValue(node, "allows-null",
855: c.allowNull);
856: n = node.getAttributes().getNamedItem("default-value");
857: if (n == null) {
858: c.defaultValue = n.getNodeValue();
859: }
860: if (mo instanceof SpeedoJoin) {
861: SpeedoJoin j = (SpeedoJoin) mo;
862: if (j.extTable != null) {
863: c.table = j.extTable;
864: }
865: SpeedoJoinColumn sjc = new SpeedoJoinColumn();
866: sjc.column = c;
867: j.columns.add(sjc);
868: logger.log(BasicLevel.DEBUG, "add column " + c.name
869: + " to a join");
870: } else if (mo instanceof SpeedoField) { //class.field.column
871: SpeedoField f = (SpeedoField) mo;
872: f.addColumn(c);
873: logger.log(BasicLevel.DEBUG, "add column " + c.name
874: + " to the field " + f.name);
875: } else if (mo instanceof SpeedoMap) {
876: SpeedoMap m = (SpeedoMap) mo;
877: String parentNodeName = node.getParentNode().getNodeName();
878: if ("key".equals(parentNodeName)) {
879: //class.field.key.column
880: m.keyColumns = c;
881: if (c.table == null && m.moField.columns != null
882: && m.moField.columns.length > 0) {
883: //use the same table than the value of the map.
884: c.table = m.moField.columns[0].table;
885: }
886: logger.log(BasicLevel.DEBUG, "add column " + c.name
887: + " to the key of map field " + m.moField.name);
888: } else if ("value".equals(parentNodeName)) {
889: if (m.moField.columns == null
890: || m.moField.columns.length == 0) {
891: m.moField.addColumn(c);
892: } else if (m.moField.columns.length == 1) {
893: m.moField.columns[0].merge(c);
894: } else {
895: logger
896: .log(
897: BasicLevel.WARN,
898: "Column '"
899: + c.name
900: + "' definition ignored (several column already defined for the field "
901: + m.moField.getSourceDesc());
902: }
903: logger.log(BasicLevel.DEBUG, "add column " + c.name
904: + " to the value of map field "
905: + m.moField.name);
906: }
907: } else if (mo instanceof SpeedoCollection) {
908: ((SpeedoCollection) mo).moField.addColumn(c);
909: logger.log(BasicLevel.DEBUG, "add column " + c.name
910: + " to the collection field "
911: + ((SpeedoCollection) mo).moField.name);
912: } else if (mo instanceof SpeedoArray) {
913: ((SpeedoArray) mo).moField.addColumn(c);
914: logger.log(BasicLevel.DEBUG, "add column " + c.name
915: + " to the array field "
916: + ((SpeedoArray) mo).moField.name);
917: } else if (mo instanceof SpeedoDiscriminator) {
918: ((SpeedoDiscriminator) mo).elements.add(c);
919: } else if (mo instanceof SpeedoIndex) {
920: SpeedoIndex si = (SpeedoIndex) mo;
921: si.columnNames.add(c.name);
922: if (si.table == null && c.table != null) {
923: si.table = c.table.name;
924: }
925: logger.log(BasicLevel.DEBUG, "add column " + c.name
926: + " to an index");
927: } else if (mo instanceof SpeedoVersion) {
928: //TODO: non visible column is not suported
929: } else if (mo instanceof SpeedoIdentity) {
930: //TODO: non visible column is not suported
931: }
932: //TODO: foreign-key.column
933: //TODO: order.column
934: //TODO: unique.column
935: return c;
936: }
937:
938: private static String getStringAttributeValue(Node node,
939: String attribName, String defaultValue) {
940: Node n = node.getAttributes().getNamedItem(attribName);
941: if (n != null) {
942: return n.getNodeValue();
943: } else {
944: return defaultValue;
945: }
946: }
947:
948: private static boolean getBooleanAttributeValue(Node node,
949: String attribName, boolean defaultValue) {
950: Node n = node.getAttributes().getNamedItem(attribName);
951: if (n != null) {
952: return Boolean.valueOf(n.getNodeValue()).booleanValue();
953: } else {
954: return defaultValue;
955: }
956: }
957:
958: }
|