KickJava   Java API By Example, From Geeks To Geeks.

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


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 org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.xml.sax.SAXException JavaDoc;
28 import org.xquark.jdbc.typing.ColumnMetaData;
29 import org.xquark.mapping.Generator;
30 import org.xquark.mapping.UserGenerator;
31 import org.xquark.schema.*;
32 import org.xquark.xml.xdbc.XMLDBCException;
33 import org.xquark.xml.xdbc.XMLErrorHandler;
34
35 /**
36  * Implementation of the ColumnMapping interface.
37  *
38  */

39 class ColumnMappingImpl extends MappingImpl
40 implements ColumnMapping, MappingConstants
41 {
42     private static final String JavaDoc RCSRevision = "$Revision: 1.7 $";
43     private static final String JavaDoc RCSName = "$Name: $";
44
45     private static Log log = LogFactory.getLog(ColumnMappingImpl.class);
46
47     private TableMappingImpl tableMapping;
48     private String JavaDoc name;
49     private int index;
50     private int keyColumnIndex = -1;
51     private int keyGenColumnIndex = -1;
52     private int joinColumnIndex = -1;
53     private int primaryKeyColumnIndex = -1;
54     private int insertColumnIndex = -1;
55     private int selectColumnIndex = -1;
56     private int fetchColumnIndex = -1;
57     private int updateColumnIndex = -1;
58     private Generator generator;
59     private MappingTypeInfo typeInfo;
60     /** generator to call when initializing the tuple.
61      * Contains a constant generator for columns which have a default value in
62      * the database
63      */

64     private Generator defaultGenerator = null;
65     private int tableRefIndex = -1;
66     private int minOccurs;
67     private boolean updateColumnWhenMissing = false;
68     private XMLErrorHandler messageHandler = null; // TODO: is it useful yet ?
69

70     ColumnMappingImpl(TableMappingImpl tableMapping, SchemaComponent comp,
71         int minOccurs, String JavaDoc name, int role, Generator generator,
72         XMLErrorHandler messageHandler)
73     throws SAXException JavaDoc
74     {
75         super(comp);
76         this.name = name;
77         this.tableMapping = tableMapping;
78         this.messageHandler = messageHandler;
79         index = tableMapping.register(this);
80         this.minOccurs = minOccurs;
81         insertColumnIndex = tableMapping.incrementColumnMappingCount();
82         ColumnMetaData cmeta = getMetaData();
83         if (cmeta != null) {
84             if (cmeta.isPrimaryKey()) {
85                 keyColumnIndex = tableMapping.incrementKeyColumnCount();
86             }
87         }
88         if ((role & KEY_ROLE) != 0) // PB IS HERE for COUNTRY
89
{
90             if ((cmeta != null) && cmeta.isLongType())
91                 throw new SAXException JavaDoc("A column with a long datatype cannot be \"inKey\".");
92             keyGenColumnIndex = tableMapping.incrementKeyGenColumnCount();
93         }
94         if ((role & SELECT_ROLE) != 0)
95         {
96             if ((cmeta != null) && cmeta.isLongType() && (tableMapping.getAction() != INSERT))
97                 throw new SAXException JavaDoc("A column with a long datatype cannot be \"inSelect\".");
98             selectColumnIndex = tableMapping.incrementSelectColumnCount();
99         }
100         else {
101             fetchColumnIndex = tableMapping.incrementFetchColumnCount();
102             if ((role & KEY_ROLE) == 0) // update all column no inSelect and not inKey
103
updateColumnIndex = tableMapping.incrementUpdateColumnCount();
104         }
105         if (generator != null)
106             setGenerator(generator);
107     }
108
109     ColumnMappingImpl(TableMappingImpl tableMapping, SchemaComponent comp,
110             int minOccurs, String JavaDoc name, int role, Generator generator,
111             boolean updateColumnWhenMissing, XMLErrorHandler messageHandler)
112             throws SAXException JavaDoc {
113         this(tableMapping, comp, minOccurs, name, role, generator, messageHandler);
114         this.updateColumnWhenMissing = updateColumnWhenMissing;
115     }
116     
117     public String JavaDoc toString() {
118         return getTableName()+"."+name;
119     }
120
121     public String JavaDoc getTableName() { return tableMapping.getTableName();}
122
123     public int getTableIndex() { return tableMapping.getTableIndex();}
124
125     public String JavaDoc getColumnName() { return name;}
126     
127     public boolean isInJoin() { return joinColumnIndex > -1;}
128     
129     public int getJoinColumnIndex() { return joinColumnIndex;}
130
131     public ColumnMetaData getMetaData()
132     {
133         TableMetaData tmeta = tableMapping.getMetaData();
134         if (tmeta == null) return null;
135         return tmeta.getColumnMetaData(name);
136     }
137
138     public int getColumnIndex() { return index; }
139
140     public int getInsertColumnIndex()
141     { return insertColumnIndex; }
142
143     public int getKeyColumnIndex()
144     {
145         return keyColumnIndex;
146     }
147
148     public int getSelectColumnIndex() { return selectColumnIndex;}
149
150     public int getFetchColumnIndex() { return fetchColumnIndex;}
151
152     public int getUpdateColumnIndex() { return updateColumnIndex;}
153
154     public Generator getGenerator() { return generator;}
155
156     public MappingTypeInfo getTypeInfo() { return typeInfo;}
157     
158     public int getKeyGenColumnIndex() {return keyGenColumnIndex;}
159         
160     public Generator getDefaultGenerator() { return defaultGenerator;}
161     
162     public Generator getInitGenerator() {
163         return defaultGenerator == null ? generator : defaultGenerator;
164     }
165
166     public int getTableRefIndex() { return tableRefIndex; }
167
168     public int getColumnType() { return getMetaData().getDataType();}
169
170     int getMinOccurs() { return minOccurs;}
171     
172     void setKeyColumnIndex(int index) { keyColumnIndex = index;}
173     
174     public void setJoinColumnIndex(int index) {joinColumnIndex = index;}
175
176     void setGenerator(Generator generator) throws SAXException JavaDoc
177     {
178         this.generator = generator;
179         
180         if (comp == null) // no component : real generator (added to initial or generators)
181
setTableMappingGenerator(generator);
182         else // if default value in the database add the generator to init generators
183
checkOccurrenceConstraints(minOccurs); // (will be overwriten if the element or attribute is encountered)
184

185         if (generator instanceof UserGenerator)
186             typeInfo = new MappingTypeInfo(((UserGenerator)generator).getXMLType());
187         else if (generator instanceof ValueGenerator)
188         {
189             Type type;
190             if (comp instanceof Declaration)
191                 type = ((Declaration)comp).getType();
192             else
193                 type = (Type)comp;
194             typeInfo = new MappingTypeInfo(type.getValueType());
195             ((ValueGenerator)generator).setTypeInfo(typeInfo);
196         }
197         else // ref generator
198
{
199             ColumnMapping refColumn = null;
200             if (generator instanceof ColumnRefGenerator)
201                 refColumn = ((ColumnRefGenerator)generator).getColumnRef();
202             if (refColumn != null)
203                 typeInfo = refColumn.getTypeInfo();
204             if (typeInfo == null)
205                 throw new SAXException JavaDoc("Cannot reference a ref generator in column "
206                         + getMetaData()
207                         +". Please directly reference the column referenced by the ref generator");
208         }
209         
210         checkTypeConstraints();
211     }
212
213     private void setDefaultGenerator(Generator generator) {
214         defaultGenerator = generator;
215         tableMapping.addToInitialValues(this);
216     }
217
218     void setTableMappingGenerator(Generator generator)
219     {
220         if (generator instanceof ValueGenerator || generator instanceof ColumnRefGenerator)
221             tableMapping.addToFinalValues(this); // cos' value node is ready at the end of node
222
else
223             tableMapping.addToInitialValues(this);
224     }
225     
226     private void checkOccurrenceConstraints(int minOccurs)
227     throws SAXException JavaDoc
228     {
229         ColumnMetaData cmeta = getMetaData();
230         if (cmeta != null) {
231             SchemaComponent comp = getSchemaComponent();
232             if (minOccurs == 0) {
233                 String JavaDoc defVal = cmeta.getDefaultValue();
234                 if (defVal != null)
235                 setDefaultGenerator(new ConstantGenerator(defVal));
236                 else if (cmeta.isNullable())
237                 setDefaultGenerator(new ConstantGenerator(null));
238                 else
239                 throw new SAXException JavaDoc("Optional element or attribute "+comp
240                 +" cannot be mapped onto " +cmeta
241                 +". The column should be nullable or have a default value");
242             }
243             if (comp instanceof ElementDeclaration
244             && ((ElementDeclaration)comp).isNillable()
245             && !cmeta.isNullable())
246             throw new SAXException JavaDoc("Nullable element "+comp
247             +"cannot be mapped onto the non-nullable "
248             +cmeta);
249         }
250     }
251
252     private void checkTypeConstraints()
253     throws SAXException JavaDoc
254     {
255         ColumnMetaData cmeta = getMetaData();
256         if (cmeta != null) {
257             if (cmeta.getRefTable() == null) {
258                 if (generator instanceof ColumnRefGenerator)
259                     // Store dependency
260
this.tableRefIndex = (((ColumnRefGenerator)generator).getColumnRef()).getTableIndex();
261             }
262             else {
263                 if (generator instanceof ColumnRefGenerator)
264                 {
265                     ColumnMapping refCol = ((ColumnRefGenerator)generator).getColumnRef();
266                     if (!refCol.getTableName().equals(cmeta.getRefTable())
267                     || !refCol.getColumnName().equals(cmeta.getRefColumn()))
268                         throw new SAXException JavaDoc("The reference mapping from "
269                                 + cmeta + " to "
270                                 + refCol.getMetaData() +
271                                 " is not consistent with existing foreign key constraints");
272                     // Store dependency
273
this.tableRefIndex = refCol.getTableIndex();
274                 }
275                 else
276                 {
277                     try
278                     {
279                         XMLDBCException ex = new XMLDBCException("The mapping for "
280                                 + cmeta + " is not consistent with existing foreign key constraints");
281                         if (messageHandler != null)
282                             messageHandler.warning(ex);
283                         log.warn(ex.getMessage());
284                     }
285                     catch (XMLDBCException e)
286                     {
287                         throw new SAXException JavaDoc("User abort", e);
288                     }
289                 }
290             }
291             typeInfo.checkTargetType(cmeta, messageHandler);
292         } // Table generation mode : no metadata, no check but store dependencies
293
else if (generator instanceof ColumnRefGenerator) {
294             // Store dependency
295
this.tableRefIndex = ((ColumnRefGenerator)generator).getColumnRef().getTableIndex();
296         }
297     }
298     
299     public TableMapping getTableMapping() { return tableMapping;}
300     
301     /**
302      * @return Returns the updateColumnWhenMissing.
303      */

304     public boolean updateColumnWhenMissing() { return updateColumnWhenMissing;}
305 }
306
Popular Tags