KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > spi > persistence > support > sqlstore > model > FieldDesc


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * FieldDesc.java
26  *
27  * Created on March 3, 2000
28  *
29  */

30
31 package com.sun.jdo.spi.persistence.support.sqlstore.model;
32
33
34 import com.sun.jdo.api.persistence.support.JDOUserException;
35 import com.sun.jdo.api.persistence.support.JDOFatalUserException;
36 import com.sun.jdo.spi.persistence.support.sqlstore.*;
37 import com.sun.jdo.spi.persistence.support.sqlstore.sco.SqlTimestamp;
38 import com.sun.jdo.spi.persistence.utility.FieldTypeEnumeration;
39 import com.sun.jdo.spi.persistence.utility.I18NHelper;
40 import com.sun.jdo.spi.persistence.utility.logging.Logger;
41 import org.netbeans.modules.dbschema.ColumnElement;
42
43 import java.lang.reflect.Field JavaDoc;
44 import java.math.BigDecimal JavaDoc;
45 import java.math.BigInteger JavaDoc;
46 import java.util.ArrayList JavaDoc;
47 import java.util.Date JavaDoc;
48 import java.util.ResourceBundle JavaDoc;
49
50 /**
51  *
52  */

53 public abstract class FieldDesc implements java.io.Serializable JavaDoc {
54
55     public static final int GROUP_DEFAULT = 1;
56
57     public static final int GROUP_NONE = 0;
58
59     /** This field is used for concurrency check */
60     public static final int PROP_IN_CONCURRENCY_CHECK = 0x1;
61
62     /** Update before image when this field is updated. This property is always set */
63     public static final int PROP_LOG_ON_UPDATE = 0x2;
64
65     /** This field is read only */
66     public static final int PROP_READ_ONLY = 0x4;
67
68     /** Record updates on this field to DB. This property is always set for primitive fields. */
69     public static final int PROP_RECORD_ON_UPDATE = 0x8;
70
71     /** Relationship updates are processed from the side containing this field. */
72     public static final int PROP_REF_INTEGRITY_UPDATES = 0x10;
73
74     /**
75      * This field is the primary tracked field.
76      * <P>
77      * Primitive fields track each other if they are mapped to same columns.
78      * One of them is made the primary tracked field as per precedence rules
79      * on the field types. This field is used to bind values to columns while
80      * updating the database.
81      * <P>
82      * RESOLVE:
83      * Investigate the runtime behaviour for relationship fields marked primary.
84      *
85      * @see #PROP_SECONDARY_TRACKED_FIELD
86      * @see ClassDesc#computeTrackedPrimitiveFields
87      * @see ClassDesc#computeTrackedRelationshipFields
88      */

89     public static final int PROP_PRIMARY_TRACKED_FIELD = 0x20;
90
91     /**
92      * This field is a secondary tracked field.
93      * <P>
94      * Seconday tracked primitive fields are not used for updates to the database
95      * or for concurrency checking.
96      * <P>
97      * RESOLVE:
98      * Investigate the runtime behaviour for secondary tracked relationship fields.
99      *
100      * @see #PROP_PRIMARY_TRACKED_FIELD
101      * @see ClassDesc#computeTrackedPrimitiveFields
102      * @see ClassDesc#computeTrackedRelationshipFields
103      */

104     public static final int PROP_SECONDARY_TRACKED_FIELD = 0x40;
105
106     /**
107      * This field tracks a relationship field.
108      * Only primitive fields can have this property set.
109      */

110     public static final int PROP_TRACK_RELATIONSHIP_FIELD = 0x80;
111
112     /** This field is part of a primary key. */
113     public static final int PROP_PRIMARY_KEY_FIELD = 0x100;
114
115     /** This field is used for version consistency validation. */
116     public static final int PROP_VERSION_FIELD = 0x200;
117
118     private static final BigDecimal JavaDoc LONG_MIN_VALUE =
119             new BigDecimal JavaDoc(String.valueOf(Long.MIN_VALUE));
120
121     private static final BigDecimal JavaDoc LONG_MAX_VALUE =
122             new BigDecimal JavaDoc(String.valueOf(Long.MAX_VALUE));
123
124     public int absoluteID;
125
126     public int fetchGroup;
127
128     public int concurrencyGroup;
129
130     public int sqlProperties;
131
132     private Field JavaDoc field;
133
134     private Class JavaDoc fieldType;
135
136     /**
137      * Contains a translation from the field type class to int constants.
138      * These constants can be used in switch statements on the field type.
139      */

140     private int enumFieldType;
141
142     private String JavaDoc fieldName;
143
144     private Class JavaDoc declaringClass;
145
146     // Should be moved to ForeignFieldDesc.
147
private Class JavaDoc componentType;
148
149     private ArrayList JavaDoc trackedFields;
150
151     /** Back pointer to declaring class descriptor. */
152     protected final ClassDesc classDesc;
153
154     /** The logger. */
155     protected final static Logger logger = LogHelperSQLStore.getLogger();
156
157     /** I18N message handler. */
158     protected final static ResourceBundle JavaDoc messages = I18NHelper.loadBundle(
159             "com.sun.jdo.spi.persistence.support.sqlstore.Bundle", // NOI18N
160
FieldDesc.class.getClassLoader());
161
162     FieldDesc(ClassDesc classDesc) {
163         // Set the default properties
164
sqlProperties |= FieldDesc.PROP_REF_INTEGRITY_UPDATES;
165         sqlProperties |= FieldDesc.PROP_IN_CONCURRENCY_CHECK;
166         sqlProperties |= FieldDesc.PROP_LOG_ON_UPDATE;
167
168         // For Boston, by default, a field is in group -1 which means that
169
// it is in its own group.
170
concurrencyGroup = -1;
171
172         this.classDesc = classDesc;
173     }
174
175     public String JavaDoc toString() {
176         return classDesc.getName() + "." + getName(); // NOI18N
177
}
178
179     public Class JavaDoc getComponentType() {
180         return componentType;
181     }
182
183     public Class JavaDoc getDeclaringClass() {
184         return declaringClass;
185     }
186
187     public Class JavaDoc getType() {
188         if (fieldType != null) return fieldType;
189
190         return Object JavaDoc.class;
191     }
192
193     public int getEnumType() {
194         return enumFieldType;
195     }
196
197     public String JavaDoc getName() {
198         if (fieldName == null)
199             fieldName = "hidden" + -absoluteID; // NOI18N
200

201         return fieldName;
202     }
203
204     public Object JavaDoc getValue(StateManager sm) {
205         if (sm == null) return null;
206
207         if (absoluteID >= 0) {
208             return ((PersistenceCapable) sm.getPersistent()).jdoGetField(absoluteID);
209         } else {
210             return sm.getHiddenValue(absoluteID);
211         }
212     }
213
214     public void setValue(StateManager sm, Object JavaDoc value) {
215         boolean debug = logger.isLoggable(Logger.FINEST);
216
217         if (sm == null) return;
218
219         if (absoluteID >= 0) {
220             if (debug) {
221                 if ((value != null) &&
222                         ((value instanceof com.sun.jdo.api.persistence.support.PersistenceCapable) ||
223                         (value instanceof java.util.Collection JavaDoc))) {
224                     Object JavaDoc[] items = new Object JavaDoc[] {field.getName(),value.getClass()};
225                     logger.finest("sqlstore.model.fielddesc.fieldname",items); // NOI18N
226
} else {
227                     Object JavaDoc[] items = new Object JavaDoc[] {field.getName(),value};
228                     logger.finest("sqlstore.model.fielddesc.fieldname",items); // NOI18N
229
}
230             }
231
232             // If the given value is null, and the field type is primitive
233
// scalar, we need to convert it to some default value. The following
234
// table shows the mapping:
235
// primitive number types (int, long, etc) --> 0
236
// boolean --> false
237
// char --> '\0'
238
if (value == null) {
239                 switch (enumFieldType) {
240                     case FieldTypeEnumeration.BOOLEAN_PRIMITIVE:
241                         value = new Boolean JavaDoc(false);
242                         break;
243                     case FieldTypeEnumeration.CHARACTER_PRIMITIVE:
244                         value = new Character JavaDoc('\0');
245                         break;
246                     case FieldTypeEnumeration.BYTE_PRIMITIVE:
247                     case FieldTypeEnumeration.SHORT_PRIMITIVE:
248                     case FieldTypeEnumeration.INTEGER_PRIMITIVE:
249                     case FieldTypeEnumeration.LONG_PRIMITIVE:
250                     case FieldTypeEnumeration.FLOAT_PRIMITIVE:
251                     case FieldTypeEnumeration.DOUBLE_PRIMITIVE:
252                         // Replace value type if necessary
253
value = convertValue(new Integer JavaDoc(0), sm);
254                         break;
255                 }
256             }
257
258             // We've tried our best to convert the value to the proper type.
259
// (convertValue() was called outside this class if necessary)
260
// Here is where we actually set the value. Anything that didn't
261
// get converted will get a ClassCastException.
262
((PersistenceCapable) sm.getPersistent()).jdoSetField(absoluteID, value);
263         } else {
264             if (debug) {
265                 Object JavaDoc[] items = new Object JavaDoc[] {getName(),value};
266                 logger.finest("sqlstore.model.fielddesc.fieldname",items); // NOI18N
267
}
268
269             sm.setHiddenValue(absoluteID, value);
270         }
271     }
272
273     public ArrayList JavaDoc getTrackedFields() {
274         return trackedFields;
275     }
276
277     /**
278      * Returns true if this field is a primary key field.
279      */

280     public boolean isKeyField() {
281         return ((sqlProperties & PROP_PRIMARY_KEY_FIELD) > 0);
282     }
283
284     /**
285      * Returns true if this field is a relationship field.
286      */

287     public boolean isRelationshipField() {
288         return false;
289     }
290
291     public Object JavaDoc convertValue(Object JavaDoc value, StateManager sm) {
292         boolean debug = logger.isLoggable(Logger.FINEST);
293         if (value == null) {
294             if (debug)
295                 logger.finest("sqlstore.model.fielddesc.convertvalue"); // NOI18N
296
return value;
297         }
298
299         if (absoluteID < 0) {
300             // Hidden field nothing to convert
301
if (debug)
302                 logger.finest("sqlstore.model.fielddesc.convertvalue.hidden",new Integer JavaDoc(absoluteID)); // NOI18N
303
return value;
304         }
305
306         if (debug) {
307             Object JavaDoc[] items = new Object JavaDoc[] {value,value.getClass().getName(),fieldType};
308             logger.finest("sqlstore.model.fielddesc.convertvalue.from_to",items); // NOI18N
309
}
310
311         // Here, we'll try our best to convert the given value to the
312
// proper type before setting the value using reflection.
313
if (value instanceof Number JavaDoc) {
314             Number JavaDoc number = (Number JavaDoc) value;
315
316             switch (enumFieldType) {
317                 case FieldTypeEnumeration.BOOLEAN_PRIMITIVE:
318                 case FieldTypeEnumeration.BOOLEAN:
319                     // Well, boolean in java is not really a number,
320
// but we'll try to convert it anyway. The algorithm is
321
// if the number is 0, set the field to false, otherwise
322
// set it to true.
323
// The easiest way to do this is to convert the number to
324
// a double before comparing it to 0.
325
if (number.doubleValue() == 0) {
326                         value = new Boolean JavaDoc(false);
327                     } else {
328                         value = new Boolean JavaDoc(true);
329                     }
330                     break;
331                 case FieldTypeEnumeration.BYTE_PRIMITIVE:
332                 case FieldTypeEnumeration.BYTE:
333                     if (!(value instanceof Byte JavaDoc)) {
334                         assertIsValid(number, Byte.MIN_VALUE, Byte.MAX_VALUE);
335                         value = new Byte JavaDoc(number.byteValue());
336                     }
337                     break;
338                 case FieldTypeEnumeration.SHORT_PRIMITIVE:
339                 case FieldTypeEnumeration.SHORT:
340                     if (!(value instanceof Short JavaDoc)) {
341                         assertIsValid(number, Short.MIN_VALUE, Short.MAX_VALUE);
342                         value = new Short JavaDoc(number.shortValue());
343                     }
344                     break;
345                 case FieldTypeEnumeration.INTEGER_PRIMITIVE:
346                 case FieldTypeEnumeration.INTEGER:
347                     if (!(value instanceof Integer JavaDoc)) {
348                         assertIsValid(number, Integer.MIN_VALUE, Integer.MAX_VALUE);
349                         value = new Integer JavaDoc(number.intValue());
350                     }
351                     break;
352                 case FieldTypeEnumeration.LONG_PRIMITIVE:
353                 case FieldTypeEnumeration.LONG:
354                     if (!(value instanceof Long JavaDoc)) {
355                         assertIsValidLong(number);
356                         value = new Long JavaDoc(number.longValue());
357                     }
358                     break;
359                 case FieldTypeEnumeration.FLOAT_PRIMITIVE:
360                 case FieldTypeEnumeration.FLOAT:
361                     if (!(value instanceof Float JavaDoc))
362                         value = new Float JavaDoc(number.floatValue());
363                     break;
364                 case FieldTypeEnumeration.DOUBLE_PRIMITIVE:
365                 case FieldTypeEnumeration.DOUBLE:
366                     if (!(value instanceof Double JavaDoc)) {
367                         // FIX FOR CONVERT FROM FLOAT.
368
if (value instanceof Float JavaDoc)
369                             value = new Double JavaDoc(number.toString());
370                         else
371                             value = new Double JavaDoc(number.doubleValue());
372                     }
373                     break;
374                 case FieldTypeEnumeration.BIGDECIMAL:
375                     if (!(value instanceof BigDecimal JavaDoc)) {
376                         if (value instanceof Double JavaDoc)
377                             value = new BigDecimal JavaDoc(number.doubleValue());
378                         else if (value instanceof BigInteger JavaDoc)
379                             value = new BigDecimal JavaDoc((java.math.BigInteger JavaDoc) value);
380                         else
381                             value = new BigDecimal JavaDoc(number.toString());
382                     }
383                     break;
384                 case FieldTypeEnumeration.BIGINTEGER:
385                     if (!(value instanceof BigInteger JavaDoc)) {
386                         if (value instanceof BigDecimal JavaDoc)
387                             value = ((BigDecimal JavaDoc) value).toBigInteger();
388                         else
389                             value = new BigInteger JavaDoc(number.toString());
390                     }
391                     break;
392             }
393         } else {
394
395             switch (enumFieldType) {
396                 case FieldTypeEnumeration.STRING:
397                     // If the value is not a String, we take the string representation
398
// of the value.
399
if (!(value instanceof String JavaDoc)) {
400                         value = value.toString();
401                     }
402                     break;
403
404                 case FieldTypeEnumeration.UTIL_DATE:
405                 case FieldTypeEnumeration.SQL_DATE:
406                 case FieldTypeEnumeration.SQL_TIME:
407                 case FieldTypeEnumeration.SQL_TIMESTAMP:
408                     value = convertToDateFieldType(value, sm);
409                     break;
410
411                 case FieldTypeEnumeration.CHARACTER_PRIMITIVE:
412                 case FieldTypeEnumeration.CHARACTER:
413                     // If the value is not a character, we take the first character
414
// of the string representation.
415
if (!(value instanceof Character JavaDoc)) {
416                         String JavaDoc str = value.toString();
417                         value = getCharFromString(str);
418                     }
419                     break;
420
421                 case FieldTypeEnumeration.BOOLEAN_PRIMITIVE:
422                 case FieldTypeEnumeration.BOOLEAN:
423                     // If the value is not a boolean, we construct a boolean
424
// using its string value.
425
if (!(value instanceof Boolean JavaDoc)) {
426                         if ((value instanceof String JavaDoc) &&
427                                 (value).equals("1")) // NOI18N
428
value = "true"; // NOI18N
429

430                         value = new Boolean JavaDoc(value.toString());
431                     }
432                     break;
433             }
434         }
435
436         return value;
437     }
438
439     /**
440      * Creates a new SCO instance. Therefore checks if PersistenceManager
441      * settings require SCO creation. SCOs will typically be created
442      * in a non managed environment.
443      *
444      * @param value Value being converted.
445      * @param sm StateManager of the persistent object being bound.
446      * @return New SCO instance according to <code>enumFieldType</code>
447      * of this field. Returns null if no SCO was created.
448      */

449     public Object JavaDoc createSCO(Object JavaDoc value, StateManager sm) {
450         Object JavaDoc retVal = null;
451
452         PersistenceManager pm = null;
453         if (sm != null) {
454             pm = (PersistenceManager) sm.getPersistenceManagerInternal();
455         }
456
457         if (pm != null && pm.getRequireTrackedSCO()) {
458             // Create a SCO instance and set values.
459
retVal = pm.newSCOInstanceInternal(fieldType,
460                     sm.getPersistent(),
461                     getName());
462
463             initializeSCO(retVal, value);
464         }
465
466         return retVal;
467     }
468
469     public static Character JavaDoc getCharFromString(String JavaDoc str) {
470         Character JavaDoc retVal = null;
471         if (str.length() == 0) {
472             retVal = new Character JavaDoc('\0');
473         } else {
474             retVal = new Character JavaDoc(str.charAt(0));
475         }
476         return retVal;
477     }
478
479     /**
480      * Converts <code>value</code> to the type given by <code>enumFieldType</code>.
481      * Creates a new SCO instance if the PersistenceManager settings require SCO
482      * creation.
483      *
484      * @param value Value being converted.
485      * @param sm StateManager associated to the persistent object being bound.
486      * @return Converted object. If no convertion is nessessary the original
487      * value is returned.
488      */

489     private Object JavaDoc convertToDateFieldType(Object JavaDoc value, StateManager sm) {
490         if (value instanceof SCO) {
491             ((SCO) value).unsetOwner();
492         }
493
494         Object JavaDoc retVal = createSCO(value, sm);
495
496         if (retVal == null) {
497             // We didn't create a SCO. This might be because we're running
498
// in a managed environment where we don't need to manage mutable
499
// objects as SCO. Simply convert value to the field type for
500
// this field.
501
retVal = convertToDateFieldType(value);
502         }
503
504         return retVal;
505     }
506
507     /**
508      * Returns an unmanaged Date instance. Converts <code>value</code>
509      * to the field type for this field according to <code>enumFieldType</code>.
510      *
511      * @param value Value being converted.
512      * @return Date instance according to <code>enumFieldType</code> of this field.
513      * If <code>value</code> is already of the correct type, it's instantly
514      * returned. Otherwise a new Date instance of the correct type is created.
515      */

516     private Object JavaDoc convertToDateFieldType(Object JavaDoc value) {
517         Object JavaDoc retVal = value;
518
519         if (!fieldType.equals(value.getClass())) {
520             // Convert to the new fieldType only.
521

522             if (value instanceof Date JavaDoc) {
523                 switch (enumFieldType) {
524                     case FieldTypeEnumeration.UTIL_DATE:
525                         retVal = new java.util.Date JavaDoc(((Date JavaDoc) value).getTime());
526                         break;
527                     case FieldTypeEnumeration.SQL_DATE:
528                         retVal = new java.sql.Date JavaDoc(((Date JavaDoc) value).getTime());
529                         break;
530                     case FieldTypeEnumeration.SQL_TIME:
531                         retVal = new java.sql.Time JavaDoc(((Date JavaDoc) value).getTime());
532                         break;
533                     case FieldTypeEnumeration.SQL_TIMESTAMP:
534                         retVal = new java.sql.Timestamp JavaDoc(((Date JavaDoc) value).getTime());
535
536                         // Adjust nano second information for Timestamps.
537
// NOTE: The constructor java.sql.Timestamp(long) calculates nano
538
// seconds. If the old and new instance both represent Timestamps,
539
// the calculation truncates nano second information from the
540
// original object, see java.sql.Timestamp#getTime().
541
if (value instanceof java.sql.Timestamp JavaDoc) {
542                             // Overwrite nano second information with the original value.
543
((java.sql.Timestamp JavaDoc) retVal).setNanos(((java.sql.Timestamp JavaDoc) value).getNanos());
544                         }
545                         break;
546                     default:
547                 }
548             }
549         }
550
551         return retVal;
552     }
553
554     /**
555      * Initializes the SCO instance <code>scoVal</code> corresponding
556      * to <code>value</code>. Currently only used for dates.
557      *
558      * @param scoVal SCO instance being populated.
559      * @param value Instance used for initialisation.
560      */

561     private void initializeSCO(Object JavaDoc scoVal, Object JavaDoc value) {
562         switch(enumFieldType) {
563             case FieldTypeEnumeration.UTIL_DATE:
564             case FieldTypeEnumeration.SQL_DATE:
565             case FieldTypeEnumeration.SQL_TIME:
566             case FieldTypeEnumeration.SQL_TIMESTAMP:
567                 // Initializing SCODate
568
if (value instanceof Date JavaDoc) {
569                     // Set milliseconds information
570
((SCODate) scoVal).setTimeInternal(((Date JavaDoc) value).getTime());
571
572                     // Adjust nano second information for Timestamps.
573
// NOTE: java.sql.Timestamp#setTime(long) recalculates nano
574
// seconds. If old and new instance both represent Timestamps,
575
// the recalculation truncates nano second information from the
576
// original object, see java.sql.Timestamp#getTime().
577
if (enumFieldType == FieldTypeEnumeration.SQL_TIMESTAMP
578                             && value instanceof java.sql.Timestamp JavaDoc) {
579                         // Overwrite nano second information with original value
580
((SqlTimestamp) scoVal).setNanosInternal(((java.sql.Timestamp JavaDoc) value).getNanos());
581                     }
582                 }
583                 break;
584             default:
585         }
586     }
587
588     private void assertIsValid(Number JavaDoc number, double min_value, double max_value) {
589         double x = number.doubleValue();
590         if (x < min_value)
591             throw new JDOUserException(I18NHelper.getMessage(messages,
592                     "core.fielddesc.minvalue", // NOI18N
593
new Object JavaDoc[]{number, String.valueOf(min_value), fieldType.getName()}));
594         if (x > max_value)
595             throw new JDOUserException(I18NHelper.getMessage(messages,
596                     "core.fielddesc.maxvalue", // NOI18N
597
new Object JavaDoc[]{number, String.valueOf(max_value), fieldType.getName()}));
598     }
599
600     private void assertIsValidLong(Number JavaDoc number) {
601         BigDecimal JavaDoc bd = null;
602         if (number instanceof BigDecimal JavaDoc) {
603             bd = (BigDecimal JavaDoc) number;
604         } else {
605             bd = new BigDecimal JavaDoc(number.toString());
606         }
607         if (bd.compareTo(LONG_MIN_VALUE) < 0) {
608             throw new JDOUserException(I18NHelper.getMessage(messages,
609                     "core.fielddesc.minvalue", // NOI18N
610
new Object JavaDoc[]{number, String.valueOf(Long.MIN_VALUE),
611                         fieldType.getName()}));
612
613         } else if (bd.compareTo(LONG_MAX_VALUE) > 0) {
614             throw new JDOUserException(I18NHelper.getMessage(messages,
615                     "core.fielddesc.maxvalue", // NOI18N
616
new Object JavaDoc[]{number, String.valueOf(Long.MAX_VALUE),
617                         fieldType.getName()}));
618         }
619     }
620
621     //
622
// ------------ Initialisation methods ------------
623
//
624

625     void setupDesc(final Class JavaDoc classType, final String JavaDoc name) {
626
627         Field JavaDoc f = (Field JavaDoc) java.security.AccessController.doPrivileged(
628                 new java.security.PrivilegedAction JavaDoc() {
629                     public Object JavaDoc run() {
630                         try {
631                             return classType.getDeclaredField(name);
632                         } catch (NoSuchFieldException JavaDoc e) {
633                             throw new JDOFatalUserException(I18NHelper.getMessage(messages,
634                             "core.configuration.loadfailed.field", // NOI18N
635
name, classType.getName()), e);
636                         }
637                     }
638                 });
639
640         setupDesc(f);
641     }
642
643     protected void setupDesc(Field JavaDoc f) {
644         field = f;
645         fieldName = f.getName();
646         declaringClass = field.getDeclaringClass();
647
648         fieldType = field.getType();
649         enumFieldType = translateToEnumType(fieldType);
650
651         if (logger.isLoggable(Logger.FINEST)) {
652             Object JavaDoc[] items= new Object JavaDoc[] {fieldName,fieldType};
653             logger.finest("sqlstore.model.fielddesc.setupdesc",items); // NOI18N
654
}
655     }
656
657     private static int translateToEnumType(Class JavaDoc fldType) {
658
659         int retVal = FieldTypeEnumeration.NOT_ENUMERATED;
660
661         if(fldType == Boolean.TYPE ) retVal = FieldTypeEnumeration.BOOLEAN_PRIMITIVE;
662         else if(fldType == Character.TYPE ) retVal = FieldTypeEnumeration.CHARACTER_PRIMITIVE;
663         else if(fldType == Byte.TYPE ) retVal = FieldTypeEnumeration.BYTE_PRIMITIVE;
664         else if(fldType == Short.TYPE ) retVal = FieldTypeEnumeration.SHORT_PRIMITIVE;
665         else if(fldType == Integer.TYPE ) retVal = FieldTypeEnumeration.INTEGER_PRIMITIVE;
666         else if(fldType == Long.TYPE ) retVal = FieldTypeEnumeration.LONG_PRIMITIVE ;
667         else if(fldType == Float.TYPE ) retVal = FieldTypeEnumeration.FLOAT_PRIMITIVE;
668         else if(fldType == Double.TYPE ) retVal = FieldTypeEnumeration.DOUBLE_PRIMITIVE;
669         else if(fldType == Boolean JavaDoc.class ) retVal = FieldTypeEnumeration.BOOLEAN;
670         else if(fldType == Character JavaDoc.class ) retVal = FieldTypeEnumeration.CHARACTER;
671         else if(fldType == Byte JavaDoc.class ) retVal = FieldTypeEnumeration.BYTE;
672         else if(fldType == Short JavaDoc.class ) retVal = FieldTypeEnumeration.SHORT;
673         else if(fldType == Integer JavaDoc.class ) retVal = FieldTypeEnumeration.INTEGER;
674         else if(fldType == Long JavaDoc.class ) retVal = FieldTypeEnumeration.LONG;
675         else if(fldType == Float JavaDoc.class ) retVal = FieldTypeEnumeration.FLOAT;
676         else if(fldType == Double JavaDoc.class ) retVal = FieldTypeEnumeration.DOUBLE;
677         else if(fldType == java.math.BigDecimal JavaDoc.class) retVal = FieldTypeEnumeration.BIGDECIMAL;
678         else if(fldType == java.math.BigInteger JavaDoc.class) retVal = FieldTypeEnumeration.BIGINTEGER;
679         else if(fldType == String JavaDoc.class ) retVal = FieldTypeEnumeration.STRING;
680         else if(fldType == java.util.Date JavaDoc.class ) retVal = FieldTypeEnumeration.UTIL_DATE;
681         else if(fldType == java.sql.Date JavaDoc.class ) retVal = FieldTypeEnumeration.SQL_DATE;
682         else if(fldType == java.sql.Time JavaDoc.class ) retVal = FieldTypeEnumeration.SQL_TIME;
683         else if(fldType == java.sql.Timestamp JavaDoc.class ) retVal = FieldTypeEnumeration.SQL_TIMESTAMP;
684         else if(fldType.isArray()) {
685             if(fldType.getComponentType() == Byte.TYPE) {
686                 retVal = FieldTypeEnumeration.ARRAY_BYTE_PRIMITIVE;
687             }
688         }
689
690         return retVal;
691     }
692
693     void setComponentType(Class JavaDoc type) {
694         this.componentType = type;
695     }
696
697     protected void addTrackedField(FieldDesc f) {
698         if (trackedFields == null)
699             trackedFields = new ArrayList JavaDoc();
700
701         if (logger.isLoggable(Logger.FINEST)) {
702             Object JavaDoc[] items = new Object JavaDoc[] {f.getName(),getName()};
703             logger.finest("sqlstore.model.fielddesc.addingfield",items); // NOI18N
704
}
705
706         trackedFields.add(f);
707     }
708
709     abstract void computeTrackedRelationshipFields();
710
711     /**
712      * This method compares the column lists between to fields to see if they match.
713      * If f1 and f2 are both primitive fields, we do an exact match.
714      * If f1 is primitve and f2 is a relationship field, we do an at-least-one match.
715      * If both f1 and f2 are relationship fields, we do an exact match.
716      * @return <code>true</code> if there is a match, <code>false</code>, otherwise.
717      */

718     static boolean compareColumns(FieldDesc f1, FieldDesc f2) {
719         ArrayList JavaDoc columnList1 = null;
720         ArrayList JavaDoc columnList2 = null;
721         ArrayList JavaDoc columnList3 = null;
722         ArrayList JavaDoc columnList4 = null;
723         boolean exactMatch = false;
724
725         // For LocalFieldDesc, we use columnDescs for comparison.
726
// Otherwise, we use localColumns for comparison.
727
if (f1 instanceof LocalFieldDesc) {
728             columnList1 = ((LocalFieldDesc) f1).columnDescs;
729
730             if (f2 instanceof LocalFieldDesc) {
731                 columnList2 = ((LocalFieldDesc) f2).columnDescs;
732
733                 // Not sure yet whether we need to a exact match
734
// here yet.
735
exactMatch = true;
736             } else {
737                 // We are comparing LocalFieldDesc and ForeignFieldDesc.
738
// We do not need an exact match. The relationship must change,
739
// if one of the LocalFieldDesc's columns is changed.
740
columnList2 = ((ForeignFieldDesc) f2).localColumns;
741             }
742         } else {
743             if (f2 instanceof LocalFieldDesc) {
744                 return false;
745             } else {
746                 ForeignFieldDesc ff1 = (ForeignFieldDesc) f1;
747                 ForeignFieldDesc ff2 = (ForeignFieldDesc) f2;
748
749                 if (ff1.useJoinTable() && ff2.useJoinTable()) {
750                     columnList1 = ff1.assocLocalColumns;
751                     columnList2 = ff2.assocLocalColumns;
752                     columnList3 = ff1.assocForeignColumns;
753                     columnList4 = ff2.assocForeignColumns;
754                 } else if (!ff1.useJoinTable() && !ff2.useJoinTable()) {
755                     columnList1 = ff1.localColumns;
756                     columnList2 = ff2.localColumns;
757                     columnList3 = ff1.foreignColumns;
758                     columnList4 = ff2.foreignColumns;
759                 } else {
760                     return false;
761                 }
762
763                 exactMatch = true;
764             }
765         }
766
767         boolean found = false;
768
769         for (int k = 0; k < 2; k++) {
770             if (k == 1) {
771                 if (columnList3 != null) {
772                     columnList1 = columnList3;
773                     columnList2 = columnList4;
774                 } else {
775                     break;
776                 }
777             }
778
779             int size1 = columnList1.size();
780             int size2 = columnList2.size();
781
782             if (exactMatch && (size1 != size2)) {
783                 return false;
784             }
785
786             for (int i = 0; i < size1; i++) {
787                 found = false;
788
789                 ColumnElement c1 = (ColumnElement) columnList1.get(i);
790
791                 // Find if any column of columnList2 matches with c1.
792
for (int j = 0; j < size2; j++) {
793                     ColumnElement c2 = (ColumnElement) columnList2.get(j);
794
795                     if (c1.getName().getFullName().equals(c2.getName().getFullName())) {
796                         found = true;
797                     }
798                 }
799
800                 // If we are doing an exact match, and no match is found,
801
// we return false.
802
if (exactMatch && !found) {
803                     return false;
804                 }
805
806                 // If we are not doing an exact match and a match is found,
807
// we return true;
808
if (!exactMatch && found) {
809                     return true;
810                 }
811             }
812         }
813
814         // If found is true, that means we got here because the two column lists match
815
// exactly. Otherwise, the two column lists don't match at all.
816
return found;
817     }
818
819 }
820
Popular Tags