KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.UnsupportedEncodingException JavaDoc;
30 import java.math.BigDecimal JavaDoc;
31 import java.text.ParseException JavaDoc;
32 import java.text.SimpleDateFormat JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Arrays JavaDoc;
35 import java.util.Date JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.StringTokenizer JavaDoc;
39
40 import com.genimen.djeneric.language.Messages;
41 import com.genimen.djeneric.repository.exceptions.CanNotDeleteException;
42 import com.genimen.djeneric.repository.exceptions.DjenericException;
43 import com.genimen.djeneric.repository.exceptions.DomainViolationException;
44 import com.genimen.djeneric.repository.exceptions.ObjectDeletedException;
45 import com.genimen.djeneric.repository.exceptions.ObjectNotDefinedException;
46 import com.genimen.djeneric.repository.exceptions.PropertyFormatException;
47 import com.genimen.djeneric.repository.exceptions.PropertyRequiredException;
48 import com.genimen.djeneric.repository.exceptions.RestrictionFailedException;
49 import com.genimen.djeneric.util.DjLogger;
50
51 /**
52  * Description of the Class
53  *
54  * @author Wido Riezebos
55  * @created November 5, 2001
56  */

57 public abstract class DjObject implements DjValueObject
58 {
59   /////////////////////////////////////////////////////////////////////
60
/**
61    * Performs the actual update in the persistent store
62    *
63    * @exception DjenericException
64    * Description of the Exception
65    */

66   protected abstract void update() throws DjenericException;
67
68   /**
69    * Performs the actual insert in the persistent store
70    *
71    * @exception DjenericException
72    * Description of the Exception
73    */

74   protected abstract void insert() throws DjenericException;
75
76   /**
77    * Performs the actual delete in the persistent store
78    *
79    * @exception DjenericException
80    * Description of the Exception
81    */

82   protected abstract void delete() throws DjenericException;
83
84   /**
85    * Performs the actual reload (requery) from the persistent store
86    *
87    * @exception DjenericException
88    * Description of the Exception
89    */

90   public abstract void reload() throws DjenericException;
91
92   /////////////////////////////////////////////////////////////////////
93

94   /**
95    * Property of type String
96    */

97   public final static int STRING_TYPE = DjDomain.STRING_TYPE;
98   /**
99    * Property of type String Integer
100    */

101   public final static int INT_TYPE = DjDomain.INT_TYPE;
102   /**
103    * Property of type Long
104    */

105   public final static int LONG_TYPE = DjDomain.LONG_TYPE;
106   /**
107    * Property of type Date
108    */

109   public final static int DATE_TYPE = DjDomain.DATE_TYPE;
110   /**
111    * Property of type BigDecimal
112    */

113   public final static int BIGDECIMAL_TYPE = DjDomain.BIGDECIMAL_TYPE;
114
115   private DjExtent _extent;
116   private boolean _isTemporary = false;
117   private boolean _isPersisted = false;
118   private boolean _isBeingLoaded = false;
119   private boolean _isMarkedForDelete = false;
120   private boolean _isModified = false;
121   private boolean _ignoreModifications = false;
122   private String JavaDoc _descriptorExpression = null;
123   private boolean _transient = false;
124   private boolean _alreadyHitDuringCurrentTransaction = false;
125   static SimpleDateFormat JavaDoc sf = new SimpleDateFormat JavaDoc(Messages
126                                                                   .getString("global.DateFormatMask"));
127   private boolean _isDetail = false;
128   private boolean _isDetailOfNewMaster;
129
130   private DjAssociation[] _detailAssociations = null;
131   private DjAssociation[] _masterAssociations = null;
132   private Object JavaDoc[] _propertyValues;
133   private Object JavaDoc[] _originalPropertyValues;
134
135   private DjSession _session;
136
137   /**
138    * Constructor for the DjObject object
139    *
140    * @param session
141    * Description of the Parameter
142    * @param extent
143    * Description of the Parameter
144    * @exception DjenericException
145    * Description of the Exception
146    */

147   protected DjObject(DjSession session, DjExtent extent) throws DjenericException
148   {
149     _propertyValues = new Object JavaDoc[extent.getPropertyCount()];
150     _originalPropertyValues = new Object JavaDoc[extent.getPropertyCount()];
151
152     _extent = extent;
153     _session = session;
154     setDescriptorExpression(extent.getDescriptorExpression());
155     initializeDefaultValues();
156   }
157
158   /**
159    * Returns a shallow copy of the object
160    *
161    * @return the copy
162    * @throws DjenericException
163    */

164   public DjObject shallowCopy() throws DjenericException
165   {
166     DjObject obj = getSession().createObject(getExtent());
167
168     DjProperty id = getExtent().getIdProperty();
169     for (int i = 0; i < getPropertyCount(); i++)
170     {
171       if (getProperty(i) == id) continue;
172       obj.set(i, get(i));
173     }
174
175     return obj;
176   }
177
178   protected void initializeDefaultValues() throws PropertyFormatException, DjenericException
179   {
180     try
181     {
182       setIgnoreModifications(true);
183       DjProperty[] properties = getExtent().getProperties();
184       for (int i = 0; i < properties.length; i++)
185       {
186         if (properties[i].getDefaultValue() != null)
187         {
188           setString(i, properties[i].getDefaultValue());
189         }
190       }
191     }
192     finally
193     { // The following is vital; the modified flag is not reset the object
194
// will never enter the sessions modified list
195
_isModified = false;
196       setIgnoreModifications(false);
197     }
198   }
199
200   /**
201    * Constructor for the DjObject object
202    *
203    * @param session
204    * Description of the Parameter
205    * @param objectType
206    * Description of the Parameter
207    * @exception DjenericException
208    * Description of the Exception
209    */

210   protected DjObject(DjSession session, String JavaDoc objectType) throws DjenericException
211   {
212     this(session, session.getPersistenceManager().getExtentByObjectType(objectType));
213   }
214
215   /**
216    * Sets the persisted attribute of the DjObject object
217    *
218    * @param b
219    * The new persisted value
220    */

221   protected void setPersisted(boolean b)
222   {
223     _isPersisted = b;
224   }
225
226   /**
227    * Sets the hitDuringCurrentTransaction of the DjObject object
228    *
229    * @param b
230    * The new hitDuringCurrentTransaction value
231    */

232   void setHitDuringCurrentTransaction(boolean b)
233   {
234     _alreadyHitDuringCurrentTransaction = b;
235   }
236
237   /**
238    * Returns the hitDuringCurrentTransaction of the DjObject object
239    *
240    * @return The hitDuringCurrentTransaction value
241    */

242   boolean isHitDuringCurrentTransaction()
243   {
244     return _alreadyHitDuringCurrentTransaction;
245   }
246
247   /**
248    * Description of the Method
249    *
250    * @param msg
251    * Description of the Parameter
252    */

253   protected void trace(String JavaDoc msg)
254   {
255     _session.trace(msg);
256   }
257
258   /**
259    * Description of the Method
260    *
261    * @param level
262    * Description of the Parameter
263    * @return Description of the Return Value
264    */

265   public boolean shouldTrace(int level)
266   {
267     return _session.shouldTrace(level);
268   }
269
270   /**
271    * Sets the beingLoaded of the DjObject object
272    *
273    * @param b
274    * The new beingLoaded value
275    */

276   protected void setBeingLoaded(boolean b)
277   {
278     _isBeingLoaded = b;
279   }
280
281   /**
282    * Sets the modified attribute of the DjObject object
283    *
284    * @param b
285    * The new modified value
286    */

287   protected void setModified(boolean b) throws DjenericException
288   {
289     if (b != _isModified)
290     {
291       _isModified = b;
292
293       // Notify the session's caching and modification list
294
if (!isTransient() && !_ignoreModifications && !_isBeingLoaded) getSession().notifyModified(this, _isModified);
295     }
296   }
297
298   public void setTransient(boolean b) throws DjenericException
299   {
300     boolean wastransient = _transient;
301
302     // It is important to set transient to the actual value before we try to
303
// cache the object
304
_transient = b;
305
306     // Switch from transient to persistent again?
307
if (wastransient && !b)
308     {
309       getSession().notifyModified(this, isModified());
310       // And reset the object ID if it was previously set to
311
// TRANSIENT_OBJECT_ID
312
if (getLong(getIdPropertyName()) < 0) setNull(getIdPropertyName());
313     }
314     else if (!_isTemporary && b) getSession().cacheObject(this);
315   }
316
317   /**
318    * Returns the transient of the DjObject object
319    *
320    * @return The transient value
321    */

322   public boolean isTransient()
323   {
324     return _transient;
325   }
326
327   // When set to true the session will not be notified when setModified() is
328
// called.
329
/**
330    * Sets the ignoreModifications of the DjObject object
331    *
332    * @param b
333    * The new ignoreModifications value
334    */

335   protected void setIgnoreModifications(boolean b)
336   {
337     _ignoreModifications = b;
338   }
339
340   /**
341    * Returns the markedForDelete of the DjObject object
342    *
343    * @return The markedForDelete value
344    */

345   public boolean isMarkedForDelete()
346   {
347     return _isMarkedForDelete;
348   }
349
350   /**
351    * Returns the instanceOf of the DjObject object
352    *
353    * @param typeName
354    * Description of the Parameter
355    * @return The instanceOf value
356    * @exception ObjectNotDefinedException
357    * Description of the Exception
358    */

359   public boolean isInstanceOf(String JavaDoc typeName) throws ObjectNotDefinedException
360   {
361     return isInstanceOf(getSession().getPersistenceManager().getExtentByObjectType(typeName));
362   }
363
364   /**
365    * Returns the instanceOf of the DjObject object
366    *
367    * @param ext
368    * Description of the Parameter
369    * @return The instanceOf value
370    */

371   public boolean isInstanceOf(DjExtent ext)
372   {
373     DjExtent sup = getExtent();
374     while (sup != null)
375     {
376       if (sup == ext) return true;
377       sup = sup.getSuper();
378     }
379     return false;
380   }
381
382   public boolean equals(Object JavaDoc o)
383   {
384     if (o == null) return false;
385     if (!(o instanceof DjObject)) return false;
386
387     DjObject obj = (DjObject) o;
388     if (obj.getExtent() != getExtent()) return false;
389
390     for (int i = 0; i < _propertyValues.length; i++)
391     {
392       if (obj._propertyValues[i] == null && _propertyValues[i] != null) return false;
393       if (obj._propertyValues[i] != null && _propertyValues[i] == null) return false;
394       if (obj._propertyValues[i] != null && _propertyValues[i] != null
395           && !obj._propertyValues[i].equals(_propertyValues[i])) return false;
396     }
397     return true;
398   }
399
400   public int hashCode()
401   {
402     int result = 0;
403
404     String JavaDoc[] names = getPropertyNames();
405     for (int i = 0; i < names.length; i++)
406     {
407       Object JavaDoc o = _propertyValues[i];
408       if (o != null) result += o.hashCode();
409     }
410     return result;
411   }
412
413   /**
414    * Gets the extent attribute of the DjObject object
415    *
416    * @return The extent value
417    */

418   public DjExtent getExtent()
419   {
420     return _extent;
421   }
422
423   /**
424    * Gets the originalPropertyValues attribute of the DjObject object
425    *
426    * @return The originalPropertyValues value
427    */

428   protected Object JavaDoc[] getOriginalPropertyValues()
429   {
430     return _originalPropertyValues;
431   }
432
433   /**
434    * Gets the propertyValues attribute of the DjObject object
435    *
436    * @return The propertyValues value
437    */

438   protected Object JavaDoc[] getPropertyValues()
439   {
440     return _propertyValues;
441   }
442
443   /**
444    * Gets the session attribute of the DjObject object
445    *
446    * @return The session value
447    */

448   public DjSession getSession()
449   {
450     return _session;
451   }
452
453   /**
454    * Description of the Method
455    */

456   protected void updateOriginalPropertyValues()
457   {
458     _originalPropertyValues = (Object JavaDoc[]) _propertyValues.clone();
459     // a shallow copy is sufficient here since peoprties are replaced and not
460
// manipulated
461
}
462
463   /**
464    * Sets the isDetail attribute of the DjObject object
465    *
466    * @param b
467    * The new isDetail value
468    */

469   protected void setIsDetail(boolean b)
470   {
471     _isDetail = b;
472   }
473
474   /**
475    * Gets the detail attribute of the DjObject object
476    *
477    * @return The detail value
478    */

479   protected boolean isDetail()
480   {
481     return _isDetail;
482   }
483
484   String JavaDoc _idCol = null;
485
486   public boolean isPropertyChanged(String JavaDoc propertyName) throws ObjectNotDefinedException
487   {
488     return isPropertyChanged(getPropertyIndex(propertyName));
489   }
490
491   public boolean isPropertyChanged(int i)
492   {
493     if (_propertyValues[i] == null && _originalPropertyValues[i] != null) return true;
494     if (_propertyValues[i] != null && _originalPropertyValues[i] == null) return true;
495     return !_propertyValues[i].equals(_originalPropertyValues[i]);
496   }
497
498   /**
499    * Gets the idPropertyName attribute of the DjObject object
500    *
501    * @return The idPropertyName value
502    * @exception ObjectNotDefinedException
503    * Description of the Exception
504    */

505   public String JavaDoc getIdPropertyName() throws ObjectNotDefinedException
506   {
507     if (_idCol == null)
508     {
509       _idCol = _extent.getIdProperty().getName();
510     }
511     return _idCol;
512   }
513
514   /**
515    * Gets the objectId attribute of the DjObject object
516    *
517    * @return The objectId value
518    * @exception DjenericException
519    * Description of the Exception
520    */

521   public long getObjectId() throws DjenericException
522   {
523     determineObjectIdIfNeeded();
524     return getLong(getIdPropertyName());
525   }
526
527   /**
528    * Gets the descriptorExpression attribute of the DjObject object
529    *
530    * @return The descriptorExpression value
531    */

532   public String JavaDoc getDescriptorExpression()
533   {
534     return _descriptorExpression;
535   }
536
537   /**
538    * Sets the descriptorExpression attribute of the DjObject object
539    *
540    * @param descriptorExpression
541    * The new descriptorExpression value
542    */

543   public void setDescriptorExpression(String JavaDoc descriptorExpression)
544   {
545     _descriptorExpression = descriptorExpression;
546   }
547
548   /**
549    * Gets the descriptor attribute of the DjObject object
550    *
551    * @return The descriptor value
552    */

553   public String JavaDoc getDescriptor()
554   {
555     String JavaDoc result = evaluateDescriptorExpression(_descriptorExpression);
556     if (result == null) return "";
557     return result;
558   }
559
560   /**
561    * Gets the descriptor attribute of the DjObject object
562    *
563    * @param origin
564    * Description of the Parameter
565    * @return The descriptor value
566    */

567   private String JavaDoc getDescriptorAvoidingRecursion(DjObject origin)
568   {
569     if (origin == this) return "Recursion Detected";
570     return getDescriptor();
571   }
572
573   /**
574    * Returns the descriptor of the DjObject object
575    *
576    * @param expr
577    * Description of the Parameter
578    * @return The descriptor value
579    */

580   public String JavaDoc getDescriptor(String JavaDoc expr)
581   {
582     if (expr == null || expr.trim().length() == 0) expr = _descriptorExpression;
583
584     String JavaDoc result = evaluateDescriptorExpression(expr);
585     if (result == null) return "";
586     return result;
587   }
588
589   private String JavaDoc evaluateDescriptorExpression(String JavaDoc expr)
590   {
591     String JavaDoc orgExpr = expr;
592     try
593     {
594       if (expr == null || expr.trim().length() == 0)
595       {
596         return getObjectNameSingular() + " " + getObjectId();
597       }
598
599       StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(expr, "+");
600       StringBuffer JavaDoc result = new StringBuffer JavaDoc();
601
602       while (tok.hasMoreElements())
603       {
604         String JavaDoc subExpr = tok.nextToken();
605         String JavaDoc single = evaluateSingleDescriptorField(subExpr);
606         if (single != null)
607         {
608           result.append(single);
609         }
610       }
611
612       if (result.length() == 0) result.append(Messages.getString("DjObject.NewObjectDescriptor", getExtent()
613           .getNameSingular()));
614       return result.toString();
615     }
616     catch (ObjectDeletedException ode)
617     {
618       return Messages.getString("global.Deleted");
619     }
620     catch (Exception JavaDoc x)
621     {
622       DjLogger.log(x);
623       return Messages.getString("DjObject.DescrEvalError", orgExpr);
624     }
625   }
626
627   private String JavaDoc evaluateSingleDescriptorField(String JavaDoc expr) throws DjenericException
628   {
629     expr = expr.trim();
630
631     // First check for string constants:
632
if (expr.length() == 0) return "";
633     if (expr.charAt(0) == '"')
634     {
635       if (expr.endsWith("\"")) return expr.substring(1, expr.length() - 1);
636       return expr.substring(1);
637     }
638
639     DjProperty prop = getProperty(expr);
640     DjPropertyType type = prop.getType();
641
642     if (type instanceof DjDomain)
643     {
644       DjDomain dom = (DjDomain) type;
645       if (dom.hasValidValues())
646       {
647         return dom.translateCode(getString(expr));
648       }
649     }
650     if (type instanceof DjExtent)
651     {
652       DjObject getFrom = (DjObject) get(expr);
653       if (getFrom == null) return null;
654       else return getFrom.getDescriptorAvoidingRecursion(this);
655     }
656     return getString(expr);
657   }
658
659   public String JavaDoc evaluateStringExpression(String JavaDoc expr)
660   {
661     String JavaDoc orgExpr = expr;
662     try
663     {
664       if (expr == null || expr.trim().length() == 0)
665       {
666         return null;
667       }
668
669       StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(expr, "+");
670       StringBuffer JavaDoc result = new StringBuffer JavaDoc();
671
672       while (tok.hasMoreElements())
673       {
674         String JavaDoc subExpr = tok.nextToken();
675         String JavaDoc single = evaluateSingleDescriptorField(subExpr);
676         if (single == null)
677         {
678           return null;
679         }
680         result.append(single);
681       }
682       if (result.length() == 0) return null;
683
684       return result.toString();
685     }
686     catch (Exception JavaDoc x)
687     {
688       DjLogger.log(x);
689       return Messages.getString("DjObject.DescrEvalError", orgExpr);
690     }
691   }
692
693   public Object JavaDoc evaluateObjectExpression(String JavaDoc expr) throws DjenericException
694   {
695     if (expr == null || expr.trim().length() == 0)
696     {
697       return null;
698     }
699
700     String JavaDoc orgExpr = expr;
701     DjObject getFrom = this;
702
703     expr = expr.trim();
704
705     if (expr.length() == 0) return null;
706
707     int idx = expr.indexOf(".");
708     while (idx != -1)
709     {
710       String JavaDoc sub = expr.substring(0, idx);
711       Object JavaDoc o = get(sub);
712       if (o == null) return null;
713       // null value of property
714
if (!(o instanceof DjObject))
715       {
716         System.err.println(Messages.getString("DjObject.DescrEvalErrorFor", orgExpr, getExtent().getName()));
717         System.err.println(Messages.getString("DjObject.CannotTraverse", sub));
718         throw new DjenericException(Messages.getString("DjObject.NotDjObject", sub));
719       }
720       getFrom = (DjObject) o;
721       expr = expr.substring(idx + 1);
722       idx = expr.indexOf(".");
723     }
724     return getFrom;
725   }
726
727   /**
728    * Gets the objectType complete with package prefix
729    *
730    * @return Returns the name of the extent
731    */

732   public String JavaDoc getQualifiedObjectType()
733   {
734     return _extent.getQualifiedObjectType();
735   }
736
737   /**
738    * Gets the objectNameSingular attribute of the DjObject object
739    *
740    * @return The objectNameSingular value
741    */

742   public String JavaDoc getObjectNameSingular()
743   {
744     return _extent.getNameSingular();
745   }
746
747   /**
748    * Gets the objectNamePlural attribute of the DjObject object
749    *
750    * @return The objectNamePlural value
751    */

752   public String JavaDoc getObjectNamePlural()
753   {
754     return _extent.getNamePlural();
755   }
756
757   /**
758    * Gets the detailAssociations attribute of the DjObject object
759    *
760    * @return The detailAssociations value
761    */

762   public DjAssociation[] getDetailAssociations()
763   {
764     if (_detailAssociations == null)
765     {
766       ArrayList JavaDoc directAssocs = new ArrayList JavaDoc();
767
768       ArrayList JavaDoc result = new ArrayList JavaDoc();
769
770       DjRelation[] rels = _extent.getDetailRelations();
771       for (int i = 0; i < rels.length; i++)
772       {
773         DjExtent detailExtent = rels[i].getDetailExtent();
774         ArrayList JavaDoc allDetails = new ArrayList JavaDoc();
775         allDetails.add(detailExtent);
776         directAssocs.add(detailExtent);
777
778         DjExtent[] allSpecs = detailExtent.getAllSpecializations();
779         for (int d = 0; d < allSpecs.length; d++)
780           allDetails.add(allSpecs[d]);
781
782         Iterator JavaDoc it = allDetails.iterator();
783         while (it.hasNext())
784         {
785           DjExtent currentDetail = (DjExtent) it.next();
786           DjAssociation a = _session.getPersistenceManager().createAssociation(_session, this, rels[i], currentDetail);
787           if (!directAssocs.contains(currentDetail)) a.setSpecializationOfActualDetailExtent(true);
788           result.add(a);
789         }
790       }
791       _detailAssociations = (DjAssociation[]) result.toArray(new DjAssociation[0]);
792     }
793
794     return _detailAssociations;
795   }
796
797   /**
798    * Gets the detailAssociationByName attribute of the DjObject object
799    *
800    * @param assocName
801    * Description of the Parameter
802    * @return The detailAssociationByName value
803    * @exception ObjectNotDefinedException
804    * Description of the Exception
805    */

806   public DjAssociation getDetailAssociationByName(String JavaDoc assocName, DjExtent specializedDetailExtent)
807       throws ObjectNotDefinedException
808   {
809     if (_detailAssociations == null)
810     {
811       getDetailAssociations();
812     }
813     for (int i = 0; i < _detailAssociations.length; i++)
814     {
815       if (_detailAssociations[i].getName().equals(assocName)
816           && _detailAssociations[i].getDetailExtent() == specializedDetailExtent)
817       {
818         return _detailAssociations[i];
819       }
820     }
821     throw new ObjectNotDefinedException(Messages.getString("DjObject.AssociationNotDefined", assocName));
822   }
823
824   /**
825    * Returns the named detail association (ignoring associations to specializations of the detail)
826    *
827    * @param assocName
828    * Description of the Parameter
829    * @return The detailAssociationByName value
830    * @exception ObjectNotDefinedException
831    * Description of the Exception
832    */

833   public DjAssociation getDetailAssociationByName(String JavaDoc assocName) throws ObjectNotDefinedException
834   {
835     if (_detailAssociations == null)
836     {
837       getDetailAssociations();
838     }
839     for (int i = 0; i < _detailAssociations.length; i++)
840     {
841       if (_detailAssociations[i].getName().equals(assocName)
842           && !_detailAssociations[i].isSpecializationOfActualDetailExtent())
843       {
844         return _detailAssociations[i];
845       }
846     }
847     throw new ObjectNotDefinedException(Messages.getString("DjObject.AssociationNotDefined", assocName));
848   }
849
850   /**
851    * Gets the masterAssociations attribute of the DjObject object
852    *
853    * @return The masterAssociations value
854    */

855   public DjAssociation[] getMasterAssociations()
856   {
857     if (_masterAssociations == null)
858     {
859       DjRelation[] rels = _extent.getMasterRelations();
860       _masterAssociations = new DjAssociation[rels.length];
861       for (int i = 0; i < rels.length; i++)
862       {
863         DjAssociation ass = _session.getPersistenceManager().createAssociation(_session, this, rels[i],
864                                                                                rels[i].getDetailExtent());
865         _masterAssociations[i] = ass;
866       }
867     }
868     return _masterAssociations;
869   }
870
871   /**
872    * Gets the masterAssociationByName attribute of the DjObject object
873    *
874    * @param assocName
875    * Description of the Parameter
876    * @return The masterAssociationByName value
877    * @exception ObjectNotDefinedException
878    * Description of the Exception
879    */

880   public DjAssociation getMasterAssociationByName(String JavaDoc assocName) throws ObjectNotDefinedException
881   {
882     if (_masterAssociations == null)
883     {
884       getMasterAssociations();
885     }
886     for (int i = 0; i < _masterAssociations.length; i++)
887     {
888       if (_masterAssociations[i].getName().equals(assocName))
889       {
890         return _masterAssociations[i];
891       }
892     }
893     throw new ObjectNotDefinedException(Messages.getString("DjObject.AssociationNotDefined", assocName));
894   }
895
896   /**
897    * Makes sure that there are no objects stored in an association that do not belong there (anymore). This occurs if
898    * properties that are part of a relation are updated. The synch causes the object to be moved from one list to the
899    * other
900    */

901   protected void synchronizeAssociations() throws DjenericException
902   {
903     if (!isTransient() && !isMarkedForDelete())
904     {
905       DjAssociation ass[] = getDetailAssociations();
906       for (int a = 0; a < ass.length; a++)
907       {
908         ass[a].synchronizeWithSession();
909       }
910     }
911   }
912
913   /**
914    * Gets the masterAssociationByPropertyName attribute of the DjObject object
915    *
916    * @param propIdx
917    * Description of the Parameter
918    * @return The masterAssociationByPropertyName value
919    */

920   public DjAssociation getMasterAssociationByPropertyName(int propIdx)
921   {
922     return getMasterAssociationByPropertyName(getPropertyName(propIdx));
923   }
924
925   /**
926    * Gets the masterAssociationByPropertyName attribute of the DjObject object
927    *
928    * @param propertyName
929    * Description of the Parameter
930    * @return The masterAssociationByPropertyName value
931    */

932   public DjAssociation getMasterAssociationByPropertyName(String JavaDoc propertyName)
933   {
934     DjAssociation[] assocs = getMasterAssociations();
935     for (int i = 0; i < assocs.length; i++)
936     {
937       if (assocs[i].getRelation().getDetailProperty().getName().equals(propertyName))
938       {
939         return assocs[i];
940       }
941     }
942     return null;
943   }
944
945   /**
946    * Description of the Method
947    *
948    * @exception PropertyRequiredException
949    * Description of the Exception
950    * @exception ObjectNotDefinedException
951    * Description of the Exception
952    */

953   public void checkRequiredProperties() throws PropertyRequiredException
954   {
955     ArrayList JavaDoc missingProperties = null;
956
957     for (int i = 0; i < getPropertyCount(); i++)
958     {
959       if (_extent.getProperty(i).isRequired() && isNull(i))
960       {
961         if (missingProperties == null)
962         {
963           missingProperties = new ArrayList JavaDoc();
964         }
965         missingProperties.add(getProperty(i).getName());
966       }
967     }
968     if (missingProperties != null)
969     {
970       throw new PropertyRequiredException(Messages.getString("global.RequiredPropNull"), this, missingProperties);
971     }
972   }
973
974   ///////////////////////////////////////////////////////////////////////////////////////////
975
//////////////////////// METADATA
976

977   public boolean hasProperty(String JavaDoc propertyName)
978   {
979     return _extent.hasProperty(propertyName);
980   }
981
982   private DjObject resolveInstance(String JavaDoc instPath, boolean implicitCreate) throws DjenericException
983   {
984     if (instPath == null) return this;
985
986     int idx = instPath.indexOf(".");
987
988     String JavaDoc basePropName = instPath;
989     String JavaDoc restPath = null;
990     if (idx != -1)
991     {
992       basePropName = instPath.substring(0, idx);
993       restPath = instPath.substring(idx + 1);
994     }
995
996     if (_extent.hasProperty(basePropName))
997     {
998