KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.*;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.xml.sax.ContentHandler JavaDoc;
30 import org.xml.sax.SAXException JavaDoc;
31 import org.xml.sax.helpers.AttributesImpl JavaDoc;
32 import org.xquark.mapper.metadata.StoragePathMetadata;
33 import org.xquark.schema.*;
34 import org.xquark.xpath.*;
35
36 /**
37  * XTreeNode implementation for XQuark mapping file memory representation.
38  *
39  */

40 public class MappingNode extends TypedXTreeNode
41 implements StoragePathMetadata
42 {
43     private static final String JavaDoc RCSRevision = "$Revision: 1.2 $";
44     private static final String JavaDoc RCSName = "$Name: $";
45         
46     private static Log log = LogFactory.getLog(MappingNode.class);
47
48     /** The schema component related to the node, if any */
49     protected SchemaComponent comp;
50     /** Table mappings defined for the SchemaComponent, if any */
51     protected List tableMappings;
52     /** Column mappings defined for the SchemaComponent, if any */
53     protected List columnMappings;
54     /** Column mapping used for reconstruction */
55     protected ColumnMapping refColumnMapping;
56     
57     /** Table mappings that are defined in the scope of the element,
58      * The default mapping is excluded because they will be added
59      * when adding the MappingNode to the PathNode.
60      */

61         // MappingNode mappingInScope+hasDefaultInScope but null if not buildable
62
// add a List data
63
// determine buildable flag : some column mappings in scope have a table mapping defined in an ancestor
64
// to implement a flag set when registering column mappings in Repository mapping
65
// TO DO : change ArrayList of mappingInScope in a HashSet
66
protected HashSet scopeTableMappings;
67     
68     /** flag that says if the node can be built with the mapping in scope
69      */

70     private boolean isBuildable = true;
71     
72     /** the first ancestor that has all table mappings in scope for this path
73      * construction
74      */

75     private int builderDepthDiff = 0; // builder was originally a reference but it was hard
76
// to manage when cloning for type mappings. Now
77
// the relative depth is stored.
78

79     
80     public MappingNode(XTree tree, XTreeNode parent, String JavaDoc namespace, String JavaDoc localName, byte type)
81     {
82         super(tree, parent, namespace, localName, type);
83     }
84     
85     // ACCESSORS
86
/** Set the schema component and the defaultAllowed internal flag */
87     public void setComponent(SchemaComponent comp)
88     {
89          this.comp = comp;
90     }
91     
92     /** Used by RepositoryMapping.register()
93      */

94     void setBuildable(boolean flag)
95     {
96         isBuildable = flag;
97     }
98     
99     public boolean isBuildable()
100     {
101         return isBuildable;
102     }
103     
104     /** Used by RepositoryMapping.register()
105      */

106     void setBuilderDiff(int diff)
107     {
108         builderDepthDiff = diff;
109     }
110     
111     public MappingNode getBuilder()
112     {
113         MappingNode node = this;
114         for (int i = 0; i < builderDepthDiff; i++)
115         {
116             node = (MappingNode)node.getParent();
117         }
118         return node;
119     }
120     
121     /** True if the schema authorize a node to use default mapping when
122      * no mapping is defined by the user (simple type or attribute).
123      * The default mapping is added in a second pass following the mapping
124      * file loading if this flag is true.
125      */

126     public boolean isDefaultAllowed()
127     {
128         boolean defaultAllowed = true;
129         if ((comp != null) && (getType() == NodeKind.ELEMENT)) // attribute is always leaf
130
{
131             Type type;
132             if (comp instanceof Type)
133                 type = (Type)comp;
134             else // Declaration (attribute or element)
135
type = ((Declaration)comp).getType();
136             if (type instanceof ComplexType)
137             {
138                 if (((ComplexType)type).getContentType() != SchemaConstants.TEXT_ONLY)
139                     defaultAllowed = false;
140             }
141             // else // (SimpleType) : default value
142
}
143         return defaultAllowed;
144     }
145         
146     public boolean potentialNewPathsExist()
147     {
148         boolean potentialNewPathsExist = false;
149         if (comp != null)
150         {
151             if ((getType() == NodeKind.ELEMENT)
152                 && (((ElementDeclaration)getDeclaration()).getType() instanceof ComplexType))
153             {
154                 ComplexType type = (ComplexType)((ElementDeclaration)getDeclaration()).getType();
155                 potentialNewPathsExist = ((type.getAttributeDeclarations().size() + type.getElementDeclarations().size())
156                 > (getChildren() == null ? 0:getChildren().size()));
157             }
158         }
159         else if (getType() == NodeKind.ELEMENT)
160             potentialNewPathsExist = true;
161         
162         // recursive call
163
if (!potentialNewPathsExist && (getChildren() != null))
164         {
165             Iterator it = getChildren().iterator();
166             while (!potentialNewPathsExist && it.hasNext())
167                 potentialNewPathsExist |= ((MappingNode)it.next()).potentialNewPathsExist();
168         }
169         
170         return potentialNewPathsExist;
171     }
172     
173     public SchemaComponent getSchemaComponent()
174     {
175         return comp;
176     }
177     
178     public Declaration getDeclaration()
179     {
180         return comp instanceof Declaration ? (Declaration)comp : null;
181     }
182     
183     /** get table mappings for the schema component.
184      * if component has tableMapping for its type, these mapping are concatenated
185      */

186     public List getTableMappings()
187     {
188         return tableMappings;
189     }
190     
191     /** get column mappings for the schema component */
192     public List getColumnMappings()
193     {
194         return columnMappings;
195     }
196     
197     /** get column mapping used for reconstruction and queries */
198     public ColumnMapping getReferenceColumnMapping()
199     {
200         return refColumnMapping;
201     }
202     
203     /** get table mapping used for reconstruction and queries */
204     public TableMapping getReferenceTableMapping()
205     {
206         if (tableMappings != null)
207             return (TableMapping)tableMappings.get(0);
208         else
209             return null;
210     }
211     
212     /** Get the table mappings in the scope element
213      * @return null if notable mapping
214      */

215     public Collection getScopeMappings()
216     {
217         return scopeTableMappings;
218     }
219     
220     /** Add a new table mapping in the element scope */
221     boolean addMappingInScope(TableMapping table)
222     {
223         if (scopeTableMappings == null)
224             scopeTableMappings = new HashSet();
225         return scopeTableMappings.add(table);
226     }
227     
228     /** Add a new set of table mapping in the element scope */
229     boolean addMappingsInScope(Collection mappings)
230     {
231         if (scopeTableMappings == null)
232             scopeTableMappings = new HashSet();
233         return scopeTableMappings.addAll(mappings);
234     }
235     
236     // PUBLIC METHODS
237

238     /** Add a table mapping to this entry and to the RepositoryMapping list */
239     void register(Mapping mapping)
240     {
241         RepositoryMapping colMetaData = (RepositoryMapping)tree;
242         if (mapping instanceof TableMapping)
243         {
244             if (tableMappings == null)
245                 tableMappings = new ArrayList(1); // bet most of elements will have only one table mapping
246
tableMappings.add(mapping);
247             ((TableMapping)mapping).setIndex(colMetaData.getTableCount());
248             colMetaData.addTableMapping((TableMapping)mapping);
249         }
250         else if (mapping instanceof ColumnMapping)
251         {
252             if (columnMappings == null)
253                 columnMappings = new ArrayList();
254             columnMappings.add(mapping);
255             if (log.isDebugEnabled())
256                 log.debug("Registering [mapping] on [schema comp]=" + mapping + comp);
257             if ((refColumnMapping == null)
258                 && (((ColumnMapping)mapping).getGenerator() != null)) // to discard the table-column mapping case
259
refColumnMapping = (ColumnMapping)mapping;
260                 
261         }
262     }
263     
264     /*
265      * Moves a column mapping at the end of the list because ref generators assume
266      * that other generators were called before to perform the potential select
267      * in the db.
268      */

269     void moveColumnMappingToTheEnd(ColumnMapping mapping) {
270         if (columnMappings != null && columnMappings.contains(mapping)) {
271             columnMappings.remove(mapping);
272             columnMappings.add(mapping);
273         }
274     }
275     
276     public Object JavaDoc clone()
277     {
278         MappingNode node = null;
279         node = (MappingNode)super.clone();
280         if (tableMappings != null)
281             node.tableMappings = new ArrayList(tableMappings);
282         if (columnMappings != null)
283             node.columnMappings = new ArrayList(columnMappings);
284         return node;
285     }
286     
287
288     public String JavaDoc toString()
289     {
290         String JavaDoc ret = super.toString() + "(" + comp + ")";
291         if (scopeTableMappings != null)
292             ret += " Scope" +scopeTableMappings;
293         if (tableMappings != null)
294             ret += " Tables" +tableMappings;
295         if (columnMappings != null)
296             ret += " Columns" + columnMappings ;
297         ret += " b=" + isBuildable + " br=" + builderDepthDiff;
298         return ret;
299     }
300     
301     public void toXML(ContentHandler JavaDoc handler)
302     throws SAXException JavaDoc
303     {
304         AttributesImpl JavaDoc atts = new AttributesImpl JavaDoc();
305         String JavaDoc value;
306         
307         // schema component
308
if (comp != null)
309         {
310             handler.startElement("", "schemaComponent", "", atts);
311             value = comp.toString();
312             handler.characters(value.toCharArray(), 0, value.length());
313             handler.endElement("", "schemaComponent", "");
314         }
315         
316         // Builder depth diff
317
handler.startElement("", "builderDepthDiff", "", atts);
318         value = String.valueOf(builderDepthDiff);
319         handler.characters(value.toCharArray(), 0, value.length());
320         handler.endElement("", "builderDepthDiff", "");
321         
322         // Optimization flags
323
atts.addAttribute("", "buildable", "", "CDATA", String.valueOf(isBuildable));
324         handler.startElement("", "flags", "", atts);
325         atts.clear();
326         handler.endElement("", "flags", "");
327         
328         // Reference column mappping
329
handler.startElement("", "refColumn", "", atts);
330         if (refColumnMapping != null)
331         {
332             value = refColumnMapping.getTableName() + "." + refColumnMapping.getColumnName();
333             handler.characters(value.toCharArray(), 0, value.length());
334         }
335         handler.endElement("", "refColumn", "");
336         
337         
338         // Table mapppings
339
handler.startElement("", "tableMappings", "", atts);
340         if (tableMappings != null)
341         {
342             Iterator it = tableMappings.iterator();
343             while (it.hasNext())
344             {
345                 atts.addAttribute("", "name", "", "CDATA", ((TableMapping)it.next()).getTableName());
346                 handler.startElement("", "table", "", atts);
347                 atts.clear();
348                 handler.endElement("", "table", "");
349             }
350         }
351         handler.endElement("", "tableMappings", "");
352         
353         // Column mapppings
354
handler.startElement("", "columnMappings", "", atts);
355         if (columnMappings != null)
356         {
357             Iterator it = columnMappings.iterator();
358             ColumnMapping column;
359             while (it.hasNext())
360             {
361                 column = (ColumnMapping)it.next();
362                 atts.addAttribute("", "name", "", "CDATA", column.getTableName() + "." + column.getColumnName());
363                 handler.startElement("", "column", "", atts);
364                 atts.clear();
365                 handler.endElement("", "column", "");
366             }
367         }
368         handler.endElement("", "columnMappings", "");
369     
370         // Table mapppings in scope
371
handler.startElement("", "tableMappingsInScope", "", atts);
372         if (scopeTableMappings != null)
373         {
374             Iterator it = scopeTableMappings.iterator();
375             while (it.hasNext())
376             {
377                 atts.addAttribute("", "name", "", "CDATA", ((TableMapping)it.next()).getTableName());
378                 handler.startElement("", "table", "", atts);
379                 atts.clear();
380                 handler.endElement("", "table", "");
381             }
382         }
383         handler.endElement("", "tableMappingsInScope", "");
384     }
385     
386     ////////////////////////////////////////////////////////////////////
387
// FAKE IMPLEMENTATION of StoragePathMetadata interface.
388
////////////////////////////////////////////////////////////////////
389
public short getPathID() { return -1;}
390     public byte getStorageMode() { return -1;}
391     public boolean isPositionEnforced() { return false;}
392     public boolean isPersistent() { return true;}
393     public boolean isNilImplicit() { return false;}
394 }
395
Popular Tags