KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > model > mapping > impl > MappingClassElementImpl


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  * MappingClassElementImpl.java
26  *
27  * Created on March 3, 2000, 1:11 PM
28  */

29
30 package com.sun.jdo.api.persistence.model.mapping.impl;
31
32 import java.util.*;
33 import java.beans.PropertyVetoException JavaDoc;
34
35 import org.netbeans.modules.dbschema.*;
36 import org.netbeans.modules.dbschema.util.NameUtil;
37
38 import com.sun.jdo.api.persistence.model.*;
39 import com.sun.jdo.api.persistence.model.mapping.*;
40 import com.sun.jdo.api.persistence.model.jdo.PersistenceClassElement;
41 import com.sun.jdo.spi.persistence.utility.I18NHelper;
42 import com.sun.jdo.spi.persistence.utility.JavaTypeHelper;
43
44 /**
45  *
46  * @author Mark Munro
47  * @author Rochelle Raccah
48  * @version %I%
49  */

50 public class MappingClassElementImpl extends MappingElementImpl
51     implements MappingClassElement
52 {
53     // used in properties bitmask, jeff will check if used
54
public static final int CLONE_FIELDS = 1;
55     public static final int CLONE_DEEP = 2;
56     public static final int CLONE_MASK = 3;
57     public static final int NAVIGABLE = 4;
58
59     PersistenceClassElement _persistenceElement;
60
61     private boolean _isModified;
62     private int _properties;
63     private ArrayList _tables; // array of MappingTableElement
64
private ArrayList _fields; // array of MappingFieldElement
65

66     /** The current version number.
67      * Note: Please increment this if there are any changes in the
68      * mapping model that might cause incompatibilities to older versions.
69      */

70     private static final int CURRENT_VERSION_NO = 5;
71
72     /** Version number of this MappingClassElementImpl object.
73      * This number is set by the initilaizer of the declaration or
74      * set by the archiver when reading a mapping file.
75      */

76     private int versionNo = CURRENT_VERSION_NO;
77
78     /** The database root for this MappingClassElement.
79      * The database root is the schema name of of all the db elements
80      * attached to this MappingClassElement.
81      */

82     private String JavaDoc _databaseRoot;
83
84     /** Consistency Level of this MappingClassElement.
85      */

86     private int _consistencyLevel;
87
88     
89     /*
90     // possibly for EJB use later
91     // private String EJBName;
92     // which of these (one from desc, one from config)?
93     // public Class finderClass;
94     // private String finderClass;
95     // private Class finderClassType;
96     // public static final String DEFAULT_JAVA_FINDERCLASS ="not yet implemented";
97     // end possibly for EJB use later
98     */

99
100     // possibly for sequence/identity fields later
101
// public ColumnElement uniqueIDCol;
102

103     /** Create new MappingClassElementImpl with no corresponding persistence
104      * element or name. This constructor should only be used for cloning and
105      * archiving.
106      */

107     public MappingClassElementImpl ()
108     {
109         this((String JavaDoc)null);
110     }
111
112     /** Creates new MappingClassElementImpl with the corresponding name
113      * @param name the name of the element
114      */

115     public MappingClassElementImpl (String JavaDoc name)
116     {
117         super(name);
118         _consistencyLevel = NONE_CONSISTENCY;
119         _properties = _properties | NAVIGABLE;
120     }
121
122     /** Creates new MappingClassElementImpl with a corresponding
123      * PersistenceClassElement
124      * @param element the persistence element with which to be associated
125      */

126     public MappingClassElementImpl (PersistenceClassElement element)
127     {
128         this((element != null) ? element.getName() : null);
129         setPersistenceElement(element);
130     }
131
132     /** Returns the version number of this MappingClassElement object.
133      * Please note, the returned version number reflects the version number at
134      * the last save, NOT the version number of the memory representation.
135      * @return version number
136      */

137     public int getVersionNumber () { return versionNo; }
138
139     /** Set the version number of this MappingClassElement.
140      * @param version the new version number
141      */

142     private void setVersionNumber (int version) { versionNo = version; }
143     
144     /** Returns true if the version number of this MappingClassElement object
145      * is older than the current version number of the archiving scheme.
146      * @see #getVersionNumber
147      * @return true if it is in need of updating, false otherwise
148      */

149     public boolean hasOldVersionNumber ()
150     {
151         return (getVersionNumber() < CURRENT_VERSION_NO);
152     }
153
154     /** Returns the mapping class element associated with the class with the
155      * given string name, using the given model object to look it up.
156      * @param name the fully qualified name of the desired class
157      * @param model the model object to be used to look it up
158      * @return mapping class element representing the desired class
159      */

160     public static MappingClassElement forName (String JavaDoc name, Model model)
161     {
162         return model.getMappingClass(name);
163     }
164
165     /** Fires property change event. This method overrides that of
166      * MappingElementImpl to update the mapping class element's modified
167      * status.
168      * @param name property name
169      * @param o old value
170      * @param n new value
171      */

172     protected final void firePropertyChange (String JavaDoc name, Object JavaDoc o, Object JavaDoc n)
173     {
174         // even though o == null and n == null will signify a change, that
175
// is consistent with PropertyChangeSupport's behavior and is
176
// necessary for this to work
177
boolean noChange = ((o != null) && (n != null) && o.equals(n));
178
179         super.firePropertyChange(name, o, n);
180
181         if (!(PROP_MODIFIED.equals(name)) && !noChange)
182             setModified(true);
183     }
184
185     /** Fires vetoable change event. This method overrides that of
186      * MappingElementImpl to give listeners a chance to block
187      * changes on the mapping class element modified status.
188      * @param name property name
189      * @param o old value
190      * @param n new value
191      * @exception PropertyVetoException when the change is vetoed by a listener
192      */

193     protected final void fireVetoableChange (String JavaDoc name, Object JavaDoc o, Object JavaDoc n)
194         throws PropertyVetoException JavaDoc
195     {
196         // even though o == null and n == null will signify a change, that
197
// is consistent with PropertyChangeSupport's behavior and is
198
// necessary for this to work
199
boolean noChange = ((o != null) && (n != null) && o.equals(n));
200
201         super.fireVetoableChange(name, o, n);
202
203         if (!(PROP_MODIFIED.equals(name)) && !noChange)
204             fireVetoableChange(PROP_MODIFIED, Boolean.FALSE, Boolean.TRUE);
205     }
206
207     /** @return persistence class element for this mapping class element
208      */

209     public final PersistenceClassElement getPersistenceElement ()
210     {
211         return _persistenceElement;
212     }
213
214     /** Set the persistence class element for this mapping class element.
215      * @param element the persistence class element
216      */

217     public void setPersistenceElement (PersistenceClassElement element)
218     {
219         _persistenceElement = element;
220     }
221
222     // TBD if needed
223
/*public void clear()
224     {
225         Iterator fieldIterator = getFields().iterator();
226
227         while (fieldIterator.hasNext())
228             ((MappingFieldElement)fieldIterator.next()).clear();
229
230         _tables = new ArrayList();
231     }
232 */

233     //================= implementation of MappingClassElement ================
234

235     /** Gets the modified flag for this mapping class.
236      * @return <code>true</code> if there have been (property) changes to this
237      * class, <code>false</code> otherwise.
238      */

239     public boolean isModified () { return _isModified; }
240
241     /** Set the modified flag for this mapping class to flag. This is usually
242      * set to <code>true</code> by property changes and <code>false</code>
243      * after a save.
244      * @param flag if <code>true</code>, this class is marked as modified;
245      * if <code>false</code>, it is marked as unmodified.
246      */

247     public void setModified (boolean flag)
248     {
249         boolean oldFlag = isModified();
250
251         if (flag != oldFlag)
252         {
253             _isModified = flag;
254             firePropertyChange(PROP_MODIFIED, JavaTypeHelper.valueOf(oldFlag),
255                 JavaTypeHelper.valueOf(flag));
256         }
257     }
258
259     /** Gets the consistency level of this mapping class.
260      * @return the consistency level, one of {@link #NONE_CONSISTENCY},
261      * {@link #CHECK_MODIFIED_AT_COMMIT_CONSISTENCY},
262      * {@link #CHECK_ALL_AT_COMMIT_CONSISTENCY},
263      * {@link #LOCK_WHEN_MODIFIED_CONSISTENCY},
264      * {@link #LOCK_WHEN_MODIFIED_CHECK_ALL_AT_COMMIT_CONSISTENCY},
265      * {@link #LOCK_WHEN_LOADED_CONSISTENCY}, or
266      * {@link #VERSION_CONSISTENCY}.
267      * The default is {@link #NONE_CONSISTENCY}.
268      */

269     public int getConsistencyLevel () { return _consistencyLevel; }
270
271     /** Set the consistency level of this mapping class.
272      * @param level an integer indicating the consistency level, one of:
273      * {@link #NONE_CONSISTENCY},{@link #CHECK_MODIFIED_AT_COMMIT_CONSISTENCY},
274      * {@link #CHECK_ALL_AT_COMMIT_CONSISTENCY},
275      * {@link #LOCK_WHEN_MODIFIED_CONSISTENCY},
276      * {@link #LOCK_WHEN_MODIFIED_CHECK_ALL_AT_COMMIT_CONSISTENCY},
277      * {@link #LOCK_WHEN_LOADED_CONSISTENCY}, or
278      * {@link #VERSION_CONSISTENCY}.
279      * @exception ModelException if impossible.
280      */

281     public void setConsistencyLevel (int level) throws ModelException
282     {
283         Integer JavaDoc old = new Integer JavaDoc(getConsistencyLevel());
284         Integer JavaDoc newLevel = new Integer JavaDoc(level);
285
286         try
287         {
288             fireVetoableChange(PROP_CONSISTENCY, old, newLevel);
289             _consistencyLevel = level;
290             firePropertyChange(PROP_CONSISTENCY, old, newLevel);
291         }
292         catch (PropertyVetoException JavaDoc e)
293         {
294             throw new ModelVetoException(e);
295         }
296     }
297
298     /** Returns the name of the SchemaElement which represents the
299      * database used by the tables mapped to this mapping class.
300      * @return the name of the database root for this mapping class
301      */

302     public String JavaDoc getDatabaseRoot () { return _databaseRoot; }
303
304     /** Set the database root for this MappingClassElement.
305      * The root represents the database used by the tables mapped to
306      * this mapping class.
307      * @param root the new database root
308      * @exception ModelException if impossible
309      */

310     public void setDatabaseRoot (SchemaElement root) throws ModelException
311     {
312         String JavaDoc old = getDatabaseRoot();
313         String JavaDoc newRoot = ((root != null) ? root.getName().getFullName() : null);
314         
315         try
316         {
317             fireVetoableChange(PROP_DATABASE_ROOT, old, newRoot);
318             _databaseRoot = newRoot;
319             firePropertyChange(PROP_DATABASE_ROOT, old, newRoot);
320         }
321         catch (PropertyVetoException JavaDoc e)
322         {
323             throw new ModelVetoException(e);
324         }
325     }
326
327     /** Returns the list of tables (MappingTableElements) used by this mapping
328      * class.
329      * @return the meta data tables for this mapping class
330      */

331     public ArrayList getTables ()
332     {
333         if (_tables == null)
334             _tables = new ArrayList();
335
336         return _tables;
337     }
338
339     /** Scans through this mapping class looking for a table whose
340      * name matches the name passed in.
341      * @param name name of the table to find.
342      * @return the meta data table whose name matches the name parameter
343      */

344     public MappingTableElement getTable (String JavaDoc name)
345     {
346         Iterator tableIterator = getTables().iterator();
347
348         while (tableIterator.hasNext())
349         {
350             MappingTableElement table =
351                 (MappingTableElement)tableIterator.next();
352
353             if (table.getName().equals(name))
354                 return table;
355         }
356
357         return null;
358     }
359
360     /** Convenience method which accepts a table element and attempts to add
361      * it as either a primary or secondary table depending on the existing list
362      * of tables and the foreign keys for the table.
363      * @param table table element to be added as either a primary or secondary
364      * table.
365      * @exception ModelException if impossible
366      */

367     public void addTable (TableElement table) throws ModelException
368     {
369         if (table != null)
370         {
371             ArrayList tables = getTables();
372
373             // If the table list is empty, this should be the primary table
374
if (tables.isEmpty())
375                 setPrimaryTable(table);
376             else
377             {
378                 HashMap newSecondaryTables = new HashMap();
379                 Iterator iterator = tables.iterator();
380                 boolean found = false;
381
382                 // If this table has already been added just skip it and return
383
while (iterator.hasNext())
384                     if (((MappingTableElement)iterator.next()).isEqual(table))
385                         return;
386
387                 // Add the table as a secondary table as long as there are
388
// relevant fks setup. Otherwise, throw an exception
389
iterator = tables.iterator();
390                 while (iterator.hasNext())
391                 {
392                     MappingTableElement mappingTable =
393                         (MappingTableElement)iterator.next();
394                     String JavaDoc absoluteTableName = NameUtil.getAbsoluteTableName(
395                         _databaseRoot, mappingTable.getTable());
396                     ForeignKeyElement[] foreignKeys = TableElement.forName(
397                         absoluteTableName).getForeignKeys();
398                     int i, count =
399                         ((foreignKeys != null) ? foreignKeys.length : 0);
400
401                     for (i = 0; i < count; i++)
402                     {
403                         ForeignKeyElement fk = foreignKeys[i];
404
405                         if (table == fk.getReferencedTable())
406                         {
407                             // store it so it can be added after we finish
408
// iterating the array (can't now because of
409
// concurrent modification restrictions)
410
newSecondaryTables.put(mappingTable, fk);
411                             found = true;
412                         }
413                     }
414                 }
415
416                 if (found) // add the secondary tables now
417
{
418                     iterator = newSecondaryTables.keySet().iterator();
419                     
420                     while (iterator.hasNext())
421                     {
422                         MappingTableElement mappingTable =
423                             (MappingTableElement)iterator.next();
424                         MappingReferenceKeyElement refKey =
425                             addSecondaryTable(mappingTable, table);
426
427                         refKey.addColumnPairs(((ForeignKeyElement)
428                             newSecondaryTables.get(mappingTable)).
429                             getColumnPairs());
430                     }
431
432                 }
433                 else
434                 {
435                     throw new ModelException(I18NHelper.getMessage(
436                         getMessages(),
437                         "mapping.table.foreign_key_not_found", table)); // NOI18N
438
}
439             }
440         }
441         else
442         {
443             throw new ModelException(I18NHelper.getMessage(getMessages(),
444                 "mapping.table.null_argument")); // NOI18N
445
}
446     }
447
448     /** Set the primary table for this mapping class to the supplied table.
449      * @param table table element to be used as the primary table.
450      * @exception ModelException if impossible
451      */

452     public void setPrimaryTable (TableElement table) throws ModelException
453     {
454         ArrayList tables = getTables();
455
456         if (!tables.isEmpty())
457         {
458             throw new ModelException(I18NHelper.getMessage(getMessages(),
459                 "mapping.table.primary_table_defined", table)); // NOI18N
460
}
461         else
462         {
463             UniqueKeyElement key = table.getPrimaryKey();
464             MappingTableElement mappingTable =
465                 new MappingTableElementImpl(table, this);
466             SchemaElement schema = table.getDeclaringSchema();
467             String JavaDoc currentRoot = getDatabaseRoot();
468
469             if (currentRoot == null) // set database root
470
setDatabaseRoot(schema);
471             else if (!currentRoot.equals(schema.getName().getFullName()))
472             {
473                 // if database root was set before, it must match
474
throw new ModelException(I18NHelper.getMessage(
475                     getMessages(), "mapping.table.schema_mismatch", // NOI18N
476
table.toString(), currentRoot));
477             }
478
479             try
480             {
481                 fireVetoableChange(PROP_TABLES, null, null);
482                 tables.add(mappingTable);
483                 firePropertyChange(PROP_TABLES, null, null);
484             }
485             catch (PropertyVetoException JavaDoc e)
486             {
487                 throw new ModelVetoException(e);
488             }
489
490             // If can't find a primary key, settle for first unique key.
491
if (key == null)
492             {
493                 UniqueKeyElement[] uniqueKeys = table.getUniqueKeys();
494
495                 if ((uniqueKeys != null) && (uniqueKeys.length > 0))
496                     key = uniqueKeys[0];
497             }
498
499             if (key == null)
500             {
501                 // This is a warning -- we can still use the table but we
502
// cannot perform update operations on it. Also the user
503
// may define the key later.
504
}
505             else
506             {
507                 ColumnElement[] columns = key.getColumns();
508                 int i, count = ((columns != null) ? columns.length : 0);
509
510                 for (i = 0; i < count; i++)
511                     mappingTable.addKeyColumn(columns[i]);
512             }
513         }
514     }
515
516     /** Adds a reference to the supplied table as a secondary table for this
517      * mapping class. It creates a MappingReferenceKeyElement for the supplied
518      * primary/secondary table pair.
519      * @param parent mapping table element which should also be the primary
520      * table.
521      * @param table table element to be used as a secondary table.
522      * @exception ModelException if impossible
523      */

524     public MappingReferenceKeyElement addSecondaryTable (MappingTableElement
525         parentTable, TableElement table) throws ModelException
526     {
527         ArrayList tables = getTables();
528
529         if ((parentTable == null) || (table == null))
530         {
531             throw new ModelException(I18NHelper.getMessage(getMessages(),
532                 "mapping.element.null_argument")); // NOI18N
533
}
534         else if (!tables.contains(parentTable))
535         {
536             throw new ModelException(I18NHelper.getMessage(getMessages(),
537                 "mapping.table.parent_table_not_found", // NOI18N
538
parentTable.getTable()));
539         }
540         else
541         {
542             // Check the parent table's reference keys to make sure that this
543
// secondary table has not already been added to this parent table.
544
// If it has, throw an exception
545
Iterator iterator = parentTable.getReferencingKeys().iterator();
546             MappingTableElement mappingTable =
547                 new MappingTableElementImpl(table, this);
548             MappingReferenceKeyElement key =
549                 new MappingReferenceKeyElementImpl(mappingTable);
550
551             while (iterator.hasNext())
552             {
553                 MappingTableElement compareTable =
554                     ((MappingReferenceKeyElement)iterator.next()).getTable();
555
556                 if (compareTable.isEqual(table))
557                 {
558                     throw new ModelException(I18NHelper.getMessage(
559                         getMessages(),
560                         "mapping.table.secondary_table_defined", // NOI18N
561
new Object JavaDoc[]{table, parentTable.getTable()}));
562                 }
563             }
564
565             try
566             {
567                 fireVetoableChange(PROP_TABLES, null, null);
568                 parentTable.addReferencingKey(key);
569                 tables.add(mappingTable);
570                 firePropertyChange(PROP_TABLES, null, null);
571             }
572             catch (PropertyVetoException JavaDoc e)
573             {
574                 throw new ModelVetoException(e);
575             }
576
577             return key;
578         }
579     }
580
581     /** Removes the reference to the supplied table as a mapped table for this
582      * mapping class. This works whether the table is the primary table or a
583      * secondary table.
584      * @param table mapping table element to be removed from this mapping class.
585      * @exception ModelException if impossible
586      */

587     public void removeTable (MappingTableElement table) throws ModelException
588     {
589         if (table != null)
590         {
591             Collection tables = getTables();
592             Iterator iterator = null;
593             boolean found = false;
594
595             try
596             {
597                 fireVetoableChange(PROP_TABLES, null, null);
598                 found = tables.remove(table);
599                 firePropertyChange(PROP_TABLES, null, null);
600             }
601             catch (PropertyVetoException JavaDoc e)
602             {
603                 throw new ModelVetoException(e);
604             }
605
606             // remove all references to this table
607
iterator = tables.iterator();
608             while (iterator.hasNext())
609             {
610                 MappingTableElement nextTable =
611                     (MappingTableElement)iterator.next();
612
613                 nextTable.removeReference(table);
614             }
615
616             if (found) // remove any fields mapped to that table
617
{
618                 ArrayList fieldsToRemove = new ArrayList();
619
620                 iterator = getFields().iterator();
621                 while (iterator.hasNext())
622                 {
623                     MappingFieldElementImpl mappingField =
624                         (MappingFieldElementImpl)iterator.next();
625                     
626                     if (mappingField.isMappedToTable(table))
627                         fieldsToRemove.add(mappingField);
628                 }
629
630                 iterator = fieldsToRemove.iterator();
631                 while (iterator.hasNext())
632                 {
633                     MappingFieldElement mappingField =
634                         (MappingFieldElement)iterator.next();
635                     boolean versionField = mappingField.isVersion();
636
637                     removeField(mappingField);
638
639                     // if it is a version field, add back an unmapped
640
// field which retains the version flag setting
641
if (versionField)
642                     {
643                         mappingField = new MappingFieldElementImpl(
644                             mappingField.getName(), this);
645                         mappingField.setVersion(true);
646                         addField(mappingField);
647                     }
648                 }
649             }
650             else
651             {
652                 throw new ModelException(I18NHelper.getMessage(getMessages(),
653                     "mapping.element.element_not_removed", table)); // NOI18N
654
}
655         }
656         else
657         {
658             throw new ModelException(I18NHelper.getMessage(getMessages(),
659                 "mapping.element.null_argument")); // NOI18N
660
}
661     }
662
663     /** Returns the list of fields (MappingFieldElements) in this mapping
664      * class. This list includes both local and relationship fields.
665      * @return the mapping fields in this mapping class
666      */

667     public ArrayList getFields ()
668     {
669         if (_fields == null)
670             _fields = new ArrayList();
671
672         return _fields;
673     }
674
675     /** Scans through this mapping class looking for a field whose
676      * name matches the name passed in.
677      * @param name name of the field to find.
678      * @return the mapping field whose name matches the name parameter
679      */

680     public MappingFieldElement getField (String JavaDoc name)
681     {
682         Iterator fieldIterator = getFields().iterator();
683
684         while (fieldIterator.hasNext())
685         {
686             MappingFieldElement field =
687                 (MappingFieldElement)fieldIterator.next();
688
689             if (name.equals(field.getName()))
690                 return field;
691         }
692
693         return null;
694     }
695
696     /** Adds a field to the list of fields in this mapping class.
697      * @param field field element to be added
698      * @exception ModelException if impossible
699      */

700     public void addField (MappingFieldElement field) throws ModelException
701     {
702         ArrayList fields = getFields();
703
704         if (!fields.contains(field))
705         {
706             try
707             {
708                 fireVetoableChange(PROP_FIELDS, null, null);
709                 fields.add(field);
710                 firePropertyChange(PROP_FIELDS, null, null);
711             }
712             catch (PropertyVetoException JavaDoc e)
713             {
714                 throw new ModelVetoException(e);
715             }
716         }
717     }
718
719     /** Removes a field from the list of fields in this mapping class.
720      * @param field field element to be removed
721      * @exception ModelException if impossible
722      */

723     public void removeField (MappingFieldElement field) throws ModelException
724     {
725         try
726         {
727             fireVetoableChange(PROP_FIELDS, null, null);
728
729             if (!getFields().remove(field))
730             {
731                 throw new ModelException(I18NHelper.getMessage(getMessages(),
732                     "mapping.element.element_not_removed", field)); // NOI18N
733
}
734
735             firePropertyChange(PROP_FIELDS, null, null);
736         }
737         catch (PropertyVetoException JavaDoc e)
738         {
739             throw new ModelVetoException(e);
740         }
741     }
742
743     /** Returns the list of version fields (MappingFieldElements) in this
744      * mapping class. This list only includes fields if the consistency
745      * level is {@link #VERSION_CONSISTENCY}.
746      * @return the version fields in this mapping class
747      */

748     public List getVersionFields ()
749     {
750         List versionFields = new ArrayList();
751
752         if (VERSION_CONSISTENCY == getConsistencyLevel())
753         {
754             Iterator iterator = getFields().iterator();
755
756             while (iterator.hasNext())
757             {
758                 MappingFieldElement fieldCandidate =
759                     (MappingFieldElement)iterator.next();
760
761                 if (fieldCandidate.isVersion())
762                     versionFields.add(fieldCandidate);
763             }
764         }
765
766         return versionFields;
767     }
768
769     /** Gets the navigable flag for this mapping class.
770      * @return <code>true</code> if lazy initialization will be used,
771      * <code>false</code> if access to a non-fetched field will result in an
772      * exception. The default is <code>true</code>.
773      */

774     public boolean isNavigable () { return ((_properties & NAVIGABLE) > 0); }
775
776     /** Set the navigable flag for this mapping class to flag.
777      * @param flag if <code>true</code>, lazy initialization will be used;
778      * if <code>false</code>, access to a non-fetched field will result in an
779      * exception.
780      * @exception ModelException if impossible
781      */

782     public void setNavigable (boolean flag) throws ModelException
783     {
784         Boolean JavaDoc old = JavaTypeHelper.valueOf(isNavigable());
785         Boolean JavaDoc newFlag = JavaTypeHelper.valueOf(flag);
786
787         try
788         {
789             fireVetoableChange(PROP_NAVIGABLE, old, newFlag);
790             _properties = (flag) ?
791                 (_properties | NAVIGABLE) : (_properties & ~NAVIGABLE);
792             firePropertyChange(PROP_NAVIGABLE, old, newFlag);
793         }
794         catch (PropertyVetoException JavaDoc e)
795         {
796             throw new ModelVetoException(e);
797         }
798     }
799
800     //============= extra object support for runtime ========================
801

802     /** Accept an arraylist of column names and return an array list containing
803      * the corresponding column or column pair objects.
804      * @param schemaName the database root used to find the column objects
805      * @param columnNames array of column names.
806      * @return an array of corresponding column objects
807      * @see org.netbeans.modules.dbschema.TableElement#forName
808      * @see org.netbeans.modules.dbschema.TableElement#getMember
809      */

810     protected static ArrayList toColumnObjects (String JavaDoc schemaName,
811         ArrayList columnNames)
812     {
813         Iterator iterator = columnNames.iterator();
814         ArrayList objects = new ArrayList();
815
816         while (iterator.hasNext())
817         {
818             String JavaDoc columnName = (String JavaDoc)iterator.next();
819             String JavaDoc absoluteColumnName =
820                 NameUtil.getAbsoluteMemberName(schemaName, columnName);
821             final TableElement table =
822                 TableElement.forName(NameUtil.getTableName(absoluteColumnName));
823
824             objects.add(table.getMember(
825                 DBIdentifier.create(absoluteColumnName)));
826         }
827
828         return objects;
829     }
830
831     //============= delegation to PersistenceClassElement ===========
832

833     /** Get the fully qualified name of the primary key class for this class
834      * element. This value is only used if <code>getObjectIdentityType</code>
835      * returns <code>APPLICATION_IDENTITY</code>
836      * @return the fully qualified key class name, <code>null</code> if the
837      * identity type is not managed by the application
838      * @see PersistenceClassElement#setObjectIdentityType
839      * @see PersistenceClassElement#APPLICATION_IDENTITY
840      *
841      */

842     public String JavaDoc getKeyClass ()
843     {
844         return getPersistenceElement().getKeyClass();
845     }
846
847     //=============== extra set methods needed for xml archiver ==============
848

849     /** Set the list of tables (MappingTableElements) used by this mapping
850      * class. This method should only be used internally and for cloning
851      * and archiving.
852      * @param tables the list of meta data tables for this mapping class
853      */

854     //@olsen: disabled method because not used by archiver
855
/*
856     public void setTables (ArrayList tables) { _tables = tables; }
857 */

858
859     /** Set the list of fields (MappingFieldElements) in this mapping
860      * class. This method should only be used internally and for cloning
861      * and archiving.
862      * @param fields the list of mapping fields in this mapping class
863      */

864     public void setFields (ArrayList fields) { _fields = fields; }
865
866     public int getProperties () { return _properties; }
867
868     //======== to be used for reference in best guess implementation ==========
869
// configure methods
870

871     /**
872      * The following method attempts to map a field to a particular table.
873      * Only local fields are supported at present
874      * @return boolean to indicate whether the mapping worked
875      * @param fieldToMap The field to be mapped
876      * @param table The table the fields to to be mapped to
877      */

878 /* public boolean mapFieldToTable (MappingFieldElement fieldToMap,
879         TableElement table) throws ModelException
880     {
881         boolean lReturn = false;
882
883         if ((fieldToMap != null) && (fieldToMap instanceof MappingFieldElement))
884         {
885             String lLocalFieldName = fieldToMap.getName();
886             ColumnElement[] tableColumns = table.getColumns();
887             int i, count = ((tableColumns != null) ? tableColumns.length : 0);
888
889             for (i = 0; i < count; i++)
890             {
891                 ColumnElement lColumn = tableColumns[i];
892
893                 if (lLocalFieldName.equalsIgnoreCase(
894                     lColumn.getName().getFullName()))
895                 {
896                     PersistenceClassElement classElement =
897                         fieldToMap.getDeclaringClass().getClassElement();
898                     MappingFieldElement lLocalField =
899                         new MappingFieldElementImpl(
900                         classElement.getField(lLocalFieldName), fieldToMap);
901                     ArrayList columns = lLocalField.getColumns();
902
903                     // If this field has already been mapped we do not want to
904                     // overwrite the existing mapping as this mechanism
905                     // is an automagic mapping approach
906                     if ((columns != null) || (columns.size() != 0))
907                         lLocalField.addColumn(lColumn);
908
909                     lReturn = true;
910                     break;
911                 }
912             }
913         }
914
915         return lReturn;
916     }
917 */

918
919     //================== possibly for EJB use later ===========================
920
/**
921      * This method returns a finder class as a class type.
922      * @return The finder class used by this configuration
923      */

924     //public Class getFinderClass() { return finderClass; }
925

926     /**
927      * This method sets the finder class for this configuration.
928      * @param finderClass The finder class used by this configuration
929      */

930     /*public void setfinderClass(Class finderClass)
931     {
932         this.finderClass = finderClass;
933     }*/

934
935     /**
936      * This method gets the finder classes name.
937      * @return The finder classes name or if finder class not
938      * defined returns an empty string.
939      */

940     /* public String getFinderClassName()
941     {
942         String lFinderClassName = new String();
943         if ( this.finderClass != null )
944         {
945             lFinderClassName = this.finderClass.getName();
946         }
947
948         return lFinderClassName;
949     }*/

950
951     /**
952      * This method sets the finder class for this configuration based on the
953      * name passed in.
954      * @param finderclassName The finder classes name that this configuration
955      * should use.
956      */

957     /* public void setFinderClassName(String finderClassName)
958         throws ClassNotFoundException
959     {
960         this.finderClass = this.getClass().getClassLoader().
961             loadClass(finderClassName);
962     }*/

963     /*
964     public String getFinderClass() { return finderClass; }
965
966     public Class getFinderClassType() { return finderClassType; }
967     public void setFinderClassType(Class c) { finderClassType = c; }
968     */

969     /**
970      * The following method validates the finder class
971      * @param finderClassName The finder class name to be validated
972      */

973     /* public boolean vaidateFinderClass(String finderClassName)
974     {
975         boolean lValid = false;
976
977         if ( finderClassName == null || finderClassName.equals(""))
978             lValid = false;
979         else if ( finderClassName.equals(this.DEFAULT_JAVA_FINDERCLASS) )
980             lValid = true;
981         else
982         {
983             // NEED to do some kind of class lookup here although not sure how
984             // to do this in netbeans not sure if this is the right approach
985             // but as long as class path is correct it should work
986             ClassLoader lClassLoader = this.getClassLoader();
987
988             try
989             {
990                 lClassLoader.loadClass(finderClassName);
991             }
992             catch (ClassNotFoundException lError)
993             {
994                 lValid = false;
995             }
996         }
997         return lValid;
998     }
999
1000    public Class getBeanFactoryType() { return beanFactoryType; }
1001    public void setBeanFactoryType(Class c) { beanFactoryType = c; }
1002    */

1003    /**
1004     * The following method will return a list of all of the
1005     * foreign EJB's referenced in this persistent descriptor
1006     * @return The list of EJB's referenced by this configuration
1007     */

1008    /*public String[] getForeignEJBNames()
1009    {
1010        // Allocate a to the size of the number of elements
1011        // elements in the array list of fields as we can't
1012        // return a bigger array that that
1013        String[] lEJBNames = new String[field.size()];
1014        int i = 0, count = this.fields.size();
1015
1016        for (; i > count; i++)
1017        {
1018            MappingFieldElement lField = this.fields.get(i);
1019
1020            if ( lField instanceof MappingRelationshipElement )
1021            {
1022                // Ok this is a foreign field so get it's EJB name
1023                String lEJBName = (lField)
1024                    (MappingRelationshipElement).getEJBType();
1025
1026                if ((lEJBName != null) && (!lEJBName.equals("")))
1027                    lEJBNames[i] = new String(lEJBName);
1028            }
1029
1030            // allocate a new array and copy the old array into it before
1031            // returns the new array
1032            String[] lReturnArray = new String[i + 1];
1033            System.arraycopy(lEJBNames, 0, lReturnArray, 0, i + 1);
1034
1035            return lReturnArray;
1036        }
1037        }*/

1038
1039    /** This method is called after a MappingClassElement is unarchived
1040     * from a .mapping file. This method provides a hook to do any checking
1041     * (version number checking) and conversion after unarchiving.
1042     * @exception ModelException if impossible
1043     */

1044    public void postUnarchive () throws ModelException
1045    {
1046        // check version number
1047
switch (versionNo)
1048        {
1049            case 0: // outdated version number
1050
case 1: // outdated version number
1051
throw new ModelException (I18NHelper.getMessage(getMessages(),
1052                    "file.incompatible_version", getName())); //NOI18N
1053
case 2:
1054                // Boston format => convert to Pilsen format
1055
stripSchemaName();
1056                break;
1057            case 3: // same as 4 except package names are different
1058
case 4: // same as 5 except version field not a choice for MFE
1059
case MappingClassElementImpl.CURRENT_VERSION_NO:
1060                // OK
1061
break;
1062            default: // version number is unknown
1063
throw new ModelException (I18NHelper.getMessage(getMessages(),
1064                    "file.incompatible_version", getName())); //NOI18N
1065
}
1066    }
1067
1068    /** This method is called prior to storing a MappingClassElement in a
1069     * .mapping file. This method provides a hook to do any conversion
1070     * before archiving.
1071     * Note, the signature of preArchive in the interface MappingClassElement
1072     * includes a throws clause (ModelException), but the actual implementation
1073     * does not throw an exception.
1074     */

1075    public void preArchive ()
1076    {
1077        // update version number
1078
setVersionNumber(CURRENT_VERSION_NO);
1079    }
1080    
1081    //=============== extra method for Boston -> Pilsen conversion ============
1082

1083    /** Boston to Pilsen conversion.
1084     * This method converts the absolute db element names to relative names and
1085     * stores the database root (meaning the schema name) in the
1086     * MappingClassElement. The method is recursively called for all
1087     * MappingTableElements and MappingFieldElements attached to this
1088     * MappingClassElement.
1089     */

1090    protected void stripSchemaName ()
1091    {
1092        String JavaDoc schemaName = null;
1093
1094        // calculate schemaName from first MappingTableElement
1095
if (_tables != null && !_tables.isEmpty())
1096        {
1097            schemaName = NameUtil.getSchemaName(
1098                ((MappingTableElement)_tables.get(0)).getTable());
1099        }
1100
1101        // set the schemaName as database root
1102
_databaseRoot = schemaName;
1103
1104        // do not change the _isModified flag
1105

1106        // handle _tables
1107
if (_tables != null)
1108        {
1109            Iterator i = _tables.iterator();
1110            while (i.hasNext())
1111                ((MappingTableElementImpl)i.next()).stripSchemaName();
1112        }
1113        
1114        // handle _fields
1115
if (_fields != null)
1116        {
1117            Iterator i = _fields.iterator();
1118            while (i.hasNext())
1119                ((MappingFieldElementImpl)i.next()).stripSchemaName();
1120        }
1121    }
1122}
1123
Popular Tags