KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > genimen > djeneric > repository > DjExtent


1 /*
2  * Copyright (c) 2001-2005 by Genimen BV (www.genimen.com) All rights reserved.
3  * Redistribution and use in source and binary forms, with or without
4  * modification, is permitted provided that the following conditions are met: -
5  * Redistributions of source code must retain the above copyright notice, this
6  * list of conditions and the following disclaimer. - Redistributions in binary
7  * form must reproduce the above copyright notice, this list of conditions and
8  * the following disclaimer in the documentation and/or other materials
9  * provided with the distribution. - All advertising materials mentioning
10  * features or use of this software must display the following acknowledgment:
11  * "This product includes Djeneric." - Products derived from this software may
12  * not be called "Djeneric" nor may "Djeneric" appear in their names without
13  * prior written permission of Genimen BV. - Redistributions of any form
14  * whatsoever must retain the following acknowledgment: "This product includes
15  * Djeneric." THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND
16  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
17  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENIMEN BV,
19  * DJENERIC.ORG, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */

27 package com.genimen.djeneric.repository;
28
29 import java.util.ArrayList JavaDoc;
30 import java.util.Arrays JavaDoc;
31 import java.util.Collections JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.StringTokenizer JavaDoc;
35
36 import com.genimen.djeneric.language.Messages;
37 import com.genimen.djeneric.repository.exceptions.CatalogException;
38 import com.genimen.djeneric.repository.exceptions.DjenericException;
39 import com.genimen.djeneric.repository.exceptions.DomainViolationException;
40 import com.genimen.djeneric.repository.exceptions.ObjectNotDefinedException;
41 import com.genimen.djeneric.util.DjLogger;
42
43 /**
44  * An DjExtent defines the persistent structure for a specific type of {@link
45  * DjObject}. An DjExtent uses properties that define the type, length etc. for
46  * the properties to be persisted; so there is a direct correlation between a
47  * {@link com.genimen.djeneric.repository.DjProperty}and the properties of a
48  * DjObject.
49  *
50  * @author Wido Riezebos @created April 18, 2002
51  */

52
53 public abstract class DjExtent implements Cloneable JavaDoc, DjPropertyType
54 {
55   /**
56    * Returns true is no data is stored in the extent (in any context)
57    *
58    * @param session
59    * The session to use
60    * @return True when empty
61    * @exception DjenericException
62    * Description of the Exception
63    */

64   public abstract boolean isEmpty(DjSession session) throws DjenericException;
65
66   /**
67    * Returns a clone
68    *
69    * @return A clone
70    */

71   public abstract Object JavaDoc clone();
72
73   String JavaDoc _name;
74   String JavaDoc _descriptorExpression = "";
75   String JavaDoc _alias;
76   String JavaDoc _nameSingular;
77   String JavaDoc _namePlural;
78   String JavaDoc _title;
79   String JavaDoc _internalCode;
80   String JavaDoc _objectType;
81   String JavaDoc _description;
82   boolean _large = false;
83   boolean _transient = false;
84
85   DjExtent _super = null;
86
87   boolean _shouldUseAlias = true;
88   long _internalId;
89
90   ArrayList JavaDoc _personalProperties = new ArrayList JavaDoc();
91   ArrayList JavaDoc _specializations = new ArrayList JavaDoc();
92
93   HashMap JavaDoc _propertiesByName = new HashMap JavaDoc();
94   HashMap JavaDoc _propertiesByInternalId = new HashMap JavaDoc();
95   HashMap JavaDoc _indexesByName = new HashMap JavaDoc();
96   ArrayList JavaDoc _personalDetailRelations = new ArrayList JavaDoc();
97   ArrayList JavaDoc _personalMasterRelations = new ArrayList JavaDoc();
98   String JavaDoc[] _propertyNames = new String JavaDoc[0];
99   DjProperty[] _properties = new DjProperty[0];
100   DjPackage _package = null;
101
102   /**
103    * Constructs a new DjExtent object.
104    *
105    * @param objectType
106    * The type of object i.e. the class name of persistent objects
107    * stored in this DjExtent. Must be unique within the model
108    * @param name
109    * The name of the extent, used in select statements in the
110    * underlying model. Must be unique within the model
111    * @param alias
112    * The alias for the extent, used for various internal purposes.
113    * Must be unique within the model
114    * @param internalCode
115    * The code used to distinguish records of a specific type in the
116    * polymorph table. Must be unique within the model
117    * @param title
118    * The title to be used for display purposes
119    * @param nameSingular
120    * The name of the persistent object type, singular e.g. 'employee'
121    * @param namePlural
122    * The name of the persistent object type, plural e.g. 'employees'
123    */

124   public DjExtent(String JavaDoc objectType, String JavaDoc name, String JavaDoc alias, String JavaDoc internalCode, String JavaDoc title, String JavaDoc nameSingular,
125                   String JavaDoc namePlural)
126
127   {
128     _internalId = DjPersistenceManager.getNextInternalId();
129     _objectType = objectType;
130     _name = name;
131     _alias = alias;
132     _nameSingular = nameSingular;
133     _namePlural = namePlural;
134     _title = title;
135
136     _internalCode = internalCode;
137   }
138
139   public DjExtent resolveType(String JavaDoc instPath) throws ObjectNotDefinedException
140   {
141     if (instPath == null) return this;
142
143     int idx = instPath.indexOf(".");
144
145     String JavaDoc basePropName = instPath;
146     String JavaDoc restPath = null;
147     if (idx != -1)
148     {
149       basePropName = instPath.substring(0, idx);
150       restPath = instPath.substring(idx + 1);
151     }
152
153     if (hasProperty(basePropName))
154     {
155       DjProperty prop = getProperty(basePropName);
156       if (!(prop.getType() instanceof DjExtent)) throw new ObjectNotDefinedException(Messages
157           .getString("DjObject.PropertyInPathNotObject", basePropName));
158
159       return ((DjExtent) prop.getType()).resolveType(restPath);
160     }
161
162     DjRelation rel = getDetailRelation(basePropName);
163     return rel.getDetailExtent().resolveType(restPath);
164   }
165
166   /**
167    * Sets the super extent (use null for none)
168    *
169    * @param superExtent
170    * The new super
171    */

172   public void setSuper(DjExtent superExtent)
173   {
174     if (_super != null) _super.removeSpecialization(this);
175
176     if (superExtent != null)
177     {
178       DjProperty idprop = findPropertyByMapping(DjPersistenceManager.MAPPING_OBJECT_ID);
179       DjProperty superIdprop = superExtent.findPropertyByMapping(DjPersistenceManager.MAPPING_OBJECT_ID);
180       if (idprop != null && superIdprop != null)
181       {
182         removeProperty(idprop);
183       }
184       superExtent.addSpecialization(this);
185     }
186     _super = superExtent;
187
188     updateHashes();
189   }
190
191   /**
192    * Returns an array of indices to be used for sorting lists of objects that
193    * are stored in this extent. BEWARE: Use the absolute value of the indices
194    * when using the index to find a property: if sorting on a property is to be
195    * done in descending order the index of the property is negative
196    *
197    * @return The property sort indices
198    */

199   public int[] getPropertySortIndices()
200   {
201     DjProperty[] props = getProperties();
202     ArrayList JavaDoc lst = new ArrayList JavaDoc();
203     for (int i = 0; i < props.length; i++)
204     {
205       if (props[i].getSortOrder() != 0) lst.add(props[i]);
206     }
207     Collections.sort(lst, new PropertySortOrderComparator());
208     int[] result = new int[lst.size()];
209
210     try
211     {
212       for (int i = 0; i < lst.size(); i++)
213       {
214         result[i] = getPropertyIndex(((DjProperty) lst.get(i)).getName());
215         if (((DjProperty) lst.get(i)).getSortOrder() < 0) result[i] = -result[i];
216       }
217     }
218     catch (ObjectNotDefinedException onde)
219     {
220       // This is impossible since the property was just retrieved from the
221
// extent
222
DjLogger.log(onde);
223     }
224     return result;
225   }
226
227   private void addSpecialization(DjExtent sub)
228   {
229     _specializations.add(sub);
230   }
231
232   private void removeSpecialization(DjExtent sub)
233   {
234     _specializations.remove(sub);
235   }
236
237   /**
238    * Returns true if this extent is part of an inheritance chain (up /
239    * downwards)
240    *
241    * @return True if this extent is part of an inheritance chain
242    */

243   public boolean isPartOfInheritanceChain()
244   {
245     return (getSuper() != null) || (getSpecializations().length > 0);
246   }
247
248   /**
249    * Returns true if the provided extent is a super (direct or indirect) of
250    * this extent
251    *
252    * @param someType
253    * The type of match
254    * @return The instanceof value
255    */

256   public boolean isInstanceof(DjExtent someType)
257   {
258     if (someType == this) return true;
259
260     if (someType == null) return false;
261
262     if (getSuper() != null) return getSuper().isInstanceof(someType);
263     return false;
264   }
265
266   public boolean isInstanceof(String JavaDoc objectTypeName)
267   {
268     if (getObjectType().equals(objectTypeName)) return true;
269     if (getQualifiedObjectType().equals(objectTypeName)) return true;
270
271     if (getSuper() != null) return getSuper().isInstanceof(objectTypeName);
272
273     return false;
274   }
275
276   /**
277    * Returns the direct specializations of this extent
278    *
279    * @return The specializations
280    */

281   public DjExtent[] getSpecializations()
282   {
283     return (DjExtent[]) _specializations.toArray(new DjExtent[0]);
284   }
285
286   /**
287    * Returns the direct and indirect specializations of this extent
288    *
289    * @return The allSpecializations value
290    */

291   public DjExtent[] getAllSpecializations()
292   {
293     ArrayList JavaDoc result = new ArrayList JavaDoc();
294     DjExtent[] children = getSpecializations();
295     for (int i = 0; i < children.length; i++)
296       result.add(children[i]);
297
298     for (int i = 0; i < children.length; i++)
299     {
300       DjExtent[] specs = children[i].getAllSpecializations();
301       for (int j = 0; j < specs.length; j++)
302         result.add(specs[j]);
303     }
304
305     return (DjExtent[]) result.toArray(new DjExtent[0]);
306   }
307
308   /**
309    * Returns the super this extent. Null if there is no super
310    *
311    * @return The super
312    */

313   public DjExtent getSuper()
314   {
315     return _super;
316   }
317
318   /**
319    * Returns the class name of the {@link DjObject}that is stored by this
320    * extent Used primarily if this DjExtent is in fact used as the type for a
321    * {@link DjProperty}
322    *
323    * @return The typeName value
324    */

325   public String JavaDoc getTypeName()
326   {
327     return _objectType;
328   }
329
330   public String JavaDoc getTypeClassName()
331   {
332     return getQualifiedObjectType();
333   }
334
335   /**
336    * Returns the nativeType of the DjExtent object for use in the persistent
337    * store: long
338    *
339    * @return The nativeType value
340    */

341   public String JavaDoc getNativeType()
342   {
343     return "long";
344   }
345
346   /**
347    * Returns the {@link DjDomain}type code for a long (DjDomain.LONG_TYPE),
348    * the internal type of the object id for a {@link DjObject}Used primarily
349    * if this DjExtent is in fact used as the type for a {@link DjProperty}
350    *
351    * @return The typeCode value
352    */

353   public int getTypeCode()
354   {
355     return DjDomain.LONG_TYPE;
356   }
357
358   /**
359    * Returns the length of the internal type of the object id for a {@link
360    * DjObject} Used primarily if this DjExtent is in fact used as the type for
361    * a {@link DjProperty}
362    *
363    * @return The length value
364    */

365   public int getLength()
366   {
367     return DjPersistenceManager.MAPPING_ID_COLUMN_SIZE;
368   }
369
370   /**
371    * Returns the 0 for the number of decimals. Used primarily if this DjExtent
372    * is in fact used as the type for a {@link DjProperty}
373    *
374    * @return The decimals value
375    */

376   public int getDecimals()
377   {
378     return 0;
379   }
380
381   /**
382    * Returns an empty String; currently a format mask is not supported for
383    * tables.
384    *
385    * @return The formatMask value
386    */

387   public String JavaDoc getFormatMask()
388   {
389     return "";
390   }
391
392   /**
393    * Sets the description for this extent, this is a technical description
394    * concerning the role of this extent in the model
395    *
396    * @param descr
397    * The new description value
398    */

399   public void setDescription(String JavaDoc descr)
400   {
401     _description = descr;
402   }
403
404   /**
405    * Returns the description for this extent, this is a technical description
406    * concerning the role of this extent in the model
407    *
408    * @return The description value
409    */

410   public String JavaDoc getDescription()
411   {
412     return _description;
413   }
414
415   /**
416    * Gets the expression used to construct the descriptive title for objects
417    * when show in a list etc.
418    *
419    * @return The descriptorExpression value
420    */

421   public String JavaDoc getDescriptorExpression()
422   {
423     if (_descriptorExpression.length() != 0) return _descriptorExpression;
424     if (getSuper() != null) return getSuper().getDescriptorExpression();
425
426     return "";
427   }
428
429   /**
430    * Returns the personalDescriptorExpression of the DjExtent object
431    *
432    * @return The personalDescriptorExpression value
433    */

434   public String JavaDoc getPersonalDescriptorExpression()
435   {
436     return _descriptorExpression;
437   }
438
439   /**
440    * Sets the expression used to construct the descriptive title for objects
441    * when show in a list etc. The expression is of the form
442    * (property(.property)* [+ property(.property)* | "constant text"])* for
443    * example "Mr " + person.name + "." is a valid expression
444    *
445    * @param expr
446    * The new descriptor expression
447    */

448   public void setDescriptorExpression(String JavaDoc expr)
449   {
450     if (expr == null) expr = "";
451     if (getSuper() != null && getSuper().getDescriptorExpression().equals(expr)) expr = "";
452
453     _descriptorExpression = expr;
454   }
455
456   /**
457    * Various hashes are used to speedup the search for properties by name or
458    * index. These hashes need to be updated if a property is modified or added;
459    * you can do this by calling this method
460    */

461   public void updateHashes()
462   {
463     ArrayList JavaDoc props = getPropertiesList();
464
465     _propertiesByName = new HashMap JavaDoc();
466     _indexesByName = new HashMap JavaDoc();
467     _propertiesByInternalId = new HashMap JavaDoc();
468     _properties = (DjProperty[]) props.toArray(new DjProperty[0]);
469     _propertyNames = new String JavaDoc[props.size()];
470
471     for (int i = 0; i < _properties.length; i++)
472     {
473       _propertyNames[i] = _properties[i].getName();
474       _propertiesByName.put(_propertyNames[i], _properties[i]);
475       _indexesByName.put(_propertyNames[i], new Integer JavaDoc(i));
476       _propertiesByInternalId.put(new Long JavaDoc(_properties[i].getInternalId()), _properties[i]);
477     }
478   }
479
480   /**
481    * Clears all properties, hashes and relations. Used by {@link #copyInto}
482    */

483   private void resetInternalData()
484   {
485     _personalProperties = new ArrayList JavaDoc();
486     _propertiesByName = new HashMap JavaDoc();
487     _propertiesByInternalId = new HashMap JavaDoc();
488     _indexesByName = new HashMap JavaDoc();
489     _personalDetailRelations = new ArrayList JavaDoc();
490     _personalMasterRelations = new ArrayList JavaDoc();
491     _propertyNames = new String JavaDoc[0];
492     _properties = new DjProperty[0];
493   }
494
495   /**
496    * Copies the entire state (deep copy) of this extent into the extent
497    * provided by parameter destinationExtent
498    *
499    * @param destinationExtent
500    * The destination extent
501    * @exception DjenericException
502    * Description of the Exception
503    */

504   public void copyInto(DjExtent destinationExtent) throws DjenericException
505   {
506     destinationExtent.resetInternalData();
507     copyPropertiesInto(destinationExtent);
508   }
509
510   /**
511    * Copies the entire state (deep copy) of this extent into the extent
512    * provided by parameter destinationExtent; WITHOUT removing the original
513    * data in the destination extent.
514    *
515    * @param nt
516    * destination extent
517    * @exception DjenericException
518    * Description of the Exception
519    */

520   protected void copyPropertiesInto(DjExtent nt) throws DjenericException
521   {
522     nt.setAlias(getAlias());
523     nt.setInternalCode(getInternalCode());
524     nt.setDescriptorExpression(getDescriptorExpression());
525     nt.setName(getName());
526     nt.setNamePlural(getNamePlural());
527     nt.setNameSingular(getNameSingular());
528     nt.setObjectType(getObjectType());
529     nt.setShouldUseAlias(_shouldUseAlias);
530     nt.setTitle(getTitle());
531     nt.setDescription(getDescription());
532     nt.setSuper(getSuper());
533     nt._specializations.addAll(_specializations);
534     nt._large = _large;
535     nt._transient = _transient;
536     nt._package = _package;
537
538     for (int i = 0; i < _personalProperties.size(); i++)
539     {
540       DjProperty org = (DjProperty) _personalProperties.get(i);
541       DjProperty prop = (DjProperty) org.clone();
542       try
543       {
544         nt.addProperty(prop);
545       }
546       catch (Exception JavaDoc x)
547       {
548         throw new DjenericException(x);
549       }
550     }
551
552     DjRelation[] rels = getPersonalDetailRelations();
553     for (int i = 0; i < rels.length; i++)
554     {
555       DjRelation rel = (DjRelation) rels[i].clone();
556       rel.setMasterExtent(nt);
557       nt.addDetailRelation(rel);
558     }
559
560     rels = getPersonalMasterRelations();
561     for (int i = 0; i < rels.length; i++)
562     {
563       DjRelation rel = (DjRelation) rels[i].clone();
564       rel.setDetailExtent(nt);
565       nt.addMasterRelation(rel);
566     }
567
568   }
569
570   /**
571    * Adds a {@link DjRelation}as a detail relation to this extent. This method
572    * does not automatically update the other end (i.e. it does not add the
573    * relation as a master relation to the detail) This is necessary because
574    * update operations on this extent might be discarded later by simply
575    * discarding this extent. In that case there can be no side effects caused
576    * by updating the master here. This is typically the case when editing the
577    * model with a model editor.
578    *
579    * @param d
580    * The feature to be added to the DetailRelation attribute
581    */

582   public void addDetailRelation(DjRelation d)
583   {
584     _personalDetailRelations.add(d);
585   }
586
587   /**
588    * Removes a {@link DjRelation}as a detail relation from this extent. This
589    * method does not automatically update the other end (i.e. it does not
590    * remove the relation from the detail's 'master relation list') This is
591    * necessary because update operations on this extent might be discarded
592    * later by simply discarding this extent. In that case there can be no side
593    * effects caused by updating the master here. This is typically the case
594    * when editing the model with a model editor.
595    *
596    * @param d
597    * The relation to be removed
598    */

599   public void removeDetailRelation(DjRelation d)
600   {
601     _personalDetailRelations.remove(d);
602   }
603
604   /**
605    * Description of the Method
606    */

607   public void removeAllDetailRelations()
608   {
609     _personalDetailRelations.clear();
610   }
611
612   /**
613    * Adds a {@link DjRelation}as a master relation to this extent. This method
614    * does not automatically update the other end (i.e. it does not add the
615    * relation as a detail relation to the master) This is necessary because
616    * update operations on this extent might be discarded later by simply
617    * discarding this extent. In that case there can be no side effects caused
618    * by updating the detail here. This is typically the case when editing the
619    * model with a model editor.
620    *
621    * @param d
622    * The feature to be added to the MasterRelation attribute
623    */

624   public void addMasterRelation(DjRelation d)
625   {
626     _personalMasterRelations.add(d);
627   }
628
629   /**
630    * Removes a {@link DjRelation}as a master relation from this extent. This
631    * method does not automatically update the other end (i.e. it does not
632    * remove the relation from the master's 'detail relation list') This is
633    * necessary because update operations on this extent might be discarded
634    * later by simply discarding this extent. In that case there can be no side
635    * effects caused by updating the master here. This is typically the case
636    * when editing the model with a model editor.
637    *
638    * @param d
639    * The relation to be removed
640    */

641   public void removeMasterRelation(DjRelation d)
642   {
643     _personalMasterRelations.remove(d);
644   }
645
646   /**
647    * Returns the detail {@link DjRelation}indexed by idx (zero based)
648    *
649    * @param idx
650    * The index of the relation
651    * @return The detailRelation value
652    */

653   public DjRelation getDetailRelation(int idx)
654   {
655     return getDetailRelations()[idx];
656   }
657
658   /**
659    * Returns the detail {@link DjRelation}named by name
660    *
661    * @param name
662    * The name of the relation
663    * @return The detail relation
664    * @exception ObjectNotDefinedException
665    * Description of the Exception
666    */

667   public DjRelation getDetailRelation(String JavaDoc name) throws ObjectNotDefinedException
668   {
669     DjRelation[] rels = getDetailRelations();
670     for (int i = 0; i < rels.length; i++)
671     {
672       if (rels[i].getName().equals(name)) return rels[i];
673     }
674     throw new ObjectNotDefinedException(Messages.getString("DjExtent.RelationNotDefined", name, getName()));
675   }
676
677   /**
678    * Returns an array of {@link DjRelation}containing all the detail relations
679    * (relations to detail tables). If there are no detail relations an empty
680    * array is returned
681    *
682    * @return The detailRelations value
683    */

684   public DjRelation[] getDetailRelations()
685   {
686     return (DjRelation[]) getDetailRelationsAsArrayList().toArray(new DjRelation[0]);
687   }
688
689   /**
690    * Returns the personalDetailRelations of the DjExtent object
691    *
692    * @return The personalDetailRelations value
693    */

694   public DjRelation[] getPersonalDetailRelations()
695   {
696     return (DjRelation[]) _personalDetailRelations.toArray(new DjRelation[0]);
697   }
698
699   /**
700    * Returns the detailRelationsAsArrayList of the DjExtent object
701    *
702    * @return The detailRelationsAsArrayList value
703    */

704   protected ArrayList JavaDoc getDetailRelationsAsArrayList()
705   {
706     if (_super == null) return _personalDetailRelations;
707     ArrayList JavaDoc all = new ArrayList JavaDoc();
708     all.addAll(_super.getDetailRelationsAsArrayList());
709     all.addAll(_personalDetailRelations);
710     return all;
711   }
712
713   /**
714    * Returns the number of detail relations (relations to a detail extent) for
715    * this extent
716    *
717    * @return The detailRelationCount value
718    */

719   public int getDetailRelationCount()
720   {
721     int length = 0;
722     if (_super != null) length = _super.getDetailRelationCount();
723     length += _personalDetailRelations.size();
724     return length;
725   }
726
727   /**
728    * Returns an array of {@link DjRelation}containing all the master
729    * relations. If there are no master relations an empty array is returned
730    *
731    * @return The masterRelations value
732    */

733   public DjRelation[] getMasterRelations()
734   {
735     return (DjRelation[]) getMasterRelationsAsArrayList().toArray(new DjRelation[0]);
736   }
737
738   /**
739    * Returns the personalMasterRelations of the DjExtent object
740    *
741    * @return The personalMasterRelations value
742    */

743   public DjRelation[] getPersonalMasterRelations()
744   {
745     return (DjRelation[]) _personalMasterRelations.toArray(new DjRelation[0]);
746   }
747
748   /**
749    * Returns the masterRelationsAsArrayList of the DjExtent object
750    *
751    * @return The masterRelationsAsArrayList value
752    */

753   protected ArrayList JavaDoc getMasterRelationsAsArrayList()
754   {
755     if (_super == null) return _personalMasterRelations;
756     ArrayList JavaDoc all = new ArrayList JavaDoc();
757     all.addAll(_super.getMasterRelationsAsArrayList());
758     all.addAll(_personalMasterRelations);
759     return all;
760   }
761
762   /**
763    * Returns the number of master relations for this extent
764    *
765    * @return The masterRelationCount value
766    */

767   public int getMasterRelationCount()
768   {
769     int length = 0;
770     if (_super != null) length = _super.getMasterRelationCount();
771     length += _personalMasterRelations.size();
772     return length;
773   }
774
775   /**
776    * Returns the masterRelationByPropertyName of the DjExtent object
777    *
778    * @param propertyName
779    * the name of the property that is in fact the reference to the
780    * master object
781    * @return The masterRelationByPropertyName value
782    */

783   public DjRelation getMasterRelationByPropertyName(String JavaDoc propertyName)
784   {
785     DjRelation[] masters = getMasterRelations();
786     for (int i = 0; i < masters.length; i++)
787     {
788       if (masters[i].getDetailProperty() != null)
789       {
790         if (masters[i].getDetailProperty().getName().equals(propertyName))
791         {
792           return masters[i];
793         }
794       }
795     }
796     return null;
797   }
798
799   public DjRelation getMasterRelationByInternalId(long internalId)
800   {
801     DjRelation[] masters = getMasterRelations();
802     for (int i = 0; i < masters.length; i++)
803     {
804       if (masters[i].getInternalId() == internalId) return masters[i];
805     }
806     return null;
807   }
808
809   /**
810    * Returns the master {@link DjRelation}indexed by idx (zero based)
811    *
812    * @param idx
813    * The index of the master relation
814    * @return The masterRelation value
815    */

816   public DjRelation getMasterRelation(int idx)
817   {
818     return getMasterRelations()[idx];
819   }
820
821   /**
822    * Returns the type (class name) of objects stored in this extent
823    *
824    * @return The objectType value
825    */

826   public String JavaDoc getObjectType()
827   {
828     return _objectType;
829   }
830
831   public String JavaDoc getQualifiedObjectType()
832   {
833     if (getPackage() == null) return getObjectType();
834     return getPackage().getName() + "." + getObjectType();
835   }
836
837   public String JavaDoc getQualifiedExtentName()
838   {
839     if (getPackage() == null) return getName();
840     return getPackage().getName() + "." + getName();
841   }
842
843   /**
844    * Sets the type (class name) of objects stored in this extent
845    *
846    * @param objectType
847    * The new objectType value
848    */

849   public void setObjectType(String JavaDoc objectType)
850   {
851     _objectType = objectType;
852   }
853
854   /**
855    * Returns the name of the extent
856    *
857    * @return The name value
858    */

859   public String JavaDoc getName()
860   {
861     return _name;
862   }
863
864   /**
865    * Sets the name of the extent
866    *
867    * @param name
868    * The new name value
869    */

870   public void setName(String JavaDoc name)
871   {
872     _name = name;
873   }
874
875   /**
876    * Returns the title/prompt to be used when referring to this extent in a
877    * singular context. E.g. "employee"
878    *
879    * @return The nameSingular value
880    */

881   public String JavaDoc getNameSingular()
882   {
883     return _nameSingular;
884   }
885
886   /**
887    * Sets the title/prompt to be used when referring to this extent in a
888    * singular context. E.g. "employee"
889    *
890    * @param nameSingular
891    * The new nameSingular value
892    */

893   public void setNameSingular(String JavaDoc nameSingular)
894   {
895     _nameSingular = nameSingular;
896   }
897
898   /**
899    * Returns the title/prompt to be used when referring to this extent in a
900    * plural context. E.g. "employees"
901    *
902    * @return The namePlural value
903    */

904   public String JavaDoc getNamePlural()
905   {
906     return _namePlural;
907   }
908
909   /**
910    * Sets the title/prompt to be used when referring to this extent in a plural
911    * context. E.g. "employees"
912    *
913    * @param namePlural
914    * The new namePlural value
915    */

916   public void setNamePlural(String JavaDoc namePlural)
917   {
918     _namePlural = namePlural;
919   }
920
921   /**
922    * Returns the title to be used when referring to this extent for use in
923    * screens or reports E.g. "Employees"
924    *
925    * @return The title value
926    */

927   public String JavaDoc getTitle()
928   {
929     return _title;
930   }
931
932   /**
933    * Sets the title to be used when referring to this extent for use in screens
934    * or reports E.g. "Employees"
935    *
936    * @param title
937    * The new title value
938    */

939   public void setTitle(String JavaDoc title)
940   {
941     _title = title;
942   }
943
944   /**
945    * Returns the alias to be used when referring to this extent E.g. "empl"
946    *
947    * @return The alias value
948    */

949   public String JavaDoc getAlias()
950   {
951     return _alias;
952   }
953
954   /**
955    * Sets the alias to be used when referring to this extent E.g. "empl"
956    *
957    * @param alias
958    * The new alias value
959    */

960   public void setAlias(String JavaDoc alias)
961   {
962     _alias = alias;
963   }
964
965   /**
966    * For internal use of SqlXlator; to indicate wheter or not a extent
967    * is referred to using an alias in a parsed sql statement
968    *
969    * @return Description of the Return Value
970    */

971   boolean shouldUseAlias()
972   {
973     return _shouldUseAlias;
974   }
975
976   /**
977    * For internal use of SqlXlator; to indicate wheter or not a extent
978    * is referred to using an alias in a parsed sql statement
979    *
980    * @param b
981    * The new shouldUseAlias value
982    */

983   void setShouldUseAlias(boolean b)
984   {
985     _shouldUseAlias = b;
986   }
987
988   /**
989    * Returns the string that is used to identify a record type in the internal
990    * Polymorph extent E.g. "emp"
991    *
992    * @return The internalCode value
993    */

994   public String JavaDoc getInternalCode()
995   {
996     return _internalCode;
997   }
998
999   /**
1000   * Sets the string that is used to identify a record type in the internal
1001   * Polymorph table BEWARE: If there are records in the Polymorph table for
1002   * this record type, changing the internal code results in hiding these
1003   * records! E.g. "emp"
1004   *
1005   * @param internalCode
1006   * The new internalCode value
1007   */

1008  public void setInternalCode(String JavaDoc internalCode)
1009  {
1010    _internalCode = internalCode;
1011  }
1012
1013  /**
1014   * Adds a property definition to this extent. DjProperty names must be unique
1015   * within a extent, if a property name is not unique a {@link
1016   * CatalogException} is thrown
1017   *
1018   * @param prop
1019   * The feature to be added to the Property attribute
1020   * @exception CatalogException
1021   * Description of the Exception
1022   */

1023  public void addProperty(DjProperty prop) throws CatalogException
1024  {
1025    String JavaDoc key = prop.getName().toLowerCase();
1026
1027    if (_propertiesByName.containsKey(key))
1028    {
1029      throw new CatalogException(Messages.getString("DjExtent.PropertyMultiple", prop.getName(), _name));
1030    }
1031    prop.setExtent(this);
1032    _personalProperties.add(prop);
1033
1034    updateHashes();
1035  }
1036
1037  /**
1038   * Removes a specific property from the extent
1039   *
1040   * @param prop
1041   * The property to be removed
1042   */

1043  public void removeProperty(DjProperty prop)
1044  {
1045    _personalProperties.remove(prop);
1046    updateHashes();
1047  }
1048
1049  /**
1050   * Returns the number of properties in this extent
1051   *
1052   * @return The propertyCount value
1053   */

1054  public int getPropertyCount()
1055  {
1056    return _propertyNames.length;
1057  }
1058
1059  /**
1060   * Returns the name of the property indexed by idx (zero based)
1061   *
1062