View Javadoc

1   /* (c) Copyright 2003 Caleigo AB, All rights reserved. 
2    * 
3    * This library is free software; you can redistribute it and/or
4    * modify it under the terms of the GNU Lesser General Public
5    * License as published by the Free Software Foundation; either
6    * version 2.1 of the License, or (at your option) any later version.
7    * 
8    * This library is distributed in the hope that it will be useful,
9    * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   * Lesser General Public License for more details.
12   * 
13   * You should have received a copy of the GNU Lesser General Public
14   * License along with this library; if not, write to the Free Software
15   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16   *  
17   */
18  package org.caleigo.core;
19  
20  
21  import java.util.*;
22  
23  import org.caleigo.core.exception.*;
24  import org.caleigo.toolkit.log.*;
25  import org.caleigo.toolkit.util.*;
26  
27  
28  
29  /*** <Description of FieldDescriptor>
30  *
31  * @author Dennis Zikovic
32  * @version 1.00
33  * 
34  *//* 
35  *
36  * WHEN        WHO       WHY & WHAT
37  * ------------------------------------------------------------------------------
38  * 2001-03-12  Dennis Zikovic    Creation
39  * 2003-07-03  Niklas Norberg    changed constructor removed the parameter int index
40  */
41  public class FieldDescriptor implements IFieldDescriptor
42  {
43      // Data members ------------------------------------------------------------
44      private String mCodeName;
45      private String mSourceName;
46      private String mDisplayName;
47      private String mEntityDescriptorName;
48      private DataType mDataType;
49      private int mLength;
50      private int mFlags;
51      private Object mDefaultValue;
52      
53      private List mValidatorList;
54      
55      
56      // Constructors ------------------------------------------------------------
57      
58      /*** The FieldDescriptor constructor has package scope to avoid missuse.
59      */
60      protected FieldDescriptor(String codeName, String sourceName, String displayName, String entityDescriptorName, DataType dataType, int length, int flags, Object defValue)
61      {
62          mCodeName = codeName;
63          mSourceName = sourceName;
64          mDisplayName = displayName;
65          mEntityDescriptorName = entityDescriptorName;
66          mDataType = dataType;
67          mLength = length;
68          mFlags = flags;
69          mDefaultValue = defValue;
70      }
71  
72      // Superclass overrides ----------------------------------------------------
73      public String toString()
74      {
75          return this.getEntityDescriptor().getDataSourceDescriptor().getCodeName()+"."+this.getEntityDescriptor().getCodeName()+"."+this.getCodeName();
76      }
77  
78      // Action methods ----------------------------------------------------------
79      protected Object writeReplace() throws java.io.ObjectStreamException
80      {
81          return new Dezerializer(mEntityDescriptorName, mCodeName);
82      }
83      
84      // Access methods ----------------------------------------------------------
85  
86      public String getCodeName()
87      {
88          return mCodeName;
89      }
90  
91      public String getSourceName()
92      {
93          return mSourceName;
94      }
95  
96      public String getDisplayName()
97      {
98          return ResourceProvider.getString(this.getEntityDescriptor().getCodeName(), mCodeName, mDisplayName);
99      }
100 
101     public DataType getDataType()
102     {
103         return mDataType;
104     }
105 
106     public int getLength()
107     {
108         return mLength;
109     }
110 
111     public Object getDefaultValue()
112     {
113         if(mDefaultValue instanceof IProxyData)
114             return ((IProxyData)mDefaultValue).getData();
115         else
116             return mDefaultValue;
117     }
118 
119     public boolean isIdentityField()
120     {
121         return (mFlags & IDENTITY_FIELD)!=0;
122     }
123 
124     public boolean isReferenceField()
125     {
126         return this.getReferenceFieldRelation()!=null;
127     }
128 
129     public boolean isRequired()
130     {
131         return (mFlags & REQUIRED)!=0;
132     }
133 
134     public boolean isIndexed()
135     {
136         return (mFlags & INDEXED)!=0;
137     }
138 
139     public boolean isAutoGenerated()
140     {
141         return (mFlags & AUTOGEN)!=0;
142     }
143 
144     public boolean isNameField()
145     {
146         return (mFlags & NAME_FIELD)!=0;
147     }
148 
149     public boolean isOverviewField()
150     {
151         return (mFlags & OVERVIEW_FIELD)!=0;
152     }
153 
154     public boolean isHintField()
155     {
156         return (mFlags & HINT_FIELD)!=0;
157     }
158 
159     public boolean isHiddenField()
160     {
161         return (mFlags & HIDDEN_FIELD)!=0;
162     }
163 
164     public boolean isReadOnly()
165     {
166         return (mFlags & READ_ONLY_FIELD)!=0;
167     }
168 
169     public boolean isNaturalOrder()
170     {
171         return (mFlags & NATURAL_ORDER)!=0;
172     }
173 
174     public IEntityDescriptor getEntityDescriptor()
175     {
176         IEntityDescriptor entityDescriptor = null;
177         try
178         {
179             Class entityClass = Class.forName(mEntityDescriptorName);
180             java.lang.reflect.Field field = entityClass.getField("instance");
181             entityDescriptor = (IEntityDescriptor)field.get(null);
182         }
183         catch(Exception e)
184         {
185             String msg = "Invalid entity descriptor data: "+mEntityDescriptorName;
186             Log.printError(this, msg);
187             throw new InvalidDescriptorException(msg, e);
188         }
189         return entityDescriptor;
190     }
191 
192     /*** This method returns true if the called field descriptor can validate
193      * data described by the field in the context of the provided IDataProvider
194      * object. The minimum requiriment is that described field data can be 
195      * provided but in some cases other data resources is also required.
196      */
197     public boolean canValidate(IDataProvider dataProvider)
198     {
199         boolean valid = true;
200         for(int j=0; valid && mValidatorList!=null && j<mValidatorList.size(); j++)
201             valid = ((IDataValidator)mValidatorList.get(j)).canValidate(dataProvider);
202         return valid;
203     }
204 
205     /*** This method validates the provided data object as described by the 
206      * called field descriptor in the context of the provided IDataProvider 
207      * object.
208      */
209     public ValidationResult validateData(Object data, IDataProvider dataProvider)
210     {
211         ValidationResult result = ValidationResult.VALID_RESULT;
212         
213         // Perform base validations.
214         result = this.performBaseValidation(data);
215         
216         // Check validity using registered validators.
217         for(int j=0; result.isValid() && mValidatorList!=null && j<mValidatorList.size(); j++)
218             if(!((IDataValidator)mValidatorList.get(j)).isDataValid(data, dataProvider))
219                 result = new ValidationResult(this, ((IDataValidator)mValidatorList.get(j)).getInvalidMessage(data, dataProvider));
220         
221         return result;
222     }
223 
224     /*** Access method that returns the field relation that the called field  
225      * is a reference to. If the called field descriptor is not a reference 
226      * field then null is returned.
227      */
228     public IFieldRelation getReferenceFieldRelation()
229     {
230         IFieldRelation refRelation = null;
231         java.util.Iterator it = this.getFieldRelations();
232         while(refRelation==null && it.hasNext())
233         {
234             IFieldRelation relation = (IFieldRelation)it.next();
235             if(relation.getReferenceField()==this)
236                 refRelation = relation;
237         }
238         return refRelation;
239     }
240     
241     /*** Access method that returns an iterator for all IFieldRelation 
242      * objects that the called field descripyor is a part of.
243      */
244     public java.util.Iterator getFieldRelations()
245     {
246         return new FieldRelationIterator();        
247     }
248     
249     // Help methods ------------------------------------------------------------
250     
251     protected void addValidator(IDataValidator dataValidator)
252     {
253         if(mValidatorList!=null)
254             mValidatorList = new ArrayList(5);
255         mValidatorList.add(dataValidator);
256     }
257     
258     /*** Performs basic validations that are relevant for all fields like
259      * checking for null values in reguired field data.
260      */
261     public ValidationResult performBaseValidation(Object dataValue)
262     {
263         // Validate null value.
264         if(dataValue==null && this.isRequired() && !this.isAutoGenerated())
265             return new ValidationResult(this, ResourceProvider.getString(this.getEntityDescriptor().getCodeName(), mCodeName+".RequiredMSG", "The "+this.getDisplayName()+" field may not be empty."));
266         
267         // Validate length.
268         if(this.getDataType()==DataType.STRING && dataValue!=null && ((String)dataValue).length()>mLength && mLength>0)
269             return new ValidationResult(this, ResourceProvider.getString(this.getEntityDescriptor().getCodeName(), mCodeName+".ToLongMSG", "The "+this.getDisplayName()+" field is to long. It may only contain "+mLength+" characters."));        
270         
271         return ValidationResult.VALID_RESULT;
272     }
273     
274     // Nested classes ----------------------------------------------------------
275     protected class FieldRelationIterator implements java.util.Iterator
276     {
277         private int mEntityRelationIndex;
278         private int mFieldRelationIndex;
279         private Object mNextObject;
280         
281         public FieldRelationIterator()
282         {
283             mEntityRelationIndex = 0;
284             mFieldRelationIndex = 0;
285             this.next();
286         }
287 
288         public Object next()
289         {
290             Object retObject = mNextObject;
291             
292             mNextObject = null;
293             while(mNextObject==null && mEntityRelationIndex<getEntityDescriptor().getEntityRelationCount())
294             {
295                 // Scan all fields in the current entity relation.
296                 while(mNextObject==null && mFieldRelationIndex<getEntityDescriptor().getEntityRelation(mEntityRelationIndex).getFieldCount())
297                 {
298                     // Check if field is part of the field relation
299                     IFieldRelation rel = getEntityDescriptor().getEntityRelation(mEntityRelationIndex).getFieldRelation(mFieldRelationIndex);
300                     if(rel.getReferenceField()==FieldDescriptor.this || rel.getTargetField()==FieldDescriptor.this)
301                         mNextObject = rel;
302                     
303                     // Advance to the next field relation.
304                     mFieldRelationIndex++;
305                 }
306                 
307                 // Advance to the next entity relation.
308                 if(mFieldRelationIndex>=getEntityDescriptor().getEntityRelation(mEntityRelationIndex).getFieldCount())
309                 {
310                     mEntityRelationIndex++;
311                     mFieldRelationIndex = 0;
312                 }
313             }
314 
315             return retObject;
316         }
317 
318         public boolean hasNext() 
319         {
320             return mNextObject!=null;
321         }
322 
323         public void remove() 
324         {
325             throw new java.lang.UnsupportedOperationException();
326         }
327     }
328     
329     protected static class Dezerializer implements java.io.Serializable
330     {
331         // Data members --------------------------------------------------------
332         protected String mEntityDescriptorClassName;
333         protected String mFieldDescriptorCodeName;
334         
335         // Constructors --------------------------------------------------------
336         public Dezerializer(String entityDescriptorClassName, String fieldDescriptorCodeName)
337         {
338             mEntityDescriptorClassName = entityDescriptorClassName;
339             mFieldDescriptorCodeName = fieldDescriptorCodeName;
340         }
341         
342         // Action methods ------------------------------------------------------
343         protected Object readResolve() throws java.io.ObjectStreamException
344         {
345             try
346             {
347                 Class entityDescriptorClass = Class.forName(mEntityDescriptorClassName);
348                 java.lang.reflect.Field entityDescriptorInstanceField = entityDescriptorClass.getField("instance");
349                 IEntityDescriptor entityDescriptor = (IEntityDescriptor) entityDescriptorInstanceField.get(null);
350                 return entityDescriptor.getFieldDescriptor(mFieldDescriptorCodeName);
351             }
352             catch (Exception e)
353             {
354                 Log.printError(this, "Error in readResolve", e);
355                 throw new java.io.InvalidObjectException(e.getMessage());
356             }
357         }
358     }
359 }