KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > metadata > SuperReferenceDescriptor


1 package org.apache.ojb.broker.metadata;
2
3 /* Copyright 2003-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import java.util.List JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.HashMap JavaDoc;
21
22 import org.apache.commons.lang.SystemUtils;
23 import org.apache.ojb.broker.metadata.fieldaccess.AnonymousPersistentField;
24 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
25 import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldFactory;
26 import org.apache.ojb.broker.util.ClassHelper;
27 import org.apache.ojb.broker.util.logging.Logger;
28 import org.apache.ojb.broker.util.logging.LoggerFactory;
29
30 /**
31  * This class handle inheritance as 1-1 association based on a anonymous field
32  * (no field in persistent object needed).
33  *
34  * @version $Id: SuperReferenceDescriptor.java,v 1.1.2.6 2005/12/21 22:26:10 tomdz Exp $
35  */

36 public class SuperReferenceDescriptor extends ObjectReferenceDescriptor
37 {
38     private transient Logger log;
39
40     public static final String JavaDoc SUPER_FIELD_INTERNAL_NAME = "ojbSuperFieldInternal";
41     public static final String JavaDoc SUPER_FIELD_NAME = RepositoryElements.TAG_SUPER;
42
43     private Boolean JavaDoc javaInheritance;
44     private Map JavaDoc declaredInheritanceFields = new HashMap JavaDoc();
45
46     public SuperReferenceDescriptor(ClassDescriptor descriptor)
47     {
48         super(descriptor);
49         // most important call, create new specific field for inheritance
50
super.setPersistentField(new SuperReferenceField(this));
51         // needed immutable settings
52
super.setLazy(false);
53         super.setCascadeRetrieve(true);
54         super.setCascadingStore(CASCADE_OBJECT);
55         super.setCascadingDelete(CASCADE_OBJECT);
56     }
57
58     public boolean isSuperReferenceDescriptor()
59     {
60         return true;
61     }
62
63     public void setItemClass(Class JavaDoc c)
64     {
65         super.setItemClass(c);
66         getClassDescriptor().setBaseClass(c.getName());
67     }
68
69     /**
70      * Noop, a specific {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField} is
71      * used internal - {@link org.apache.ojb.broker.metadata.SuperReferenceDescriptor.SuperReferenceField}.
72      */

73     public void setPersistentField(Class JavaDoc c, String JavaDoc fieldname)
74     {
75         // noop
76
}
77
78     /**
79      * Noop, a specific {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField} is
80      * used internal - {@link org.apache.ojb.broker.metadata.SuperReferenceDescriptor.SuperReferenceField}.
81      */

82     public void setPersistentField(PersistentField pf)
83     {
84         // noop
85
}
86
87     public void setLazy(boolean lazy)
88     {
89         getLog().info("Not allowed to change this property, will ignore setting");
90     }
91
92     public void setCascadeRetrieve(boolean b)
93     {
94         getLog().info("Not allowed to change this property, will ignore setting");
95     }
96
97     public void setCascadingStore(int cascade)
98     {
99         getLog().info("Not allowed to change this property, will ignore setting");
100     }
101
102     public void setCascadingStore(String JavaDoc value)
103     {
104         getLog().info("Not allowed to change this property, will ignore setting");
105     }
106
107     public void setCascadingDelete(int cascade)
108     {
109         getLog().info("Not allowed to change this property, will ignore setting");
110     }
111
112     public void setCascadingDelete(String JavaDoc value)
113     {
114         getLog().info("Not allowed to change this property, will ignore setting");
115     }
116
117     public void setCascadeStore(boolean cascade)
118     {
119         getLog().info("Not allowed to change this property, will ignore setting");
120     }
121
122     public void setCascadeDelete(boolean cascade)
123     {
124         getLog().info("Not allowed to change this property, will ignore setting");
125     }
126
127     public SuperReferenceField getInheritanceField()
128     {
129         return (SuperReferenceField) getPersistentField();
130     }
131
132     /**
133      * If this method returns <em>true</em> the inheritance described by this object
134      * is a <em>normal</em> JAVA inheritance. If <em>false</em> the inheritance is only declared
135      * in the O/R mapping it's a <em>declarative inheritance</em>, the referenced "super class" in <strong>not</strong>
136      * a JAVA super class of the main class.
137      */

138     public boolean isJavaInheritance()
139     {
140         if(javaInheritance == null)
141         {
142             javaInheritance = getClassDescriptor().getSuperClassDescriptor().getClassOfObject()
143                     .isAssignableFrom(getClassDescriptor().getClassOfObject()) ? Boolean.TRUE : Boolean.FALSE;
144         }
145         return javaInheritance.booleanValue();
146     }
147
148     synchronized PersistentField getDeclaredInheritanceField(Class JavaDoc target, String JavaDoc name)
149     {
150         Map JavaDoc fields = (HashMap JavaDoc) declaredInheritanceFields.get(target);
151         if(fields == null)
152         {
153             fields = new HashMap JavaDoc();
154             declaredInheritanceFields.put(target, fields);
155         }
156         PersistentField pf = (PersistentField) fields.get(name);
157         if(pf == null)
158         {
159             pf = PersistentFieldFactory.createPersistentField(target, name);
160             // System.out.println("## tmp field: " + target + ", name: " + name + ", field: " + pf);
161
fields.put(name, pf);
162         }
163         return pf;
164     }
165
166     private Logger getLog()
167     {
168         if(log == null)
169         {
170             log = LoggerFactory.getLogger(SuperReferenceField.class);
171         }
172         return log;
173     }
174
175
176     //====================================================
177
// inner class
178
//====================================================
179

180     public static final class SuperReferenceField extends AnonymousPersistentField
181     {
182         private transient Logger log;
183
184         private SuperReferenceDescriptor superRef;
185
186         public SuperReferenceField(SuperReferenceDescriptor superRef)
187         {
188             super(SUPER_FIELD_INTERNAL_NAME);
189             this.superRef = superRef;
190         }
191
192         private Logger getLog()
193         {
194             if(log == null)
195             {
196                 log = LoggerFactory.getLogger(SuperReferenceField.class);
197             }
198             return log;
199         }
200
201         /**
202          * Field values of 'value' (base object) are copied to 'obj' (derived object)
203          * then obj is saved in a map
204          *
205          * @param target - the base object instance
206          * @param value - the derived object instance
207          * @throws MetadataException
208          */

209         public synchronized void set(Object JavaDoc target, Object JavaDoc value) throws MetadataException
210         {
211             // System.out.println("target: " + target + " value: " + value);
212
ClassDescriptor superCld = superRef.getClassDescriptor().getSuperClassDescriptor();
213             if(superRef.isJavaInheritance())
214             {
215                 copyFields(superCld, target, superCld, value, true, true);
216             }
217             else
218             {
219                 copyFields(superRef.getClassDescriptor(), target, superCld, value, false, false);
220             }
221         }
222
223         /**
224          * Field values of specified 'obj' (the derived object) are copied to
225          * 'value' (base object) then value is returned as a referenced object.
226          * If the base object is the super class of the specified 'obj', then
227          * return the specified object.
228          * Else a base class instance will be created at runtime and the field values
229          * from the derived object are copied to the base class object.
230          *
231          * @param obj - the base object instance
232          * @throws MetadataException
233          */

234         public synchronized Object JavaDoc get(Object JavaDoc obj) throws MetadataException
235         {
236             if(obj == null) return null;
237             if(superRef.isJavaInheritance())
238             {
239                 return obj;
240             }
241             else
242             {
243                 return getObjectWithDeclaredSuperClass(obj);
244             }
245         }
246
247         private Object JavaDoc getObjectWithDeclaredSuperClass(Object JavaDoc obj)
248         {
249             Object JavaDoc value = getFromFieldCache(obj);
250             if(value == null)
251             {
252                 ClassDescriptor baseCld = null;
253                 try
254                 {
255                     baseCld = superRef.getClassDescriptor().getSuperClassDescriptor();
256                     value = ClassHelper.buildNewObjectInstance(baseCld);
257                 }
258                 catch(Exception JavaDoc e)
259                 {
260                     throw new MetadataException("Can't create new base class object for '"
261                             + (baseCld != null ? baseCld.getClassNameOfObject() : null) + "'", e);
262                 }
263                 copyFields(baseCld, value, superRef.getClassDescriptor(), obj, true, false);
264                 putToFieldCache(obj, value);
265             }
266             return value;
267         }
268
269         void copyFields(ClassDescriptor targetCld, Object JavaDoc target, ClassDescriptor sourceCld, Object JavaDoc source, boolean targetIsSuper, boolean javaInheritance)
270         {
271             if(getLog().isDebugEnabled())
272             {
273                 String JavaDoc msg = ("Copy fields from " + SystemUtils.LINE_SEPARATOR
274                         + "source object '" + (source != null ? source.getClass().getName() : null) + "'" + SystemUtils.LINE_SEPARATOR
275                         + "using source fields declared in '" + sourceCld.getClassNameOfObject() + "'" + SystemUtils.LINE_SEPARATOR
276                         + "to target object '" + (target != null ? target.getClass().getName() : null) + "'" + SystemUtils.LINE_SEPARATOR
277                         + "using target fields declared in '" + targetCld.getClassNameOfObject() + "'" + SystemUtils.LINE_SEPARATOR
278                         + "the fields to copy are declared in '" + (targetIsSuper ? targetCld.getClassNameOfObject() : sourceCld.getClassNameOfObject()) + "' class" + SystemUtils.LINE_SEPARATOR
279                         + "the used classes are associated by java inheritance: " + javaInheritance + SystemUtils.LINE_SEPARATOR);
280                 getLog().debug(msg);
281             }
282             /*
283             arminw:
284             If the target object is a super object of the source object, iterate all target object fields.
285             If the source object is a super object of the target object, iterate all source object fields
286
287             If java inheritance is used (target is super class of source or vice versa) we can use the same
288             FieldDescriptor to copy the fields.
289             If only a "declarative inheritance" is used (no class inheritance, only identical field names of the super class)
290             we have to use the associated FieldDescriptor of target and source ClassDescriptor
291             */

292             FieldDescriptor[] fields = targetIsSuper ? targetCld.getFieldDescriptions() : sourceCld.getFieldDescriptions();
293             for(int i = 0; i < fields.length; i++)
294             {
295                 FieldDescriptor field = fields[i];
296                 if(!field.isAnonymous())
297                 {
298                     performFieldCopy(target, targetCld, source, sourceCld,
299                                 field.getPersistentField(), targetIsSuper, javaInheritance);
300                 }
301             }
302             List JavaDoc refs = targetIsSuper ? targetCld.getCollectionDescriptors() : sourceCld.getCollectionDescriptors();
303             for(int i = 0; i < refs.size(); i++)
304             {
305                 CollectionDescriptor col = (CollectionDescriptor) refs.get(i);
306                 PersistentField pf = col.getPersistentField();
307                 performFieldCopy(target, targetCld, source, sourceCld, pf, targetIsSuper, javaInheritance);
308             }
309
310             refs = targetIsSuper ? targetCld.getObjectReferenceDescriptors() : sourceCld.getObjectReferenceDescriptors();
311             for(int i = 0; i < refs.size(); i++)
312             {
313                 ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) refs.get(i);
314                 PersistentField pf = ord.getPersistentField();
315                 performFieldCopy(target, targetCld, source, sourceCld, pf, targetIsSuper, javaInheritance);
316             }
317         }
318
319         private void performFieldCopy(Object JavaDoc target, ClassDescriptor targetCld, Object JavaDoc source,
320                                  ClassDescriptor sourceCld, PersistentField pf, boolean targetIsSuper, boolean javaInheritance)
321         {
322             if(javaInheritance)
323             {
324                 pf.set(target, pf.get(source));
325             }
326             else
327             {
328                 if(targetIsSuper)
329                 {
330                     if(pf instanceof SuperReferenceField)
331                     {
332                         log.error("Declared inheritance doesn't support nested super references, target '"
333                                 + targetCld.getClassNameOfObject() + "' has super reference");
334                     }
335                     else
336                     {
337                         PersistentField tmp = superRef.getDeclaredInheritanceField(sourceCld.getClassOfObject(), pf.getName());
338                         pf.set(target, tmp.get(source));
339                     }
340                 }
341                 else
342                 {
343                     PersistentField tmp = superRef.getDeclaredInheritanceField(targetCld.getClassOfObject(), pf.getName());
344                     tmp.set(target, pf.get(source));
345                 }
346             }
347         }
348     }
349 }
350
351
Popular Tags