KickJava   Java API By Example, From Geeks To Geeks.

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


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.sql.SQLException JavaDoc;
26 import java.sql.Types JavaDoc;
27 import java.util.*;
28
29 import org.xml.sax.SAXException JavaDoc;
30 import org.xquark.jdbc.typing.ColumnMetaData;
31 import org.xquark.mapping.Generator;
32 import org.xquark.mapper.RepositoryException;
33 import org.xquark.mapper.dbms.*;
34 import org.xquark.mapper.metadata.CollectionMetadata;
35 import org.xquark.mapper.util.RepositoryProperties;
36 import org.xquark.schema.*;
37 import org.xquark.schema.datatypes.PrimitiveType;
38
39 /**
40  * Implementation of the TableMapping interface for 'unmapped' elements or attributes.
41  *
42  * Elements or attributes are mapped to the default XML data table.
43  *
44  */

45 public class DefaultTableMapping extends BaseTableMappingImpl
46 {
47     private static final String JavaDoc RCSRevision = "$Revision: 1.7 $";
48     private static final String JavaDoc RCSName = "$Name: $";
49     private TableInfo tableInfo;
50     private ArrayList valueMappings = new ArrayList(3);
51     
52     /** Constructor.
53      * @param colMapping the RepositoryMapping object to which this object belongs.
54      * @param comp the SchemaComponent associated with this "mapping component".
55      * @param name relational table name.
56      * @param conn a connection allowing access to the metadata for the table retrieved from JDBC
57      * @param action the action to perform on the rows of the table (check, insert, update, ...)
58      * @param generate If true, mapping is loaded even if relational tables
59      * are not present : mapping is loaded for table generation.
60      */

61     public DefaultTableMapping(CollectionMetadata colMeta, AbstractConnection conn)
62     throws SAXException JavaDoc, SQLException JavaDoc, RepositoryException
63     {
64         super(colMeta.getMapping(), null, conn);
65         tableInfo = colMeta.getTableInfo(TableSpec.TYPE_DATA);
66         name = tableInfo.getName();
67         this.tableMetaData = tableInfo.getJDBCMetaData(conn);
68         
69         // create column mapping array
70
columnMappings = new ColumnMapping[tableMetaData.getColumnCount()];
71
72         initialize();
73         dependencies = Collections.EMPTY_LIST;
74         initialValues = Collections.EMPTY_LIST; // XQuark index parameters initialized when entering the element
75
}
76     
77     /**
78      * Accessors.
79      */

80     
81     public ColumnMapping[] getColumnMappings() {
82         return columnMappings;
83     }
84
85     public int getColumnMappingCount() {
86         return getColumnCount();
87     }
88
89     public int getBatchSize() {
90         return RepositoryProperties.getIntProperty(CONF_DATA_BATCHSIZE);
91     }
92
93     public int getOIDTableColumnCount() {
94         return 0;
95     }
96     public int getSelectColumnCount() {
97         return 0;
98     }
99     public int getFetchColumnCount() {
100         return 0;
101     }
102     public int getUpdateColumnCount() {
103         return 0;
104     }
105     public int getAction() {
106         return INSERT;
107     }
108     public boolean isClustered() {
109         return true;
110     }
111     public int getPathIDIndex() {
112         return V_PATHID_INDEX;
113     }
114     public int getUOIDIndex() {
115         return V_UOID_INDEX;
116     }
117
118     public boolean isShareable() {
119         return true;
120     }
121
122     public boolean isTableShared() {
123         return true;
124     }
125
126     public boolean isShared() {
127         return true;
128     }
129
130     /*
131      * This is a trick because we dont want to create a TableMapping for every
132      * couple(type, default table) to limit the number of tuple factories and
133      * statements.
134      */

135     public ColumnMapping createDefaultMappingView(SchemaComponent comp, boolean useStringDelimitor)
136     throws RepositoryException {
137         return new DefaultTableMappingView(comp, useStringDelimitor).getColumnView();
138     }
139     
140     ////////////////////////////////////////////////////////////////////////////
141
// MappingInfo IMPLEMENTATION
142
////////////////////////////////////////////////////////////////////////////
143
/* It is a trick because user table are not created automatically whereas OIDs are */
144     public String JavaDoc getSelectStatement() {
145         return null;
146     }
147
148     public String JavaDoc getUpdateStatement() {
149         return null;
150     }
151
152     public String JavaDoc getOIDInsertStatement() {
153         return null;
154     }
155
156     public String JavaDoc getOIDTableName() {
157         return null;
158     }
159     
160     //////////////////////////////////////////////////////////////////////////
161
// PRIVATE
162
//////////////////////////////////////////////////////////////////////////
163
private void initializeStatements()
164     {
165         insertStatement = tableInfo.getInsertStatement();
166         
167         StringBuffer JavaDoc columnList = new StringBuffer JavaDoc();
168         StringBuffer JavaDoc namedColumnList = new StringBuffer JavaDoc();
169         StringBuffer JavaDoc wildcards = new StringBuffer JavaDoc();
170         
171         ColumnInfo[] columns = tableInfo.getColumns();
172         String JavaDoc columnName = null;
173         for (int i = 0; i < columns.length; i++)
174         {
175             columnName = columns[i].getName();
176             
177             columnList.append(columnName);
178             columnList.append(',');
179             
180             namedColumnList.append("w.");
181             namedColumnList.append(columnName);
182             namedColumnList.append(',');
183             
184             wildcards.append("?,");
185         }
186         columnList.setLength(columnList.length() - 1);
187         namedColumnList.setLength(namedColumnList.length() - 1);
188         wildcards.setLength(wildcards.length() - 1);
189         
190         this.columnList = columnList.toString();
191         this.namedColumnList = namedColumnList.toString();
192         this.wildcards = wildcards.toString();
193     }
194     
195     private void initialize()
196     throws RepositoryException, SQLException JavaDoc
197     {
198         ColumnInfo[] columns = tableInfo.getColumns();
199         
200         StringBuffer JavaDoc columnList = new StringBuffer JavaDoc();
201         primaryKeyColumnMappings = new ColumnMapping[columns.length];
202         ColumnMapping column = null;
203         for (int i = 0; i < columns.length; i++)
204         {
205             columnList.append("w.");
206             columnList.append(columns[i].getName());
207             columnList.append(',');
208             switch (i)
209             {
210                 case V_UOID_INDEX :
211                     column = new DefaultColumnMapping(columns[i],
212                     SystemVariableGenerator.createGenerator(UOID_VALUE), i, true);
213                     break;
214                 case V_PATHID_INDEX :
215                     column = new DefaultColumnMapping(columns[i],
216                     SystemVariableGenerator.createGenerator(PATHID_VALUE), i, true);
217                     break;
218                 default :
219                     column = new DefaultColumnMapping(columns[i],
220                     new ValueGenerator(), i, false);
221                     valueMappings.add(i-2, column);
222                     break;
223             }
224             if (columns[i].isPrimaryKey())
225                 primaryKeyColumnMappings[keyColumnCount++] = column;
226             columnMappings[i] = column;
227         }
228         columnList.setLength(columnList.length() - 1);
229         namedColumnList = columnList.toString();
230         initializeStatements();
231     }
232     
233     public ColumnMapping getDefaultColumnMapping(SchemaComponent comp)
234     {
235         int mappingIndex = V_CHAR_VALUE_INDEX - 2;
236         if (comp != null)
237         {
238             Type type = null;
239             if (comp instanceof Type)
240                 type = (Type)comp;
241             else
242                 type = ((Declaration)comp).getType();
243             
244             SimpleType sType = type.getValueType();
245             if (sType != null)
246             {
247                 int pType = sType.getPrimitive().getType();
248                 
249                 if (pType == PrimitiveType.UNION)
250                 {
251                     // try to find a common target basic type
252
Iterator it = sType.getMemberTypes().iterator();
253                     PrimitiveType wType = null;
254                     
255                     int previousMappingIndex = -1;
256                     while (it.hasNext())
257                     {
258                         wType = ((SimpleType)it.next()).getPrimitive();
259                         mappingIndex = getMappingIndex(MappingTypeInfo.ABSTRACT_SCHEMA_JDBC_MAPPING[wType.getType()]);
260                         if ((previousMappingIndex != -1) && (mappingIndex != previousMappingIndex))
261                         {
262                             mappingIndex = V_CHAR_VALUE_INDEX - 2;
263                             break;
264                         }
265                         previousMappingIndex = mappingIndex;
266                     }
267                 }
268                 else
269                     mappingIndex = getMappingIndex(MappingTypeInfo.ABSTRACT_SCHEMA_JDBC_MAPPING[pType]);
270             }
271         }
272         return (ColumnMapping)valueMappings.get(mappingIndex);
273     }
274     
275     private int getMappingIndex(int basicJDBCType)
276     {
277         int mappingIndex = V_CHAR_VALUE_INDEX - 2;
278         switch (basicJDBCType)
279         {
280             case Types.VARCHAR: case Types.VARBINARY:
281                 mappingIndex = V_CHAR_VALUE_INDEX - 2;
282                 break;
283             case Types.DECIMAL: case Types.FLOAT: case Types.DOUBLE:
284                 mappingIndex = V_NUM_VALUE_INDEX - 2;
285                 break;
286             case Types.TIMESTAMP:
287                 mappingIndex = V_DATE_VALUE_INDEX - 2;
288                 break;
289         }
290         return mappingIndex;
291     }
292    
293     //////////////////////////////////////////////////////////////////////////
294
// INNER CLASSES
295
//////////////////////////////////////////////////////////////////////////
296
private class DefaultColumnMapping implements ColumnMapping
297     {
298         
299         private Generator generator;
300         private MappingTypeInfo typeInfo;
301         private int index;
302         private ColumnInfo columnInfo;
303         
304         DefaultColumnMapping(ColumnInfo column, Generator generator, int index, boolean finalGen)
305         throws RepositoryException
306         {
307             columnInfo = column;
308             this.generator = generator;
309             // for OIDs create a typeInfo (for values a different will be created for each path)
310
String JavaDoc type = null;
311             if (generator instanceof SystemVariableGenerator)
312                 type = ((SystemVariableGenerator)generator).getXMLType();
313             else // set a type info for null setting
314
{
315                 switch (getMetaData().getDataType())
316                 {
317                     case Types.VARCHAR: case Types.VARBINARY:
318                         type = "string";
319                         break;
320                     case Types.DECIMAL: case Types.FLOAT: case Types.DOUBLE:
321                         type = "decimal";
322                         break;
323                     case Types.TIMESTAMP:
324                         type = "dateTime";
325                         break;
326                 }
327             }
328             try
329             {
330                 typeInfo = new MappingTypeInfo(type, false);
331                 typeInfo.checkTargetType(getMetaData()); // no handler (system)
332
}
333             catch (SAXException JavaDoc e)
334             {
335                 throw new RepositoryException(RepositoryException.INTERNAL_ERROR,
336                 "Error while setting type conversion flags on DATA table.", e);
337             }
338             if (finalGen)
339                 addToFinalValues(this);
340             this.index = index;
341         }
342         
343         public SchemaComponent getSchemaComponent() {
344             return getSchemaType();
345         }
346
347         public Type getSchemaType() {
348             Type ret = null;
349             if (typeInfo != null)
350                 ret = typeInfo.getXMLType();
351             return ret;
352         }
353
354         public String JavaDoc getColumnName() {
355             return columnInfo.getName();
356         }
357
358         public ColumnMetaData getMetaData() {
359             return DefaultTableMapping.this.getMetaData().getColumnMetaData(
360                     getColumnName());
361         }
362
363         public int getColumnIndex() {
364             return index;
365         }
366
367         public int getInsertColumnIndex() {
368             return getColumnIndex();
369         }
370
371         public int getKeyColumnIndex() {
372             if (columnInfo.isPrimaryKey())
373                 return index;
374             else
375                 return -1;
376         }
377
378         public int getSelectColumnIndex() {
379             return -1;
380         }
381
382         public int getFetchColumnIndex() {
383             return -1;
384         }
385
386         public int getUpdateColumnIndex() {
387             return -1;
388         }
389
390         public Generator getGenerator() {
391             return generator;
392         }
393
394         public Generator getDefaultGenerator() {
395             return null;
396         }
397
398         public Generator getInitGenerator() {
399             return getGenerator();
400         }
401
402         public int getTableRefIndex() {
403             return -1;
404         }
405
406         public int getColumnType() {
407             return columnInfo.getDataType();
408         }
409
410         public TableMapping getTableMapping() {
411             return DefaultTableMapping.this;
412         }
413
414         public String JavaDoc getTableName() {
415             return name;
416         }
417
418         public int getTableIndex() {
419             return DefaultTableMapping.this.getTableIndex();
420         }
421
422         public String JavaDoc toString() {
423             return getTableName() + "." + getColumnName();
424         }
425
426         public MappingTypeInfo getTypeInfo() {
427             return typeInfo;
428         }
429
430         public int getJoinColumnIndex() {
431             return -1;
432         }
433
434         public boolean isInJoin() {
435             return false;
436         }
437
438         public boolean updateColumnWhenMissing() {
439             return false;
440         }
441     }
442     
443     private class DefaultTableMappingView extends MappingImpl implements TableMapping
444     {
445         private ColumnMapping[] columns;
446         private DefaultColumnMappingView columnView;
447         
448         DefaultTableMappingView(SchemaComponent comp, boolean useStringDelimitor)
449         throws RepositoryException
450         {
451             super(comp);
452 // columns = new ColumnMapping[DefaultTableMapping.this.columnMappings.length];
453
columns = (ColumnMapping[])DefaultTableMapping.this.columnMappings.clone();
454             columnView = new DefaultColumnMappingView(this, comp, useStringDelimitor);
455             columns[columnView.getColumnIndex()] = columnView;
456         }
457         
458         /**
459          * Overriden because default mapping uses views on real table mapping.
460          * As query reconstruction use equality, we use what realy identifies
461          * the table mapping: its index.
462          */

463         public boolean equals(Object JavaDoc o)
464         {
465             boolean ret = false;
466             if (o instanceof TableMapping)
467                 ret = o.equals(DefaultTableMapping.this);
468             return ret;
469         }
470         /** Overriden because default mapping uses views on real table mapping.
471          * (As query reconstruction use a map).
472          */

473         public int hashCode()
474         {
475             return DefaultTableMapping.this.hashCode();
476         }
477    
478         public int getColumnCount()
479         {
480             return DefaultTableMapping.this.getColumnCount();
481         }
482         
483         public int getColumnMappingCount()
484         {
485             return getColumnCount();
486         }
487
488         public ColumnMapping[] getColumnMappings()
489         {
490             return DefaultTableMapping.this.columnMappings;
491         }
492
493         public DefaultColumnMappingView getColumnView()
494         {
495             return columnView;
496         }
497         
498         public ColumnMapping getColumnMapping(int index)
499         {
500             return columns[index];
501         }
502         
503         public List finalParameters()
504         {
505             return DefaultTableMapping.this.finalParameters();
506         }
507         
508         public int getAction()
509         {
510             return DefaultTableMapping.this.getAction();
511         }
512         
513         public int getBatchSize()
514         {
515             return DefaultTableMapping.this.getBatchSize();
516         }
517         
518         public String JavaDoc getColumnList()
519         {
520             return DefaultTableMapping.this.getColumnList();
521         }
522         
523         public ColumnMapping getColumnMapping(String JavaDoc name)
524         {
525             return DefaultTableMapping.this.getColumnMapping(name);
526         }
527         
528         public String JavaDoc getInsertStatement()
529         {
530             return DefaultTableMapping.this.getInsertStatement();
531         }
532         
533         public String JavaDoc getJoinCondition()
534         {
535             return DefaultTableMapping.this.getJoinCondition();
536         }
537         
538         public int getKeyColumnCount()
539         {
540             return DefaultTableMapping.this.getKeyColumnCount();
541         }
542         
543         public String JavaDoc getJoinColumnList()
544         {
545             return DefaultTableMapping.this.getJoinColumnList();
546         }
547         
548         public String JavaDoc getJoinColumnTypes()
549         {
550             return DefaultTableMapping.this.getJoinColumnTypes();
551         }
552         
553         public String JavaDoc getJoinWildcards()
554         {
555             return DefaultTableMapping.this.getJoinWildcards();
556         }
557         
558         public TableMetaData getMetaData()
559         {
560             return DefaultTableMapping.this.getMetaData();
561         }
562         
563         public String JavaDoc getNamedColumnList()
564         {
565             return DefaultTableMapping.this.getNamedColumnList();
566         }
567         
568         public ColumnMapping[] getJoinColumns()
569         {
570             return DefaultTableMapping.this.getJoinColumns();
571         }
572         
573         public String JavaDoc getOIDInsertStatement()
574         {
575             return DefaultTableMapping.this.getOIDInsertStatement();
576         }
577         
578         public int getOIDTableColumnCount()
579         {
580             return DefaultTableMapping.this.getOIDTableColumnCount();
581         }
582         
583         public String JavaDoc getPathIDColumnName()
584         {
585             return DefaultTableMapping.this.getPathIDColumnName();
586         }
587         
588         public int getPathIDIndex()
589         {
590             return DefaultTableMapping.this.getPathIDIndex();
591         }
592         
593         public ColumnMapping[] getPrimaryKey()
594         {
595             return DefaultTableMapping.this.getPrimaryKey();
596         }
597         
598         public int getSelectColumnCount()
599         {
600             return DefaultTableMapping.this.getSelectColumnCount();
601         }
602         
603         public int getFetchColumnCount()
604         {
605             return DefaultTableMapping.this.getFetchColumnCount();
606         }
607         
608         public ColumnMapping[] getSelectColumns()
609         {
610             return DefaultTableMapping.this.getSelectColumns();
611         }
612         
613         public ColumnMapping[] getFetchColumns()
614         {
615             return DefaultTableMapping.this.getFetchColumns();
616         }
617         
618         public String JavaDoc getSelectStatement()
619         {
620             return DefaultTableMapping.this.getSelectStatement();
621         }
622         
623         public int getTableIndex()
624         {
625             return DefaultTableMapping.this.getTableIndex();
626         }
627         
628         public String JavaDoc getTableName()
629         {
630             return DefaultTableMapping.this.getTableName();
631         }
632         
633         public String JavaDoc getUOIDColumnName()
634         {
635             return DefaultTableMapping.this.getUOIDColumnName();
636         }
637         
638         public int getUOIDIndex()
639         {
640             return DefaultTableMapping.this.getUOIDIndex();
641         }
642         
643         public int getUpdateColumnCount()
644         {
645             return DefaultTableMapping.this.getUpdateColumnCount();
646         }
647         
648         public ColumnMapping[] getUpdateColumns()
649         {
650             return DefaultTableMapping.this.getUpdateColumns();
651         }
652         
653         public String JavaDoc getUpdateStatement()
654         {
655             return DefaultTableMapping.this.getUpdateStatement();
656         }
657         
658         public String JavaDoc getWildcards()
659         {
660             return DefaultTableMapping.this.getWildcards();
661         }
662         
663         public List initParameters()
664         {
665             return DefaultTableMapping.this.initParameters();
666         }
667         
668         public boolean isClustered()
669         {
670             return DefaultTableMapping.this.isClustered();
671         }
672         
673         public void setIndex(int index)
674         {
675             // no op
676
}
677         
678         public String JavaDoc getOIDTableName()
679         {
680             return DefaultTableMapping.this.getOIDTableName();
681         }
682         
683         public TableMapping getTableMapping()
684         {
685             return this;
686         }
687         
688         public boolean isShareable()
689         {
690             return DefaultTableMapping.this.isShareable();
691         }
692         
693         public boolean isTableShared()
694         {
695             return DefaultTableMapping.this.isTableShared();
696         }
697
698         public boolean isShared()
699         {
700             return DefaultTableMapping.this.isShared();
701         }
702     }
703     
704     private class DefaultColumnMappingView extends MappingImpl implements ColumnMapping
705     {
706         
707         private ValueGenerator generator;
708         private MappingTypeInfo typeInfo;
709         private ColumnMapping columnMapping;
710         private DefaultTableMappingView tableMapping;
711         
712         DefaultColumnMappingView(
713                                 DefaultTableMappingView tableMapping,
714                                 SchemaComponent comp,
715                                 boolean useStringDelimitor
716                                 )
717         throws RepositoryException
718         {
719             super(comp);
720             this.columnMapping = getDefaultColumnMapping(comp);
721             this.tableMapping = tableMapping;
722             // clone the value generator to keep its copy of MappingTypeInfo
723
generator = (ValueGenerator)((ValueGenerator)columnMapping.getGenerator()).clone();
724             try
725             {
726                 Type schemaType = getSchemaType();
727                 if (schemaType == null)
728                     typeInfo = columnMapping.getTypeInfo(); // use the lax one corresponding to the target type
729
else
730                 {
731                     typeInfo = new MappingTypeInfo(schemaType.getValueType(), useStringDelimitor);
732                     typeInfo.checkTargetType(getMetaData(), null);
733                 }
734             }
735             catch (SAXException JavaDoc e)
736             {
737                 throw new RepositoryException(RepositoryException.NOT_ALLOWED,
738                 "XML type for " + comp + " does not fit the default mapping table.", e);
739             }
740             generator.setTypeInfo(typeInfo);
741         }
742         
743         public String JavaDoc getColumnName() {
744             return columnMapping.getColumnName();
745         }
746
747         public ColumnMetaData getMetaData() {
748             return columnMapping.getMetaData();
749         }
750
751         public int getColumnIndex() {
752             return columnMapping.getColumnIndex();
753         }
754
755         public int getInsertColumnIndex() {
756             return getColumnIndex();
757         }
758
759         public int getKeyColumnIndex() {
760             return columnMapping.getKeyColumnIndex();
761         }
762
763         public int getSelectColumnIndex() {
764             return columnMapping.getSelectColumnIndex();
765         }
766
767         public int getFetchColumnIndex() {
768             return columnMapping.getFetchColumnIndex();
769         }
770
771         public int getUpdateColumnIndex() {
772             return columnMapping.getUpdateColumnIndex();
773         }
774
775         public Generator getGenerator() {
776             return generator;
777         }
778
779         public Generator getDefaultGenerator() {
780             return null;
781         }
782
783         public Generator getInitGenerator() {
784             return getGenerator();
785         }
786
787         public int getTableRefIndex() {
788             return -1;
789         }
790
791         public int getColumnType() {
792             return columnMapping.getColumnType();
793         }
794
795         public TableMapping getTableMapping() {
796             return tableMapping;
797         }
798
799         public String JavaDoc getTableName() {
800             return name;
801         }
802
803         public int getTableIndex() {
804             return DefaultTableMapping.this.getTableIndex();
805         }
806
807         public String JavaDoc toString() {
808             return getTableName() + "." + getColumnName();
809         }
810
811         public MappingTypeInfo getTypeInfo() {
812             return typeInfo;
813         }
814
815         public int getJoinColumnIndex() {
816             return -1;
817         }
818
819         public boolean isInJoin() {
820             return false;
821         }
822
823         public boolean updateColumnWhenMissing() {
824             return false;
825         }
826     }
827 }
828
Popular Tags