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   * @param idx
1063   * The index of the property
1064   * @return The property name
1065   */

1066  public String JavaDoc getPropertyName(int idx)
1067  {
1068    return _propertyNames[idx];
1069  }
1070
1071  /**
1072   * Returns the property indexed by idx (zero based)
1073   *
1074   * @param idx
1075   * The index of the property
1076   * @return The property value
1077   */

1078  public DjProperty getProperty(int idx)
1079  {
1080    return _properties[idx];
1081  }
1082
1083  /**
1084   * Returns the property identified by it's own internal ID (every property
1085   * has it's own unique internal ID; this ID is only guaranteed to be the same
1086   * during the life of a specific {@link DjPersistenceManager}instance
1087   *
1088   * @param id
1089   * The internal id of the property
1090   * @return The property
1091   * @exception ObjectNotDefinedException
1092   * Description of the Exception
1093   */

1094  public DjProperty getPropertyByInternalId(long id) throws ObjectNotDefinedException
1095  {
1096    DjProperty prop = (DjProperty) _propertiesByInternalId.get(new Long JavaDoc(id));
1097    if (prop != null) return prop;
1098    throw new ObjectNotDefinedException(Messages.getString("DjExtent.InternalNotFound", String.valueOf(id)));
1099  }
1100
1101  /**
1102   * Returns the internalId of the DjExtent object
1103   *
1104   * @return The internalId value
1105   */

1106  protected long getInternalId()
1107  {
1108    return _internalId;
1109  }
1110
1111  /**
1112   * Sets the internalId of the DjExtent object
1113   *
1114   * @param internalId
1115   * The new internalId value
1116   */

1117  protected void setInternalId(long internalId)
1118  {
1119    _internalId = internalId;
1120  }
1121
1122  /**
1123   * Returns an array of property names
1124   *
1125   * @return The propertyNames value
1126   */

1127  public String JavaDoc[] getPropertyNames()
1128  {
1129    return _propertyNames;
1130  }
1131
1132  /**
1133   * Returns the index of a property identified by it's name
1134   *
1135   * @param propName
1136   * The name of the property
1137   * @return The index of the property
1138   * @exception ObjectNotDefinedException
1139   * Description of the Exception
1140   */

1141  public int getPropertyIndex(String JavaDoc propName) throws ObjectNotDefinedException
1142  {
1143    Integer JavaDoc itg = (Integer JavaDoc) _indexesByName.get(propName);
1144    if (itg != null) return itg.intValue();
1145
1146    throw new ObjectNotDefinedException(Messages.getString("DjExtent.NamedPropNotFound", propName, _name));
1147  }
1148
1149  /**
1150   * Returns the property identified by it's name Names are case insensitive
1151   *
1152   * @param name
1153   * The name of the property
1154   * @return The property
1155   * @exception ObjectNotDefinedException
1156   * Description of the Exception
1157   */

1158  public DjProperty getProperty(String JavaDoc propName) throws ObjectNotDefinedException
1159  {
1160    int idx = propName.lastIndexOf(".");
1161    if (idx == -1) return doGetProperty(propName);
1162
1163    String JavaDoc instPath = propName.substring(0, idx);
1164    propName = propName.substring(idx + 1);
1165    return resolveType(instPath).doGetProperty(propName);
1166  }
1167
1168  private DjProperty doGetProperty(String JavaDoc propName) throws ObjectNotDefinedException
1169  {
1170    DjProperty prop = (DjProperty) _propertiesByName.get(propName);
1171    if (prop == null) throw new ObjectNotDefinedException(Messages.getString("DjExtent.NamedPropNotFound", propName,
1172                                                                             _name));
1173    return prop;
1174  }
1175
1176  /**
1177   * Returns the property identified by it's mapping (i.e. the column that
1178   * actually stores the data in the Polymorph table: str01, num04 etc.)
1179   *
1180   * @param name
1181   * The name of the mapping
1182   * @return The propertyByMapping value
1183   * @exception ObjectNotDefinedException
1184   * Thrown if the property is not found
1185   */

1186  public DjProperty getPropertyByMapping(String JavaDoc mapName) throws ObjectNotDefinedException
1187  {
1188    DjProperty prop = findPropertyByMapping(mapName);
1189    if (prop == null) throw new ObjectNotDefinedException(Messages.getString("DjExtent.MapNotFound", mapName, _name));
1190    return prop;
1191  }
1192
1193  /**
1194   * Returns the property identified by it's mapping (i.e. the column that
1195   * actually stores the data in the Polymorph table: str01, num04 etc.)
1196   *
1197   * @param name
1198   * The name of the mapping
1199   * @return The propertyByMapping value
1200   */

1201  public DjProperty findPropertyByMapping(String JavaDoc mapName)
1202  {
1203    Iterator JavaDoc it = _propertiesByName.values().iterator();
1204    while (it.hasNext())
1205    {
1206      DjProperty prop = (DjProperty) it.next();
1207      if (prop.getMapping().equalsIgnoreCase(mapName)) return prop;
1208    }
1209    return null;
1210  }
1211
1212  /**
1213   * Returns an array of properties for this extent
1214   *
1215   * @return The properties value
1216   */

1217  public DjProperty[] getProperties()
1218  {
1219    return _properties;
1220  }
1221
1222  /**
1223   * Returns an array of properties for this extent
1224   *
1225   * @return The personalProperties value
1226   */

1227  public DjProperty[] getPersonalProperties()
1228  {
1229    DjProperty[] result = (DjProperty[]) _personalProperties.toArray(new DjProperty[0]);
1230    Arrays.sort(result, new PropertyComparator());
1231    return result;
1232  }
1233
1234  /**
1235   * Returns the list of properties of this extent
1236   *
1237   * @return The propertiesList value
1238   */

1239  public ArrayList JavaDoc getPropertiesList()
1240  {
1241    ArrayList JavaDoc result = new ArrayList JavaDoc();
1242    if (_super != null) result.addAll(_super.getPropertiesList());
1243    result.addAll(_personalProperties);
1244    return result;
1245  }
1246
1247  /**
1248   * Returns true if the property is inherited from a super extent
1249   *
1250   * @param prop
1251   * The property to check
1252   * @return True if the property is inherited from a super extent
1253   */

1254  public boolean isInherited(DjProperty prop)
1255  {
1256    return !_personalProperties.contains(prop);
1257  }
1258
1259  /**
1260   * Returns true if the relation is inherited from a super extent
1261   *
1262   * @param rel
1263   * The relation to check
1264   * @return True if the relation is inherited from a super extent
1265   */

1266  public boolean isInherited(DjRelation rel)
1267  {
1268    return !_personalDetailRelations.contains(rel) && !_personalMasterRelations.contains(rel);
1269  }
1270
1271  /**
1272   * Returns an array of properties for this extent, sorted in ascending order
1273   * by their name
1274   *
1275   * @return The propertiesSorted value
1276   */

1277  public DjProperty[] getPropertiesSorted()
1278  {
1279    Iterator JavaDoc it = _propertiesByName.values().iterator();
1280    ArrayList JavaDoc v = new ArrayList JavaDoc();
1281    while (it.hasNext())
1282    {
1283      v.add(it.next());
1284    }
1285
1286    Collections.sort(v, new PropertyComparator());
1287    return (DjProperty[]) v.toArray(new DjProperty[0]);
1288  }
1289
1290  /**
1291   * Sorts the properties by their name. Be very careful with this one! It
1292   * changes the indexes for get/setProperty(int idx)
1293   */

1294  public void sortProperties()
1295  {
1296    Collections.sort(_personalProperties, new PropertyComparator());
1297    updateHashes();
1298  }
1299
1300  /**
1301   * Returns a string that lists all properties, separated by new lines
1302   *
1303   * @return The propertyListString value
1304   */

1305  public String JavaDoc getPropertyListString()
1306  {
1307    StringBuffer JavaDoc result = new StringBuffer JavaDoc(100);
1308
1309    Iterator JavaDoc it = _propertiesByName.values().iterator();
1310    while (it.hasNext())
1311    {
1312      Object JavaDoc o = it.next();
1313      result.append(((DjProperty) o).getName());
1314      if (it.hasNext()) result.append(",\n");
1315    }
1316    return result.toString();
1317  }
1318
1319  /**
1320   * Returns true if there is a property name by parameter propertyName. Names
1321   * are case insensitive
1322   *
1323   * @param propertyName
1324   * Description of the Parameter
1325   * @return Description of the Return Value
1326   */

1327  public boolean hasProperty(String JavaDoc propertyName)
1328  {
1329    return _propertiesByName.containsKey(propertyName);
1330  }
1331
1332  /**
1333   * Returns true if there is a property with internal ID internalID
1334   *
1335   * @param internalId
1336   * Description of the Parameter
1337   * @return Description of the Return Value
1338   */

1339  public boolean hasProperty(long internalId)
1340  {
1341    for (int i = 0; i < getPropertyCount(); i++)
1342    {
1343      if (getProperty(i).getInternalId() == internalId) return true;
1344    }
1345    return false;
1346  }
1347
1348  /**
1349   * Returns true if there is a {@link DjRelation}name relationName
1350   *
1351   * @param relationName
1352   * Description of the Parameter
1353   * @return Description of the Return Value
1354   */

1355  public boolean hasRelation(String JavaDoc relationName)
1356  {
1357    return hasDetailRelation(relationName) || hasMasterRelation(relationName);
1358  }
1359
1360  public boolean hasDetailRelation(String JavaDoc relationName)
1361  {
1362    for (int i = 0; i < getDetailRelationCount(); i++)
1363    {
1364      if (getDetailRelation(i).getName().equalsIgnoreCase(relationName)) return true;
1365    }
1366    return false;
1367  }
1368
1369  public boolean hasMasterRelation(String JavaDoc relationName)
1370  {
1371    for (int i = 0; i < getMasterRelationCount(); i++)
1372    {
1373      if (getMasterRelation(i).getName().equalsIgnoreCase(relationName)) return true;
1374    }
1375    return false;
1376  }
1377
1378  public boolean hasRelation(String JavaDoc relationName, DjExtent otherEnd)
1379  {
1380    for (int i = 0; i < getDetailRelationCount(); i++)
1381    {
1382      if (getDetailRelation(i).getName().equalsIgnoreCase(relationName)
1383          && getDetailRelation(i).getDetailExtent() == otherEnd) return true;
1384    }
1385    for (int i = 0; i < getMasterRelationCount(); i++)
1386    {
1387      if (getMasterRelation(i).getName().equalsIgnoreCase(relationName)
1388          && getMasterRelation(i).getMasterExtent() == otherEnd) return true;
1389    }
1390    return false;
1391  }
1392
1393  /**
1394   * Returns the property that is mapped to the primary key property in the
1395   * Polymorph table If no property is mapped to the primary key property
1396   * {@link ObjectNotDefinedException}is thrown.
1397   *
1398   * @return The idProperty value
1399   * @exception ObjectNotDefinedException
1400   * Description of the Exception
1401   */

1402  public DjProperty getIdProperty() throws ObjectNotDefinedException
1403  {
1404    return getPropertyByMapping(DjPersistenceManager.MAPPING_OBJECT_ID);
1405  }
1406
1407  /**
1408   * Returns the name of the extent, delegates to getName()
1409   *
1410   * @return Description of the Return Value
1411   */

1412  public String JavaDoc toString()
1413  {
1414    return getName();
1415  }
1416
1417  /**
1418   * Returns the type of the component to be used to display/edit an object in
1419   * editors etc. The type returned is {@link DjDomain}.COMP_COMBOBOX
1420   *
1421   * @return The componentType value
1422   */

1423  public int getComponentType()
1424  {
1425    return DjDomain.COMP_COMBOBOX;
1426  }
1427
1428  /**
1429   * Returns the type name of the component to be used to display/edit an
1430   * object in editors etc. The type returned is {@link DjDomain}."Lookup"
1431   *
1432   * @return The componentTypeName value
1433   */

1434  public String JavaDoc getComponentTypeName()
1435  {
1436    return DjDomain.int2componentType(getComponentType());
1437  }
1438
1439  public void autoAdjustMappings(DjProperty[] forTheseProperties) throws ObjectNotDefinedException, CatalogException
1440  {
1441    for (int i = 0; i < forTheseProperties.length; i++)
1442    {
1443      DjProperty prop = getProperty(forTheseProperties[i].getName());
1444
1445      // ignore ID properties and inherited properties; do not try to repair
1446
// these
1447
if (prop.getMapping().equals(DjPersistenceManager.MAPPING_OBJECT_ID) || isInherited(prop)) continue;
1448      try
1449      {
1450        DjRelation rel = getMasterRelationByPropertyName(prop.getName());
1451        if (rel != null)
1452        {
1453          prop.setType(rel.getMasterExtent());
1454        }
1455
1456        if (rel == null && prop.getType() instanceof DjExtent)
1457        {
1458          throw new CatalogException(Messages.getString("DjExtent.InvalidPropertyType", prop.getName(), prop.getType()
1459              .toString()));
1460        }
1461
1462        if (prop.getType() instanceof DjExtent) autoMapRelation(prop);
1463        else autoMapNormalProperty(prop);
1464      }
1465      catch (CatalogException ce)
1466      {
1467        throw new CatalogException(prop.getName() + ": " + ce.getMessage());
1468      }
1469    }
1470  }
1471
1472  private void autoMapNormalProperty(DjProperty prop) throws CatalogException
1473  {
1474    int typeCode = prop.getTypeCode();
1475    if (typeCode == DjDomain.BIGDECIMAL_TYPE || typeCode == DjDomain.INT_TYPE || typeCode == DjDomain.LONG_TYPE)
1476    {
1477      if (!prop.getMapping().startsWith(DjPersistenceManager.MAPPING_NUM))
1478      {
1479        prop.setMapping(findNextFreeMapping(DjPersistenceManager.MAPPING_NUM));
1480      }
1481    }
1482    else if (prop.getTypeCode() == DjDomain.BYTE_TYPE)
1483    {
1484      if (!prop.getMapping().startsWith(DjPersistenceManager.MAPPING_LNG))
1485      {
1486        prop.setMapping(findNextFreeMapping(DjPersistenceManager.MAPPING_LNG));
1487      }
1488    }
1489    else if (prop.getTypeCode() == DjDomain.DATE_TYPE)
1490    {
1491      if (!prop.getMapping().startsWith(DjPersistenceManager.MAPPING_DAT))
1492      {
1493        prop.setMapping(findNextFreeMapping(DjPersistenceManager.MAPPING_DAT));
1494      }
1495    }
1496    else if (prop.getTypeCode() == DjDomain.STRING_TYPE)
1497    {
1498      int length = prop.getLength();
1499      if (length <= DjPersistenceManager.MAPPING_STR_MAX)
1500      {
1501        prop.setMapping(findNextFreeMapping(DjPersistenceManager.MAPPING_STR));
1502      }
1503      else if (length <= DjPersistenceManager.MAPPING_TXT_MAX)
1504      {
1505        prop.setMapping(findNextFreeMapping(DjPersistenceManager.MAPPING_TXT));
1506      }
1507      else
1508      {
1509        prop.setMapping(findNextFreeMapping(DjPersistenceManager.MAPPING_LNG));
1510      }
1511    }
1512  }
1513
1514  private void autoMapRelation(DjProperty prop) throws CatalogException
1515  {
1516    prop.setMapping(findNextFreeMapping(DjPersistenceManager.MAPPING_REL));
1517  }
1518
1519  private boolean propertyIsMapped(DjExtent extent, String JavaDoc map)
1520  {
1521    try
1522    {
1523      extent.getPropertyByMapping(map);
1524      return true;
1525    }
1526    catch (ObjectNotDefinedException ond)
1527    {
1528      // ignore
1529
}
1530    DjExtent[] specializations = extent.getSpecializations();
1531    for (int i = 0; i < specializations.length; i++)
1532    {
1533      if (propertyIsMapped(specializations[i], map)) return true;
1534    }
1535    return false;
1536  }
1537
1538  public String JavaDoc findNextFreeMapping(String JavaDoc startCode) throws CatalogException
1539  {
1540    int sz = DjPersistenceManager.getMaxMappingCount(startCode);
1541
1542    for (int i = 1; i <= sz; i++)
1543    {
1544      String JavaDoc code = startCode;
1545      if (i < 10) code += "0";
1546      code += i;
1547      if (!propertyIsMapped(this, code)) return code;
1548    }
1549    throw new CatalogException(Messages.getString("DjExtent.NoMoreMappings", startCode));
1550  }
1551
1552  /**
1553   * Returns true if the extent of the object provided is an instance of this
1554   *
1555   * @param value
1556   * Description of the Parameter
1557   * @exception DomainViolationException
1558   * Description of the Exception
1559   */

1560  public void validateValue(Object JavaDoc value) throws DomainViolationException
1561  {
1562    if (value == null) return;
1563
1564    if (value instanceof DjObject)
1565    {
1566      DjObject obj = (DjObject) value;
1567      if (!obj.getExtent().isInstanceof(this)) throw new DomainViolationException(Messages
1568          .getString("DjExtent.ValueNotOfType", getObjectType()));
1569    }
1570    else if (!(value instanceof Long JavaDoc)) throw new DomainViolationException(Messages.getString("DjExtent.ValueNotOfType",
1571                                                                                             getObjectType()));
1572  }
1573
1574  /**
1575   * Validates the descriptor expression
1576   *
1577   * @exception CatalogException
1578   * Thrown when the expression is invalid
1579   */

1580  public void validateDescriptorExpression() throws CatalogException
1581  {
1582    validateDescriptorExpression(getDescriptorExpression());
1583  }
1584
1585  public void validateDescriptorExpression(String JavaDoc expr) throws CatalogException
1586  {
1587    try
1588    {
1589      if (expr == null || expr.trim().length() == 0)
1590      {
1591        return;
1592      }
1593
1594      StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(expr, "+");
1595
1596      while (tok.hasMoreElements())
1597      {
1598        String JavaDoc subExpr = tok.nextToken();
1599        validateSingleDescriptorExpr(subExpr);
1600      }
1601    }
1602    catch (Exception JavaDoc x)
1603    {
1604      throw new CatalogException(Messages.getString("DjExtent.InvalidDescriptor", getName(), getDescriptorExpression(),
1605                                                    x.getMessage()));
1606    }
1607  }
1608
1609  private void validateSingleDescriptorExpr(String JavaDoc expr) throws DjenericException
1610  {
1611    expr = expr.trim();
1612
1613    // First check for string constants:
1614
if (expr.length() == 0) return;
1615    if (expr.startsWith("\"") && expr.endsWith("\"") && expr.length() > 1) return;
1616
1617    // Try to get the property
1618
getProperty(expr);
1619  }
1620
1621  public DjProperty[] getPropertiesWithInvalidMapping()
1622  {
1623    ArrayList JavaDoc result = new ArrayList JavaDoc();
1624
1625    DjProperty[] cols = getProperties();
1626    for (int i = 0; i < cols.length; i++)
1627    {
1628      if (!cols[i].mappingIsValid()) result.add(cols[i]);
1629
1630      for (int j = 0; j < cols.length; j++)
1631      {
1632        if (cols[i].getMapping().equals(cols[j].getMapping()) && !result.contains(cols[i]) && !result.contains(cols[j])
1633            && j != i)
1634        {
1635          if (!isInherited(cols[i])) result.add(cols[i]);
1636          else if (!isInherited(cols[j])) result.add(cols[j]);
1637        }
1638      }
1639    }
1640
1641    return (DjProperty[]) result.toArray(new DjProperty[0]);
1642  }
1643
1644  /**
1645   * Validates the definition of this extent; checks for duplicate names,
1646   * required properties etc. If validation fails a {@link CatalogException}is
1647   * thrown
1648   *
1649   * @param mgr
1650   * Description of the Parameter
1651   * @param strictChecking
1652   * Description of the Parameter
1653   * @exception CatalogException
1654   * Description of the Exception
1655   */

1656  public void validate(DjPersistenceManager mgr, boolean strictChecking) throws CatalogException
1657  {
1658    if (getName().trim().length() == 0) throw new CatalogException(Messages.getString("DjExtent.EmptyName"));
1659    if (getNamePlural().trim().length() == 0) throw new CatalogException(Messages.getString("DjExtent.PluralEmpty",
1660                                                                                            getName()));
1661    if (getNameSingular().trim().length() == 0) throw new CatalogException(Messages.getString("DjExtent.SingularEmpty",
1662                                                                                              getName()));
1663    if (getObjectType().trim().length() == 0) throw new CatalogException(Messages.getString("DjExtent.TypeEmpty",
1664                                                                                            getName()));
1665    if (getTitle().trim().length() == 0) throw new CatalogException(Messages
1666        .getString("DjExtent.TitleEmpty", getName()));
1667    if (getInternalCode().trim().length() == 0) throw new CatalogException(Messages.getString("DjExtent.InternalEmpty",
1668                                                                                              getName()));
1669    if (getInternalCode().length() > DjPersistenceManager.MAX_INTERNAL_CODE_LENGTH) throw new CatalogException(Messages
1670        .getString("DjExtent.AliasTooLong", getName(), String.valueOf(DjPersistenceManager.MAX_INTERNAL_CODE_LENGTH)));
1671    if (mgr.isKnownDomain(getObjectType())) throw new CatalogException(Messages.getString("DjExtent.TypeNotUnique",
1672                                                                                          getName(), getObjectType()));
1673
1674    setName(getName().trim());
1675    setAlias(getAlias().trim());
1676    setObjectType(getObjectType().trim());
1677
1678    DjProperty idprop = null;
1679    try
1680    {
1681      idprop = getPropertyByMapping(DjPersistenceManager.MAPPING_OBJECT_ID);
1682      if (idprop.getTypeCode() != DjDomain.LONG_TYPE)
1683      {
1684        throw new CatalogException(Messages.getString("DjExtent.IDNotLong", idprop.getName(), getName()));
1685      }
1686
1687    }
1688    catch (ObjectNotDefinedException x)
1689    {
1690      try
1691      {
1692        createIdProperty(mgr);
1693      }
1694      catch (DjenericException dje)
1695      {
1696        DjLogger.log(dje);
1697        throw new CatalogException(Messages.getString("global.IdNotMapped", getName(),
1698                                                      DjPersistenceManager.MAPPING_OBJECT_ID));
1699      }
1700    }
1701
1702    if (strictChecking) validateDescriptorExpression();
1703
1704    if (!DjPersistenceManager.isValidName(getName()))
1705    {
1706      throw new CatalogException(Messages.getString("DjExtent.InvalidExtentName", getName()));
1707    }
1708    if (!DjPersistenceManager.isValidName(getObjectType()))
1709    {
1710      throw new CatalogException(Messages.getString("DjExtent.InvalidExtentType", getName(), getObjectType()));
1711    }
1712    if (!DjPersistenceManager.isValidName(getAlias()))
1713    {
1714      throw new CatalogException(Messages.getString("DjExtent.InvalidAlias", getName(), getAlias()));
1715    }
1716
1717    DjProperty[] props = getProperties();
1718    for (int i = 0; i < props.length; i++)
1719    {
1720      for (int j = 0; j < props.length; j++)
1721      {
1722        if ((props[i] != props[j]) && (props[i].getAlias().equalsIgnoreCase(props[j].getAlias())))
1723        {
1724          throw new CatalogException(Messages.getString("DjExtent.PropAliasNotUnique", getName(), props[j].getName()));
1725        }
1726        if ((props[i] != props[j]) && (props[i].getName().equalsIgnoreCase(props[j].getName())))
1727        {
1728          throw new CatalogException(Messages.getString("DjExtent.PropNameNotUnique", getName(), props[j].getName()));
1729        }
1730        if ((props[i] != props[j]) && (props[i].getMapping().equalsIgnoreCase(props[j].getMapping())))
1731        {
1732          throw new CatalogException(Messages.getString("DjExtent.DuplicateMapping", getName() + "."
1733                                                                                     + props[j].getName(), props[i]
1734              .getMapping(), props[j].getName()));
1735        }
1736      }
1737    }
1738    for (int i = 0; i < props.length; i++)
1739    {
1740      props[i].validate(mgr, strictChecking);
1741    }
1742
1743    DjRelation[] rels = getMasterRelations();
1744    for (int i = 0; i < rels.length; i++)
1745    {
1746      rels[i].validate(mgr, strictChecking);
1747      DjProperty detailProp = rels[i].getDetailProperty();
1748
1749      if (!detailProp.getMapping().startsWith(DjPersistenceManager.MAPPING_REL))
1750      {
1751        throw new CatalogException(Messages.getString("DjExtent.NotRelMapped", getName() + "." + rels[i].getName(),
1752                                                      detailProp.getName(), DjPersistenceManager.MAPPING_REL,
1753                                                      detailProp.getMapping()));
1754      }
1755      for (int j = 0; j < rels.length; j++)
1756      {
1757        if (rels[i] != rels[j])
1758        {
1759          if ((rels[i].getDetailExtent() == rels[j].getDetailExtent())
1760              && (rels[i].getDetailProperty() == rels[j].getDetailProperty()))
1761          {
1762            throw new CatalogException(Messages.getString("DjExtent.DuplicateRel", getName(), rels[i].getDetailExtent()
1763                .getName(), rels[i].getDetailProperty().getName()));
1764          }
1765        }
1766      }
1767    }
1768
1769    rels = getDetailRelations();
1770    for (int i = 0; i < rels.length; i++)
1771    {
1772      for (int j = 0; j < rels.length; j++)
1773      {
1774        if (rels[i] != rels[j])
1775        {
1776          if (rels[i].getName().equals(rels[j].getName()) && strictChecking)
1777          {
1778            String JavaDoc msg = Messages.getString("DjExtent.DupRelName", getName(), rels[i].getName());
1779
1780            if (!rels[i].getMasterExtent().getName().equals(rels[j].getMasterExtent().getName()))
1781            {
1782              msg += "\n"
1783                     + Messages.getString("DjExtent.RelsDefinedIn", rels[i].getDetailExtent().getName(), rels[j]
1784                         .getDetailExtent().getName());
1785            }
1786            throw new CatalogException(msg);
1787          }
1788        }
1789      }
1790    }
1791
1792    if (getSuper() != null)
1793    {
1794      try
1795      {
1796        mgr.getType(getSuper().getTypeName());
1797      }
1798      catch (Exception JavaDoc x)
1799      {
1800        throw new CatalogException(Messages.getString("DjExtent.InvalidSuperType", getName(), getSuper().getTypeName()));
1801      }
1802    }
1803  }
1804
1805  public String JavaDoc getDefaultMasterRelationName()
1806  {
1807    String JavaDoc relationName = getNamePlural();
1808    if (relationName == null || relationName.trim().length() == 0)
1809    {
1810      relationName = getObjectType();
1811    }
1812    relationName = relationName.trim();
1813
1814    for (int i = 1; i < relationName.length(); i++)
1815    {
1816      if (relationName.charAt(i - 1) == ' ') relationName = relationName.substring(0, i)
1817                                                            + relationName.toUpperCase().substring(i, i + 1)
1818                                                            + relationName.substring(i + 1);
1819    }
1820    StringBuffer JavaDoc result = new StringBuffer JavaDoc();
1821    for (int i = 0; i < relationName.length(); i++)
1822    {
1823      char ch = relationName.charAt(i);
1824      if (Character.isJavaIdentifierPart(ch)) result.append(ch);
1825    }
1826
1827    if (result.length() > 0) relationName = result.toString();
1828
1829    if (relationName.length() > 0)
1830    {
1831      relationName = relationName.toLowerCase().charAt(0) + relationName.substring(1);
1832    }
1833    return relationName;
1834  }
1835
1836  /**
1837   * Returns true if the extent will contain a large amount of objects
1838   */

1839  public boolean isLarge()
1840  {
1841    return _large;
1842  }
1843
1844  /**
1845   * Set to true if the extent will contain a large amount of objects
1846   */

1847  public void setLarge(boolean b)
1848  {
1849    _large = b;
1850  }
1851
1852  public DjProperty createIdProperty(DjPersistenceManager mgr) throws DjenericException
1853  {
1854    DjProperty prop = new DjProperty("id", DjPersistenceManager.MAPPING_OBJECT_ID, "id", Messages
1855        .getString("ModelEditor.ObjectID"), mgr.getType(DjPersistenceManager.INTERNAL_ID_COLUMN_TYPE), true, 0, null,
1856        Messages.getString("ModelEditor.ObjectID"));
1857
1858    prop.setQueryable(false);
1859    addProperty(prop);
1860    return prop;
1861  }
1862
1863  /**
1864   *
1865   */

1866  public void fixAlias()
1867  {
1868    StringBuffer JavaDoc alias = new StringBuffer JavaDoc(getInternalCode());
1869    if (alias.length() == 0) alias.append(getName());
1870
1871    if (alias.length() > DjPersistenceManager.MAX_INTERNAL_CODE_LENGTH)
1872    {
1873      int i = 0;
1874      while (i < alias.length())
1875      {
1876        if ("aAeEiIoOuU".indexOf(alias.charAt(i)) != -1) alias.deleteCharAt(i);
1877        else i++;
1878      }
1879      if (alias.length() > DjPersistenceManager.MAX_INTERNAL_CODE_LENGTH)
1880      {
1881        alias = new StringBuffer JavaDoc(alias.substring(0, DjPersistenceManager.MAX_INTERNAL_CODE_LENGTH));
1882      }
1883    }
1884    setInternalCode(alias.toString());
1885    setAlias(alias.toString());
1886  }
1887
1888  public void clearSpecializations()
1889  {
1890    _specializations.clear();
1891
1892  }
1893
1894  public void refreshSpecializations()
1895  {
1896    setSuper(getSuper());
1897  }
1898
1899  public boolean isTransient()
1900  {
1901    return _transient;
1902  }
1903
1904  public void setTransient(boolean transient1)
1905  {
1906    _transient = transient1;
1907  }
1908
1909  public DjPackage getPackage()
1910  {
1911    return _package;
1912  }
1913
1914  public void setPackage(DjPackage package1)
1915  {
1916    _package = package1;
1917  }
1918
1919  public String JavaDoc getPropertyType(String JavaDoc propertyPath) throws ObjectNotDefinedException
1920  {
1921    DjProperty prop;
1922    int idx = propertyPath.indexOf(".");
1923    if (idx == -1)
1924    {
1925      try
1926      {
1927        prop = getProperty(propertyPath);
1928      }
1929      catch (ObjectNotDefinedException onde)
1930      {
1931        try
1932        {
1933          DjExtent detail = getDetailRelation(propertyPath).getDetailExtent();
1934          return detail.getQualifiedObjectType();
1935        }
1936        catch (ObjectNotDefinedException onde2)
1937        {
1938          throw onde;
1939        }
1940      }
1941    }
1942    else
1943    {
1944      idx = propertyPath.lastIndexOf(".");
1945      String JavaDoc propName = propertyPath.substring(idx + 1);
1946      String JavaDoc instPath = propertyPath.substring(0, idx);
1947      DjExtent ext = resolveType(instPath);
1948      prop = ext.getProperty(propName);
1949    }
1950    if (prop.getType() instanceof DjExtent)
1951    {
1952      return ((DjExtent) prop.getType()).getQualifiedObjectType();
1953    }
1954    else
1955    {
1956      return prop.getNativeTypeClass().getName();
1957    }
1958  }
1959
1960  protected void deleteInvalidRelationProperties()
1961  {
1962    DjProperty[] props = getProperties();
1963    for (int p = 0; p < props.length; p++)
1964    {
1965      if (props[p].isMappedToRelation() && getMasterRelationByPropertyName(props[p].getName()) == null)
1966      {
1967        DjLogger.log("Removed invalid relprop: " + props[p]);
1968        removeProperty(props[p]);
1969      }
1970    }
1971  }
1972
1973  public boolean hasUidDefined()
1974  {
1975    for (int i = 0; i < getPropertyCount(); i++)
1976      if (getProperty(i).isPartOfUID()) return true;
1977    return false;
1978  }
1979}
Popular Tags