KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > mapper > mapping > Loader


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.mapper.mapping;
24
25 import java.io.File JavaDoc;
26 import java.lang.reflect.Constructor JavaDoc;
27 import java.net.MalformedURLException JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.sql.SQLException JavaDoc;
30 import java.util.*;
31
32 import org.xml.sax.*;
33 import org.xquark.mapping.CompilationContext;
34 import org.xquark.mapping.Generator;
35 import org.xquark.mapping.UserGenerator;
36 import org.xquark.mapper.dbms.AbstractConnection;
37 import org.xquark.mapper.metadata.RepositoryConstants;
38 import org.xquark.mapper.util.RepositoryProperties;
39 import org.xquark.schema.*;
40 import org.xquark.util.DefaultElementHandler;
41 import org.xquark.util.ElementHandler;
42 import org.xquark.util.SAXLoader;
43 import org.xquark.xml.xdbc.XMLErrorHandler;
44 import org.xquark.xpath.NodeKind;
45 import org.xquark.xpath.XNode;
46
47 /** This class is responsible for building the memory reprezentation of the
48  * mapping (RepositoryMapping) from a mapping file.
49  * @see org.xquark.mapper.metadata.RepositoryMapping
50  */

51 public class Loader extends SAXLoader implements MappingConstants
52 {
53     private static final String JavaDoc RCSRevision = "$Revision: 1.7 $";
54     private static final String JavaDoc RCSName = "$Name: $";
55
56     private RepositoryMapping colMapping =null;
57     private MappingFactory factory;
58     private XMLReader reader;
59     private AbstractConnection conn;
60     private SchemaManager manager;
61     /** Used to load user generators */
62     private ClassLoader JavaDoc classLoader = null;
63     private boolean generate =false;
64     private String JavaDoc version ="1.0";
65     private BuilderMappingContext context =null;
66     private Type currentType = null;
67     private List scope = new ArrayList();
68     /** Type Mappings */
69     private String JavaDoc currentNamedMap = null; // contains the current named mapping
70
private HashMap namedMappings = new HashMap(); // {name, [scopeItem1, scopeItem2, ...]}
71
/* If not null, warning are sent to it */
72     private XMLErrorHandler messageHandler = null;
73     /* This flag is used to desactivate OID tables in mapping for mapper */
74     private boolean userTablesOnly = false;
75
76     /** Constructor
77      * @param reader Parser used to analyse mapping file.
78      * @param conn JDBC connection used to retrieve database metadata.
79      * @param generate If true, mapping is loaded even if relational tables
80      * are not present : mapping is loaded for table generation.
81      * If false, table existence must be verified.
82      */

83     public Loader(
84         XMLReader reader,
85         AbstractConnection conn,
86         SchemaManager manager,
87         boolean generate) {
88         this(reader, conn, manager, null, generate);
89     }
90
91     public Loader(
92         XMLReader reader,
93         AbstractConnection conn,
94         SchemaManager manager,
95         ClassLoader JavaDoc loader,
96         boolean generate) {
97             super(null);
98             setElementHandler(new MappingHandler());
99             this.reader = reader;
100             this.conn = conn;
101             this.manager = manager;
102             this.generate = generate;
103             if (loader == null)
104                 classLoader = getClass().getClassLoader();
105             else
106                 classLoader = loader;
107         }
108     
109     public RepositoryMapping load(InputSource source, MappingFactory factory, boolean userTablesOnly)
110     throws java.io.IOException JavaDoc, SAXException, SQLException JavaDoc
111     {
112         return load(source, factory, null, userTablesOnly);
113     }
114             
115     public RepositoryMapping load(InputSource source, MappingFactory factory,
116             XMLErrorHandler messageHandler, boolean userTablesOnly)
117     throws java.io.IOException JavaDoc, SAXException, SQLException JavaDoc
118     {
119         this.colMapping = (RepositoryMapping)factory.getTree();
120         this.factory = factory;
121         this.messageHandler = messageHandler;
122         this.userTablesOnly = userTablesOnly;
123         currentType = null;
124         scope.clear();
125         namedMappings.clear();
126         reader.setContentHandler(this);
127         reader.parse(source);
128         colMapping.initialize(conn);
129         return colMapping;
130     }
131
132     private void notifyUnknownElement(String JavaDoc uri, String JavaDoc name)
133     throws SAXException
134     {
135         throw new SAXParseException("Syntax error : the element \"" + name
136                                + "\" with namespace \"" + uri + "\""
137                                + " is not part of the mapping language.",
138                                getDocumentLocator());
139     }
140
141     private boolean isMappingNamespace(String JavaDoc uri) {
142         return BRIDGE_MAPPING_URI.equals(uri)
143             || BRIDGE_MAPPING_URI_1_0.equals(uri)
144             || MAPPING_URI.equals(uri);
145     }
146
147     private void initMapping(Attributes atts) throws SAXException
148     {
149         context = new BuilderMappingContext(factory); // TO MOVE adding a reset
150
// to context ?
151
String JavaDoc ver = atts.getValue("", VERSION_ATTR);
152         if (ver != null)
153             version = ver;
154         URL JavaDoc base = null;
155         String JavaDoc systemId = getDocumentLocator().getSystemId();
156         if (systemId != null) {
157             try {
158                 base = new URL JavaDoc(systemId);
159             } catch (MalformedURLException JavaDoc ex) {
160                 // should not happen
161
}
162         }
163         String JavaDoc schemaLocations = atts.getValue("", SCHEMA_LOCATION_ATTR);
164         if (schemaLocations == null) {
165             schemaLocations = atts.getValue("", NO_NS_SCHEMA_LOCATION_ATTR);
166             if (schemaLocations != null)
167                 manager.addSchemaLocation(null, resolveSchemaURI(schemaLocations, base));
168         }
169         else {
170             StringTokenizer tok = new StringTokenizer(schemaLocations);
171             while (tok.hasMoreTokens()) {
172                 String JavaDoc ns = tok.nextToken();
173                 if (!tok.hasMoreTokens()) {
174                     throw new SAXParseException("Odd number of values in schemaLocation attribute: "
175                             + schemaLocations, getDocumentLocator());
176                 }
177                 manager.addSchemaLocation(ns, resolveSchemaURI(tok.nextToken(), base));
178             }
179         }
180     }
181
182     private String JavaDoc resolveSchemaURI(String JavaDoc loc, URL JavaDoc base) throws SAXParseException {
183         URL JavaDoc uri = null;
184         try {
185             if (base == null) {
186                 File JavaDoc wDir = new File JavaDoc(".");
187                 try {
188                     base = new URL JavaDoc(wDir.toURL().toExternalForm());
189                 } catch (MalformedURLException JavaDoc ex) {
190                     // no op : try without base
191
}
192                 uri = new URL JavaDoc(base, loc);
193             } else
194                 uri = new URL JavaDoc(base, loc);
195         } catch (MalformedURLException JavaDoc ex) {
196             throw new SAXParseException(
197                     "The location '"
198                             + loc
199                             + "' is malformed or it is relative and your input source does not provide a base URI.",
200                     getDocumentLocator());
201             // if invalid URI, ignore it
202
}
203         return uri.toString();
204     }
205     
206     private String JavaDoc resolvePrefix(String JavaDoc qname) throws SAXException {
207         String JavaDoc prefix = "";
208         int index = qname.indexOf(':');
209         if (index > 0) prefix = qname.substring(0, index);
210         String JavaDoc ns = getPrefixMapping(prefix);
211         if (ns == null && !prefix.equals(""))
212         throw new SAXParseException("Unknown namespace prefix " + prefix, getDocumentLocator());
213         return ns;
214     }
215
216     private String JavaDoc getLocalName(String JavaDoc qname) {
217         int index = qname.indexOf(':');
218         if (index > 0) return qname.substring(index+1);
219         else return qname;
220     }
221
222     private String JavaDoc getTableNamePart(String JavaDoc columnName, TableMappingImpl defaultTable) throws SAXException
223     {
224         String JavaDoc tablePart;
225         int index = columnName.lastIndexOf('.');
226         if (index != -1)
227             return columnName.substring(0, index);
228         else
229         {
230             TableMappingImpl tableMapping;
231             if (defaultTable == null) {
232                 tableMapping = getCurrentTableMapping();
233                 if (tableMapping == null)
234                     throw new SAXParseException("No table name is specified in '" + columnName
235                         + "' column name specification and no default table mapping was encountered.",
236                         getDocumentLocator());
237             }
238             else
239                 tableMapping = defaultTable;
240                 
241             return tableMapping.getTableName();
242         }
243     }
244
245     private String JavaDoc getTableNamePart(String JavaDoc columnName) throws SAXException
246     {
247         return getTableNamePart(columnName, null);
248     }
249
250     private String JavaDoc getColumnNamePart(String JavaDoc columnName) throws SAXException {
251         int index = columnName.lastIndexOf('.');
252         if (index == -1)
253             return columnName;
254         else
255             return columnName.substring(index+1);
256     }
257
258     private String JavaDoc checkColumnName(String JavaDoc columnName) throws SAXException {
259         return checkColumnName(columnName, null);
260     }
261
262     private String JavaDoc checkColumnName(String JavaDoc columnName, TableMappingImpl tm)
263     throws SAXException {
264         String JavaDoc tableName = getTableNamePart(columnName, tm);
265         columnName = getColumnNamePart(columnName);
266         if (tm == null)
267             tm = findMappingInScope(tableName);
268         else if (!tm.getTableName().equals(tableName))
269             throw new SAXParseException(
270                 "Column mapping cannot be defined here for table " + tableName,
271                 getDocumentLocator());
272         if (tm == null)
273             throw new SAXParseException(
274                 "Table " + tableName + " is not in scope",
275                 getDocumentLocator());
276         TableMetaData meta = tm.getMetaData();
277         if (meta != null && meta.getColumnMetaData(columnName) == null)
278             throw new SAXParseException(
279                 "Column "
280                     + columnName
281                     + " is not a column of table "
282                     + tableName,
283                 getDocumentLocator());
284         return columnName;
285     }
286
287     private ColumnMapping checkColumnRef(
288         String JavaDoc columnName,
289         TableMappingImpl tm,
290         List refChildTableMappings)
291         throws SAXException {
292         
293         String JavaDoc tableName = getTableNamePart(columnName);
294         columnName = getColumnNamePart(columnName);
295         // look in inner mapping first
296
if (tm == null && refChildTableMappings != null) {
297             int len = refChildTableMappings.size();
298             TableMappingImpl myTm = null;
299             for (int i = 0; i < len; i++) {
300                 myTm = (TableMappingImpl)refChildTableMappings.get(i);
301                 if (myTm.getTableName().equals(tableName))
302                     tm = myTm;
303             }
304         }
305         // then in scope
306
if (tm == null)
307             tm = findMappingInScope(tableName);
308         if (tm == null)
309             throw new SAXParseException(
310                 "Table " + tableName + " is not in scope",
311                 getDocumentLocator());
312         else if (!tm.getTableName().equals(tableName))
313             throw new SAXParseException(
314                 "Column mapping does not refer to table " + tableName,
315                 getDocumentLocator());
316
317         ColumnMapping cm = tm.getColumnMapping(columnName);
318         if (cm == null)
319             throw new SAXParseException(
320                 "Unknown column " + columnName + " in table " + tableName,
321                 getDocumentLocator());
322         return cm;
323     }
324
325     private int getAction(Attributes atts) throws SAXException
326     {
327         String JavaDoc actionName = atts.getValue("", ACTION_ATTR);
328         int action = INSERT;
329         if (actionName != null)
330         {
331             if (actionName.equals(INSERT_VALUE)) action = INSERT;
332             else if (actionName.equals(CHECK_VALUE)) action = CHECK;
333             else if (actionName.equals(UPDATE_VALUE)) action = UPDATE;
334             else if (actionName.equals(SELECT_VALUE)) action = SELECT;
335             else
336             throw new SAXParseException("Illegal action value: "+actionName,
337                 getDocumentLocator());
338         }
339         return action;
340     }
341     private int getBatchSize(Attributes atts) throws SAXException
342     {
343         int batchSize = RepositoryProperties.getIntProperty(RepositoryConstants.CONF_USER_BATCHSIZE);
344         String JavaDoc size = atts.getValue("", BATCH_SIZE_ATTR);
345         if (size != null)
346             batchSize = Integer.parseInt(size);
347         return batchSize;
348     }
349
350     /** Process key and select attributes for a column mapping building
351      * the role property for column mapping.
352      */

353     private int getRole(Attributes atts,int def) throws SAXException
354     {
355         int role = def;
356         String JavaDoc inKey = atts.getValue("", IN_KEY_ATTR);
357         if (inKey != null)
358         {
359             if (inKey.equals(TRUE_VALUE) || inKey.equals(TRUE_NUM_VALUE)) role |= KEY_ROLE;
360             else if (inKey.equals(FALSE_VALUE) || inKey.equals(FALSE_NUM_VALUE)) role &= ~KEY_ROLE;
361             else
362             throw new SAXParseException("Illegal value: "+inKey+" in inKey attribute", getDocumentLocator());
363         }
364         String JavaDoc inSelect = atts.getValue("", IN_SELECT_ATTR);
365         if (inSelect != null)
366         {
367             if (inSelect.equals(TRUE_VALUE) || inSelect.equals(TRUE_NUM_VALUE))
368                 role |= SELECT_ROLE;
369             else if (inSelect.equals(FALSE_VALUE) || inSelect.equals(FALSE_NUM_VALUE))
370                 role &= ~SELECT_ROLE;
371             else
372                 throw new SAXParseException("Illegal value: " + inSelect + " in inSelect attribute",
373                     getDocumentLocator());
374         }
375         return role;
376     }
377
378     private ElementDeclaration getElementDeclaration(String JavaDoc elementName)
379     throws SAXException
380     {
381         if (elementName == null)
382         throw new SAXParseException("Missing name attribute in element mapping declaration",
383             getDocumentLocator());
384         /* Look in the ElementDeclaration stack if present*/
385         String JavaDoc namespace = resolvePrefix(elementName);
386         String JavaDoc localName = getLocalName(elementName);
387         ElementDeclaration decl = null;
388         /* if the element corresponds to a complex type, look for the element in the complex type */
389         if (context.isEmpty() && (currentType != null))
390             decl = currentType.getElementDeclaration(namespace, localName);
391         if (decl == null)
392             decl = context.getElementDeclaration(namespace, localName);
393         if (decl == null) {
394             if (manager.getSchema(namespace) == null)
395                 throw new SAXParseException("Schema "+ (namespace == null ?
396                         "":"for namespace '" + namespace + "' ")
397                         + "could not be loaded.", getDocumentLocator());
398             else
399                 throw new SAXParseException("Unknown element '" + elementName
400                     +"' in element mapping declaration", getDocumentLocator());
401
402         }
403         return decl;
404     }
405
406     private AttributeDeclaration getAttributeDeclaration(String JavaDoc attrName) throws SAXException
407     {
408         if (attrName == null)
409         throw new SAXParseException("Missing name attribute in attribute mapping declaration",
410             getDocumentLocator());
411         String JavaDoc namespace = resolvePrefix(attrName);
412         String JavaDoc localName = getLocalName(attrName);
413         AttributeDeclaration decl = null;
414         if (context.isEmpty() && (currentType != null))
415             decl = currentType.getAttributeDeclaration(namespace, localName);
416         if (decl == null)
417             decl = context.getAttributeDeclaration(namespace, localName);
418         if (decl == null) {
419             if (manager.getSchema(namespace) == null)
420                 throw new SAXParseException("Schema "+ (namespace == null ?
421                         "":"for namespace '" + namespace + "' ")
422                         + "could not be loaded.", getDocumentLocator());
423             else
424                 throw new SAXParseException("Unknown attribute '" + attrName
425                     +"' in attribute mapping declaration", getDocumentLocator());
426         }
427         return decl;
428     }
429
430     private Generator getUserGenerator(String JavaDoc genClass, String JavaDoc table, String JavaDoc column) throws SAXException
431     {
432         try {
433             Class JavaDoc generatorClass = Class.forName(genClass, true, classLoader);
434             // check the class implements the generator interface
435

436             Class JavaDoc[] interfaces = generatorClass.getInterfaces();
437             int i = 0;
438             for (; i < interfaces.length && interfaces[i] != UserGenerator.class; i++);
439             if (i == interfaces.length)
440                 throw new SAXParseException("Class '" + genClass
441                 + "' is not an UserGenerator instance", getDocumentLocator());
442                 
443             // get the constructor with compilation context if exist
444
Generator gen = null;
445             try {
446                 Constructor JavaDoc constructor = generatorClass.getConstructor(
447                     new Class JavaDoc[] {CompilationContext.class});
448                 gen = (Generator)constructor.newInstance(
449                     new Object JavaDoc[] {buildCompilationContext(table, column)});
450             }
451             catch (NoSuchMethodException JavaDoc e) {
452                 // try the default constructor
453
gen = (Generator)generatorClass.newInstance();
454             }
455             return gen;
456         }
457         catch (ClassNotFoundException JavaDoc ex1) {
458             throw new SAXParseException("Generator class '"+genClass+"' not found",
459                 getDocumentLocator(), ex1);
460         }
461         catch (IllegalAccessException JavaDoc ex2) {
462             throw new SAXParseException("Could not access constructor in generator class "
463             + genClass, getDocumentLocator(), ex2);
464         }
465         catch (InstantiationException JavaDoc ex3) {
466             throw new SAXParseException("Instantiation of generator class '"
467             + genClass + "' failed", getDocumentLocator(), ex3);
468         }
469         catch (ClassCastException JavaDoc ex4) {
470             throw new SAXParseException("Generator class '"+genClass
471             +"' does not implement the interface org.xquark.xml.mapping.Generator",
472             getDocumentLocator(), ex4);
473         } catch (Exception JavaDoc ex) {
474             throw new SAXParseException("Failed to load generator class " + genClass
475             , getDocumentLocator(), ex);
476         }
477     }
478
479     private CompilationContext buildCompilationContext(String JavaDoc table, String JavaDoc column) {
480         CompilationContext ret = new CompilationContext();
481         ret.put(CompilationContext.TABLE_NAME, table);
482         ret.put(CompilationContext.COLUMN_NAME, column);
483         ret.put(CompilationContext.DBMS_TYPE, String.valueOf(conn.getDBMSType()));
484         ret.put(CompilationContext.USE_QUOTES_4_DDL, String.valueOf(conn.useDoubleQuotes4DDLNames()));
485         return ret;
486     }
487
488     private Generator getValueGenerator(Declaration decl) throws SAXException {
489         return getValueGenerator(decl.getType());
490     }
491     private Generator getValueGenerator(Type type) throws SAXException
492     {
493         if (!hasChararacterData(type))
494             throw new SAXParseException(
495             "Cannot reference $NodeValue in column mapping within an XML node without character data.",
496             getDocumentLocator());
497
498         SimpleType simple = type.getValueType();
499         if (simple != null)
500             return new ValueGenerator();
501         
502         throw new SAXParseException(
503                 "Cannot reference $NodeValue in complex element mapping",
504                 getDocumentLocator());
505     }
506     
507     private boolean hasChararacterData(Type type) {
508         boolean ret = true;
509         if (type instanceof ComplexType)
510         {
511             int contentType = ((ComplexType)type).getContentType();
512             if (contentType == SchemaConstants.ELEMENT_ONLY || contentType == SchemaConstants.EMPTY)
513                 ret = false;
514         } // else simple type
515

516         return ret;
517     }
518     
519     private Generator getSystemVariableGenerator(String JavaDoc source, Type type) throws SAXException
520     {
521         if (source.equals(VALUE_VALUE))
522             return getValueGenerator(type);
523         else
524         {
525             Generator generator = SystemVariableGenerator.createGenerator(source);
526             if (generator == null)
527                 throw new SAXParseException("Unknown system variable " + source
528                 + " in column mapping declaration", getDocumentLocator());
529             return generator;
530         }
531     }
532
533     /* used for complexType table mapping only */
534     private TableMappingImpl buildTypeTableMapping(Attributes atts) throws SAXException
535     {
536         String JavaDoc typeName = atts.getValue("", TYPE_ATTR);
537         if (typeName == null)
538             throw new SAXParseException("Missing type attribute in type mapping specification",
539                 getDocumentLocator());
540         String JavaDoc namespace = resolvePrefix(typeName);
541         Type type = context.createTypeMapping(namespace, getLocalName(typeName)); // Update the schema context (create a root node for type)
542

543         if (type == null)
544             throw new SAXParseException("Unknown type " + typeName
545                 + " in mapping declaration", getDocumentLocator());
546         String JavaDoc name = atts.getValue("", NAME_ATTR);
547         if (name == null || name.length() == 0)
548             throw new SAXParseException("Missing name in mapping declaration",
549                     getDocumentLocator());
550         TableMappingImpl res = buildTableMapping(type, atts);
551         currentNamedMap = name;
552         List typeScope = new ArrayList();
553         typeScope.add(pushScope(res));
554         namedMappings.put(name, typeScope); // put the last Table mapping encountered as the first to consider (push)
555
return res;
556     }
557
558     private TableMappingImpl buildTableMapping(SchemaComponent comp,Attributes atts)
559     throws SAXException
560     {
561         TableMappingImpl result;
562         String JavaDoc tableName = atts.getValue("", TABLE_ATTR);
563         if (tableName == null || tableName.length() == 0)
564             throw new SAXParseException("Missing table name in mapping declaration",
565                 getDocumentLocator());
566         int action = getAction(atts);
567         result = new TableMappingImpl(colMapping, comp, tableName, conn, action,
568         generate, getBatchSize(atts), userTablesOnly);
569         context.register(result);
570         return result;
571     }
572
573     private void buildGeneratorColumnMapping(Attributes atts, boolean substitution)
574     throws SAXException {
575         TableMapping tm = peekScope().getLastInserted();
576         SchemaComponent sc = null;
577         if (tm == null) // for instance when called by an element substitution generator
578
sc = context.getCurrentNode().getSchemaComponent();
579         else
580             sc = tm.getSchemaComponent();
581         buildGeneratorColumnMapping(atts, sc, substitution);
582     }
583     
584     /**
585      * Process generator column mapping object creation.
586      */

587     private void buildGeneratorColumnMapping(Attributes atts, SchemaComponent sc, boolean substitution)
588     throws SAXException
589     {
590         Type type = null;
591         if (sc instanceof Type)
592             type = (Type)sc;
593         else // declaration
594
type = ((Declaration)sc).getType();
595         
596         TableMappingImpl tableMapping = getCurrentTableMapping();
597         String JavaDoc columnName = checkColumnName(atts.getValue("", COLUMN_ATTR), tableMapping);
598         Generator generator = null;
599         String JavaDoc ref = atts.getValue("", REF_ATTR);
600         String JavaDoc source = atts.getValue("", VAR_ATTR);
601         String JavaDoc genClass = atts.getValue("", USER_GENERATOR_ATTR);
602         if (genClass == null)
603             genClass = atts.getValue("", METHOD_ATTR); // 4 compatibility reasons
604

605         // NIY String XpathRef = atts.getValue("", XPATH_ATTR);
606

607         int defaultRole = 0;
608         if (ref != null)
609         {
610             if (source != null || genClass != null)
611             throw new SAXParseException("Can have only one of " + REF_ATTR + ", "
612                                     + VAR_ATTR + " and " + USER_GENERATOR_ATTR
613                                     + " attributes in generator declaration ("
614                                     + tableMapping.getTableName() + "." + columnName + ").",
615                                     getDocumentLocator());
616             peekScope().addPendingRef(columnName, ref, sc); // processed when getting out of the surrounding element
617
defaultRole = 0;
618         }
619         else if (source != null)
620         {
621             if (genClass != null)
622             throw new SAXParseException("Can have only one of "
623                                     + VAR_ATTR + " and " + USER_GENERATOR_ATTR
624                                     + " attributes in generator declaration ("
625                                     + tableMapping.getTableName() + "." + columnName + ").",
626                                     getDocumentLocator());
627             generator = getSystemVariableGenerator(source, type);
628             defaultRole = KEY_ROLE;
629         }
630         else if (genClass != null)
631         {
632             generator = getUserGenerator(genClass, tableMapping.getTableName(), columnName);
633             defaultRole = KEY_ROLE;
634         }
635         else
636             throw new SAXParseException("One of " + REF_ATTR + ", " + VAR_ATTR + " and " + USER_GENERATOR_ATTR
637                                     + " attributes must be specified in column mapping declaration ("
638                                     + tableMapping.getTableName() + "." + columnName + ").",
639                                     getDocumentLocator());
640         int role = getRole(atts, defaultRole);
641         // If the XML node is an attribute or a simple content element, the generator specified
642
//
643
if (substitution || generator instanceof ValueGenerator){
644             if (type instanceof SimpleType || (type instanceof ComplexType
645                 && ((ComplexType) type).getContentType() == SchemaConstants.TEXT_ONLY))
646                 context.register(new ColumnMappingImpl(tableMapping, sc, 1,
647                         columnName, getRole(atts, SELECT_ROLE), generator,
648                         messageHandler));
649             else
650                 throw new SAXParseException(
651                         "A substitution generator cannot be defined on a complex content element.",
652                         getDocumentLocator());
653         }
654         else
655             new ColumnMappingImpl(tableMapping, null, 1, columnName, role, generator, messageHandler);
656     }
657
658     
659     /**
660      * This method browse element hierarchy in schema to determine the occurence
661      * bounds within a given ancestor.
662      *
663      * @param elem
664      * element which occurence bounds are to be calculated
665      * @param ancestor
666      * scope where occurence is searched
667      * @param occurrences
668      * an int[2] array for collecting result. {min_occurs,
669      * max_occurs}
670      * @return the child element declaration of the ancestor.
671      */

672     private ElementDeclaration computeHierarchyInfo(SchemaComponent ancestor,int[] occurrences)
673     {
674         ElementDeclaration child = null;
675         SchemaComponent parent, current = null;
676         ComplexType type;
677         int[] occurrenceCount;
678         long mult;
679         Iterator it = context.iterator();
680         if (it.hasNext()) // if we're processing an attribute elem is null and occurences is filled with atttribute occurence
681
current = (ElementDeclaration)it.next();
682         while (it.hasNext() && current != ancestor)
683         {
684             parent = (SchemaComponent)it.next();
685             if (parent instanceof Declaration)
686                 type = (ComplexType)((Declaration)parent).getType();
687             else
688                 type = (ComplexType)parent;
689             
690             occurrenceCount = type.getDeclarationOccurrence
691                                 (
692                                 current.getNamespace(),
693                                 current.getName()
694                                 );
695             for (int i = 0; i <= 1; i++)
696             {
697                 mult = (long)occurrences[i] * (long)occurrenceCount[i];
698                 occurrences[i] = (mult <= Integer.MAX_VALUE ? (int)mult : Integer.MAX_VALUE);
699             }
700
701             
702             child = (ElementDeclaration)current;
703             current = parent;
704         }
705         return child;
706     }
707     
708     private String JavaDoc buildElementColumnMapping(String JavaDoc columnName,Attributes atts, ElementDeclaration decl, boolean updateWhenMissing)
709     throws SAXException
710     {
711         String JavaDoc tableName = getTableNamePart(columnName);
712         columnName = checkColumnName(columnName);
713         TableMappingImpl tableMapping = findMappingInScope(tableName);
714         int[] occurrences = { 1, 1 };
715         ElementDeclaration ancestorChild =
716         computeHierarchyInfo(tableMapping.getSchemaComponent(), occurrences);
717
718         if (occurrences[1] > 1)
719             throw new SAXParseException("Multivalued element " + decl
720                 + " cannot be mapped onto a column", getDocumentLocator());
721         if (ancestorChild != null)
722         tableMapping.addMappedChild(ancestorChild);
723         String JavaDoc ref = atts.getValue("", REF_ATTR);
724         
725         Generator generator = null;
726         if (ref == null)
727             generator = getValueGenerator(decl);
728         int role = getRole(atts, SELECT_ROLE);
729         context.register(new ColumnMappingImpl(tableMapping, decl, occurrences[0],
730             columnName, role, generator, updateWhenMissing, messageHandler));
731         return ref;
732     }
733
734     /** Ref generators are created here (should it be a real generator or a
735      * table-column mapping).
736      * @param columnName
737      * @param refTable
738      * @param refCol
739      * @throws SAXException
740      */

741     private void completePendingRef(
742         TableMappingImpl defaultTable,
743         String JavaDoc columnName,
744         TableMappingImpl refTable,
745         String JavaDoc refCol,
746         List refChildTableMappings,
747         MappingNode originalContext
748         )
749         throws SAXException {
750         Generator generator =
751             new ColumnRefGenerator(checkColumnRef(refCol, refTable, refChildTableMappings));
752         String JavaDoc tableName = getTableNamePart(columnName, defaultTable);
753         TableMappingImpl tableMapping = findMappingInScope(tableName);
754         if (tableMapping == null) // in the case of a type scope cut from the current scope
755
tableMapping = defaultTable;
756         columnName = checkColumnName(columnName, tableMapping);
757         ColumnMappingImpl mapping =
758             (ColumnMappingImpl) tableMapping.getColumnMapping(columnName);
759         // Move the table-column mapping generator to the end (does nothing 4 ref generator)
760
originalContext.moveColumnMappingToTheEnd(mapping);
761         mapping.setGenerator(generator);
762     }
763
764     private void completePendingRefs(List refs) throws SAXException {
765         if (refs != null) {
766             int len = refs.size();
767             RefItem refItem = null;
768             for (int i = 0; i < len; i++) {
769                 refItem = (RefItem) refs.get(i);
770                 completePendingRef(
771                     refItem.defautTableMapping,
772                     refItem.columnName,
773                     null,
774                     refItem.ref,
775                     refItem.childrenTableMappings,
776                     refItem.contextNode
777                     );
778             }
779         }
780     }
781     
782     private TableMappingImpl completeTableMappingRef(
783         Declaration decl,
784         String JavaDoc columnName,
785         String JavaDoc pendingRef,
786         Attributes atts)
787         throws SAXException {
788         TableMappingImpl tableMapping = checkTableMappingRef(decl, atts);
789         if (tableMapping == null)
790             return null;
791         completePendingRef(null, columnName, tableMapping, pendingRef, null, context.getCurrentNode());
792         return tableMapping;
793     }
794
795     private TableMappingImpl checkTableMappingRef(Declaration decl, Attributes atts)
796     throws SAXException
797     {
798         String JavaDoc map = atts.getValue("", MAP_ATTR);
799         if (map == null) return null;
800         TableMappingImpl tableMapping = postProcessTypeMapping(map);
801         if (tableMapping == null)
802             throw new SAXParseException("Unknown named mapping for name '" + map
803             + "'. Check the named table mapping is defined earlier in the mapping file.",
804             getDocumentLocator());
805         if (tableMapping.getSchemaType() != decl.getType())
806             throw new SAXParseException("The mapping specified for name '" + map
807             + "' does not match the element or attribute type.",
808             getDocumentLocator());
809         return tableMapping;
810     }
811
812     private String JavaDoc buildAttributeColumnMapping(String JavaDoc columnName, Attributes atts, AttributeDeclaration decl, boolean updateWhenMissing)
813     throws SAXException
814     {
815         String JavaDoc tableName = getTableNamePart(columnName);
816         columnName = checkColumnName(columnName);
817         TableMappingImpl tableMapping = findMappingInScope(tableName);
818         int[] occurrences = new int[2];
819         switch (decl.getUse())
820         {
821             case SchemaConstants.REQUIRED:
822                 occurrences[0] = 1;
823                 occurrences[1] = 1;
824                 break;
825             case SchemaConstants.OPTIONAL:
826                 occurrences[0] = 0;
827                 occurrences[1] = 1;
828                 break;
829             case SchemaConstants.PROHIBITED:
830                 occurrences[0] = 0;
831                 occurrences[1] = 0;
832                 break;
833         };
834         ElementDeclaration ancestorChild = computeHierarchyInfo(tableMapping.getSchemaComponent(), occurrences);
835
836         if (occurrences[1] > 1)
837             throw new SAXParseException("Multivalued attribute " + decl
838             + " cannot be mapped onto a column", getDocumentLocator());
839         if (ancestorChild != null)
840         tableMapping.addMappedChild(ancestorChild);
841         String JavaDoc ref = atts.getValue("", REF_ATTR);
842         Generator generator = null;
843         if (ref == null)
844             generator = getValueGenerator(decl);
845         int role = getRole(atts, SELECT_ROLE);
846         context.register(new ColumnMappingImpl(tableMapping, decl, occurrences[0],
847         columnName, role, generator, updateWhenMissing, messageHandler));
848         return ref;
849     }
850
851     private ElementDeclaration startElementMapping(Attributes atts) throws SAXException
852     {
853         ElementDeclaration decl = getElementDeclaration(atts.getValue("", NAME_ATTR));
854         if ((atts.getValue("", REF_ATTR) != null ||
855             atts.getValue("", IN_SELECT_ATTR) != null ||
856             atts.getValue("", IN_KEY_ATTR) != null) &&
857             atts.getValue("", COLUMN_ATTR) == null)
858             throw new SAXParseException(
859             "ref, inKey and inSelect attributes are allowed in element mapping declaration only when the column attribute is present.",
860             getDocumentLocator());
861         return decl;
862     }
863     
864     private AttributeDeclaration startAttributeMapping(Attributes atts) throws SAXException {
865         AttributeDeclaration decl = getAttributeDeclaration(atts.getValue("", NAME_ATTR));
866         if ((atts.getValue("", REF_ATTR) != null ||
867             atts.getValue("", IN_SELECT_ATTR) != null ||
868             atts.getValue("", IN_KEY_ATTR) != null) &&
869             atts.getValue("", COLUMN_ATTR) == null)
870             throw new SAXParseException(
871             "ref, inKey and inSelect attributes are allowed in element mapping declaration only when the column attribute is present.",
872             getDocumentLocator());
873         return decl;
874     }
875
876     /**
877      * Process an element from the mapping file.
878      * Used for root level (MAPPING element) & first level (ELEMENT or MAP elements) (TO BE IMPROVED).
879      * Replaced by the corresponding handler at the deeper levels.
880      */

881     class MappingHandler extends DefaultElementHandler
882     {
883         private static final String JavaDoc RCSRevision = "$Revision: 1.7 $";
884         private static final String JavaDoc RCSName = "$Name: $";
885         public ElementHandler startElement(String JavaDoc namespaceURI,String JavaDoc localName,Attributes atts)
886         throws SAXException
887         {
888             if (isMappingNamespace(namespaceURI))
889             {
890                 /* process the root MAPPING element (level 0) */
891                 if (localName.equals(MAPPING_TAG))
892                 {
893                     initMapping(atts);
894                     return this; // Provide handler for level 1
895
}
896                 /* process the MAP element (level 1 for Type Mapping) */
897                 else if (localName.equals(MAP_TAG))
898                 {
899                     TableMappingImpl mapping = buildTypeTableMapping(atts);
900                     currentType = (Type)mapping.getSchemaComponent();
901                     return new TableMappingHandler(); // Provide handler for next level
902
}
903                 /* process the ELEMENT element (level 1) containing only a MAP element (because of the level) */
904                 else if (localName.equals(ELEMENT_TAG))
905                 {
906                     ElementDeclaration decl = startElementMapping(atts); // Retrieves the Element decl from the schema
907
context.createElementMapping(decl, (checkTableMappingRef(decl, atts) != null)); // Update the schema context
908

909                     /* Create scope */
910                     pushScope();
911                     
912                     return new ElementMappingHandler(); // Provide handler for next level
913
}
914             }
915             notifyUnknownElement(namespaceURI, localName);
916             return this;
917         }
918
919         public void endElement(String JavaDoc namespaceURI,String JavaDoc localName) throws SAXException {
920             if (isMappingNamespace(namespaceURI))
921             {
922                 if (localName.equals(MAP_TAG))
923                 {
924                     // NOTE: Scope are now attached to the surrounding element, except for top-level mappings
925
popScope();
926                     context.popType(); // Update the schema context removing the Element declaration from the schema
927
currentType = null;
928                     currentNamedMap = null;
929                 }
930                 else if (localName.equals(ELEMENT_TAG)) {
931                     postProcessEnclosedTableMapping();
932                     context.pop(); // Update the schema context removing the Element declaration from the schema
933
}
934                 // no op when getting out of MAPPING element.
935
}
936         }
937
938
939     }
940
941     /** Process an element from the mapping file when the element encountered
942      * is not a MAP element, i.e., process ELEMENT, ATRIBUTE or GENERATOR elements.
943      * If the mapping element is bound to a column mapping this object is
944      * returned and recycled.
945      * If the mapping element has got a content (ELEMENT or ATTRIBUTE) a new
946      * is created.
947      */

948     class TableMappingHandler extends DefaultElementHandler
949     {
950         private static final String JavaDoc RCSRevision = "$Revision: 1.7 $";
951         private static final String JavaDoc RCSName = "$Name: $";
952
953         private ElementDeclaration eltDecl = null;
954         private AttributeDeclaration attDecl = null;
955         private boolean childExpected = false;
956
957         public ElementHandler startElement(String JavaDoc namespaceURI,String JavaDoc localName,Attributes atts)
958         throws SAXException
959         {
960             String JavaDoc pendingRef = null;
961             childExpected = false;
962             
963             if (isMappingNamespace(namespaceURI))
964             {
965                 String JavaDoc columnName = null;
966                 /* Process the tag corresponding to a column mapping */
967                 if (localName.equals(GENERATOR_TAG))
968                 {
969                     buildGeneratorColumnMapping(atts, false);
970                     return this;
971                 }
972                 /* Process the tag corresponding to an ELEMENT element */
973                 else if (localName.equals(ELEMENT_TAG))
974                 {
975                     boolean updateWhenMissing = Boolean.valueOf(atts.getValue("", UPDATE_WHEN_MISSING_ATTR)).booleanValue();
976                     // Starts a new element table mapping declaration, which should
977
// resolve pending ref if it is not null
978
eltDecl = startElementMapping(atts); // Retrieves the Element decl from the schema
979
context.createElementMapping(eltDecl, (checkTableMappingRef(eltDecl, atts) != null)); // Update the schema context (Now done event for element with no table mapping, to build RepositoryMapping tree)
980

981                     /* A COLUMN attribute exists : it is an empty element corresponding to a column mapping*/
982                     columnName = atts.getValue("",COLUMN_ATTR);
983                     RefItem refItem = null;
984                     if (columnName != null)
985                     {
986                         // build column mapping, returns pending ref if mapping
987
// refers to a foreign table
988
pendingRef = buildElementColumnMapping(columnName, atts, eltDecl, updateWhenMissing);
989                         if (pendingRef == null) // Column mapping complete
990
return this; // parsing ended
991
else
992                         {
993                             // check if mapping is a reference to an existing type mapping,
994
// which should resolve pending ref.
995
// Returns null if not a reference
996
TableMapping mapping = completeTableMappingRef(eltDecl, columnName, pendingRef, atts);
997                             if (mapping == null)
998                                 refItem = peekScope().addPendingRef(columnName, pendingRef, eltDecl);
999                             else
1000                                return this; // parsing ended
1001
}
1002                    }
1003                    
1004                    /* Create scope */
1005                    childExpected = true;
1006                    if (currentNamedMap == null)
1007                        pushScope();
1008                    else
1009                        ((List)namedMappings.get(currentNamedMap)).add(pushScope());
1010                    
1011                    if (refItem != null)
1012                        refItem.childrenTableMappings = peekScope().getTableMappings();
1013                    
1014                    /* This ELEMENT element has a content. A new ElementMappingHandler is created */
1015                    return new ElementMappingHandler(updateWhenMissing); // Provide handler for the content elements
1016
}
1017                /* Process the tag corresponding to an ATTRIBUTE element */
1018                else if (localName.equals(ATTRIBUTE_TAG))
1019                {
1020                    boolean updateWhenMissing = Boolean.valueOf(atts.getValue("", UPDATE_WHEN_MISSING_ATTR)).booleanValue();
1021                    attDecl = startAttributeMapping(atts); // Retrieves the Attribute decl from the schema
1022

1023                    /* A COLUMN attribute exists : it is an empty element corresponding to a column mapping*/
1024                    columnName = atts.getValue("",COLUMN_ATTR);
1025                    RefItem refItem = null;
1026                    if (columnName != null)
1027                    {
1028                        // build column mapping, returns pending ref if mapping
1029
// refers to a foreign table
1030
pendingRef = buildAttributeColumnMapping(columnName, atts, attDecl, updateWhenMissing);
1031                        if (pendingRef == null) // Column mapping complete
1032
return this; // parsing ended
1033
else
1034                        {
1035                            // check if mapping is a reference to an existing type mapping,
1036
// which should resolve pending ref.
1037
// Returns null if not a reference
1038
TableMapping mapping = completeTableMappingRef(attDecl, columnName, pendingRef, atts);
1039                            if (mapping == null)
1040                                refItem = peekScope().addPendingRef(columnName, pendingRef, attDecl);
1041                            else
1042                                return this; // parsing ended
1043
}
1044                    }
1045
1046                    /* Create scope */
1047                    childExpected = true;
1048                    if (currentNamedMap == null)
1049                        pushScope();
1050                    else
1051                        ((List)namedMappings.get(currentNamedMap)).add(pushScope());
1052                    
1053                    if (refItem != null)
1054                        refItem.childrenTableMappings = peekScope().getTableMappings();
1055                    
1056                    /* This ATTRIBUTE element has a content. A new AttributeMappingHandler is created */
1057                    // Starts a new element table mapping declaration
1058
return new AttributeMappingHandler(attDecl, updateWhenMissing); // Provide handler for the MAP element (only content possible for ATTRIBUTE element)
1059
}
1060            }
1061            notifyUnknownElement(namespaceURI, localName);
1062            return this;
1063        }
1064
1065        public void endElement(String JavaDoc namespaceURI,String JavaDoc localName) throws SAXException {
1066            if (isMappingNamespace(namespaceURI))
1067            {
1068                if (localName.equals(ELEMENT_TAG) || localName.equals(ATTRIBUTE_TAG))
1069                {
1070                    if (childExpected && currentNamedMap == null)
1071                        postProcessEnclosedTableMapping();
1072                    if (eltDecl != null)
1073                    {
1074                        eltDecl = null;
1075                        context.pop();
1076                    }
1077                }
1078            }
1079        }
1080    }
1081    
1082    private void postProcessEnclosedTableMapping() throws SAXException
1083    {
1084        postProcessEnclosedTableMapping(peekScope()); // do not pop since scope is used...
1085
popScope();
1086    }
1087    
1088    private TableMappingImpl postProcessTypeMapping(String JavaDoc name) throws SAXException
1089    {
1090        TableMappingImpl ret = null;
1091        Object JavaDoc o = namedMappings.get(name);
1092        
1093        if (o instanceof List) { // only first time, process pending needed
1094
List stack = (List) o;
1095            for (int i = stack.size() - 1; i >= 0; i--) {
1096                postProcessEnclosedTableMapping((ScopeItem) stack.get(i));
1097            }
1098            ret = ((ScopeItem)stack.get(0)).getLastInserted();
1099            namedMappings.put(name, ret);
1100        }
1101        else
1102            ret = (TableMappingImpl) o;
1103        
1104        return ret;
1105    }
1106    
1107    private void postProcessEnclosedTableMapping(ScopeItem scopeItem) throws SAXException
1108    {
1109        // Complete pending refs every table mapping encountered
1110
completePendingRefs(scopeItem.getPendingRefs());
1111
1112        // Initialize table mappings (Now Column mappings are created)
1113
Iterator it = scopeItem.getTableMappings().iterator();
1114                    
1115        while (it.hasNext()) {
1116            ((TableMappingImpl) it.next()).initialize(conn);
1117        }
1118    }
1119    
1120    /** Processes the content of an ELEMENT element.
1121     * Behaves like a TableMappingHandler except if the current mapping element
1122     * is a MAP one. A new TableMappingHandler is then created.
1123     */

1124    class ElementMappingHandler extends TableMappingHandler {
1125        private static final String JavaDoc RCSRevision = "$Revision: 1.7 $";
1126        private static final String JavaDoc RCSName = "$Name: $";
1127        
1128        private boolean updateWhenMissing = false;
1129        private String JavaDoc columnName = null;
1130        
1131        ElementMappingHandler() {}
1132        
1133        ElementMappingHandler(boolean updateWhenMissing) {
1134            this.updateWhenMissing = updateWhenMissing;
1135        }
1136        
1137        public ElementHandler startElement(String JavaDoc namespaceURI, String JavaDoc localName, Attributes atts)
1138        throws SAXException {
1139            if (isMappingNamespace(namespaceURI))
1140            {
1141                if (localName.equals(MAP_TAG))
1142                {
1143                    addMapping2Scope(buildTableMapping(context.top(), atts));
1144                    return new TableMappingHandler();
1145                }
1146                else if (localName.equals(GENERATOR_TAG))
1147                {
1148                    if (columnName != null)
1149                        throw new SAXParseException(
1150                                "Cannot define a generator under an element already mapped on a column.",
1151                                getDocumentLocator()
1152                                );
1153                    buildGeneratorColumnMapping(atts, true);
1154                    return this;
1155                }
1156                else
1157                    return super.startElement(namespaceURI, localName, atts);
1158            }
1159            notifyUnknownElement(namespaceURI, localName);
1160            return this;
1161        }
1162
1163    }
1164
1165    /** Processes the content of an ATTRIBUTE element (i.e., MAP element).
1166     * A new TableMappingHandler is created.
1167     */

1168    class AttributeMappingHandler extends DefaultElementHandler {
1169        private static final String JavaDoc RCSRevision = "$Revision: 1.7 $";
1170        private static final String JavaDoc RCSName = "$Name: $";
1171        
1172        private AttributeDeclaration attDecl;
1173        private boolean updateWhenMissing = false;
1174        private String JavaDoc columnName = null;
1175
1176        AttributeMappingHandler(AttributeDeclaration decl, boolean updateWhenMissing) {
1177            attDecl = decl;
1178            this.updateWhenMissing = updateWhenMissing;
1179        }
1180
1181        public ElementHandler startElement(String JavaDoc namespaceURI, String JavaDoc localName, Attributes atts)
1182        throws SAXException {
1183            if (isMappingNamespace(namespaceURI))
1184            {
1185                if (localName.equals(MAP_TAG))
1186                {
1187                    addMapping2Scope(buildTableMapping(attDecl, atts));
1188                    return new TableMappingHandler();
1189                }
1190                else if (localName.equals(GENERATOR_TAG))
1191                {
1192                    if (columnName != null)
1193                        throw new SAXParseException(
1194                                "Cannot define a generator under an attribute already mapped on a column.",
1195                                getDocumentLocator()
1196                                );
1197                    buildGeneratorColumnMapping(atts, attDecl, true);
1198                    return this;
1199                }
1200            }
1201            notifyUnknownElement(namespaceURI, localName);
1202            return this;
1203        }
1204    }
1205    
1206    private TableMappingImpl getCurrentTableMapping() {
1207        for (int i = scope.size() - 1; i >= 0; i--) {
1208            TableMappingImpl tm = ((ScopeItem)scope.get(i)).getLastInserted();
1209            if (tm != null)
1210                return tm;
1211        }
1212        return null;
1213    }
1214    
1215    private TableMappingImpl findMappingInScope(String JavaDoc tableName) {
1216        for (int i = scope.size() - 1; i >= 0; i--) {
1217            List tms = ((ScopeItem)scope.get(i)).getTableMappings();
1218            for (int j = 0; j < tms.size(); j++) {
1219                TableMappingImpl tm = (TableMappingImpl)tms.get(j);
1220                if (tm.getTableName().equals(tableName)) return tm;
1221            }
1222        }
1223        return null;
1224    }
1225
1226    private void addMapping2Scope(TableMappingImpl tm) {
1227        peekScope().addTableMapping(tm);
1228    }
1229
1230    private ScopeItem pushScope() {
1231        ScopeItem ret = new ScopeItem();
1232        scope.add(ret);
1233        return ret;
1234    }
1235    
1236    private ScopeItem pushScope(TableMappingImpl tm) {
1237        ScopeItem ret = new ScopeItem(tm);
1238        scope.add(ret);
1239        return ret;
1240    }
1241    
1242    private ScopeItem peekScope() {
1243        return (ScopeItem) scope.get(scope.size() - 1);
1244    }
1245    
1246    private ScopeItem popScope() {
1247        return (ScopeItem) scope.remove(scope.size() - 1);
1248    }
1249    
1250    private class ScopeItem {
1251        /** A map between table mappings and a list of pending ref {tm, [ref1,ref2,..]} */
1252        private List tmList = new ArrayList(1);
1253        private List refList = null;
1254        
1255        ScopeItem() {
1256        }
1257        
1258        ScopeItem(TableMappingImpl tm) {
1259            this();
1260            addTableMapping(tm);
1261        }
1262        
1263        void addTableMapping(TableMappingImpl tm) {
1264            tmList.add(tm);
1265        }
1266        
1267        List getPendingRefs() {
1268            return refList;
1269        }
1270        
1271        List getTableMappings() {
1272            return tmList;
1273        }
1274        
1275        TableMappingImpl getLastInserted() {
1276            TableMappingImpl ret = null;
1277            if (!tmList.isEmpty())
1278                ret = (TableMappingImpl)tmList.get(tmList.size() - 1);
1279            return ret;
1280        }
1281        
1282        RefItem addPendingRef(String JavaDoc column, String JavaDoc pendingRef, SchemaComponent sc) {
1283            RefItem ret = null;
1284            if (refList == null)
1285                refList = new ArrayList(2);
1286            ret = new RefItem(column, pendingRef, getLastInserted(), sc);
1287            refList.add(ret);
1288            return ret;
1289        }
1290    }
1291    
1292    private class RefItem {
1293        String JavaDoc columnName = null;
1294        String JavaDoc ref = null;
1295        TableMappingImpl defautTableMapping = null;
1296        List childrenTableMappings = null;
1297        MappingNode contextNode = null;
1298        
1299        RefItem(String JavaDoc columnName, String JavaDoc ref, TableMappingImpl defautTableMapping, SchemaComponent sc) {
1300            this.columnName = columnName;
1301            this.ref = ref;
1302            this.defautTableMapping = defautTableMapping;
1303            contextNode = context.getCurrentNode();
1304            if (sc instanceof AttributeDeclaration) {
1305                AttributeDeclaration attDecl = (AttributeDeclaration) sc;
1306                contextNode = (MappingNode) contextNode.getChild(
1307                        new XNode(attDecl.getNamespace(), attDecl.getName(), NodeKind.ATTRIBUTE));
1308            }
1309        }
1310    }
1311}
1312
1313
1314
1315
1316
1317
1318
Popular Tags