KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > queryframework > MapContainerPolicy


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.queryframework;
23
24 import java.security.AccessController JavaDoc;
25 import java.security.PrivilegedActionException JavaDoc;
26 import java.util.*;
27 import java.lang.reflect.*;
28
29 import oracle.toplink.essentials.exceptions.*;
30 import oracle.toplink.essentials.internal.ejb.cmp3.base.CMP3Policy;
31 import oracle.toplink.essentials.internal.helper.*;
32 import oracle.toplink.essentials.queryframework.DatabaseQuery;
33 import oracle.toplink.essentials.internal.security.PrivilegedAccessHelper;
34 import oracle.toplink.essentials.internal.security.PrivilegedClassForName;
35 import oracle.toplink.essentials.internal.security.PrivilegedMethodInvoker;
36 import oracle.toplink.essentials.internal.security.PrivilegedGetValueFromField;
37 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
38 import oracle.toplink.essentials.internal.sessions.AbstractSession;
39
40 /**
41  * <p><b>Purpose</b>: A MapContainerPolicy is ContainerPolicy whose container
42  * class implements the Map interface.
43  * <p>
44  * <p><b>Responsibilities</b>:
45  * Provide the functionality to operate on an instance of a Map.
46  *
47  * @see ContainerPolicy
48  * @see CollectionContainerPolicy
49  */

50 public class MapContainerPolicy extends InterfaceContainerPolicy {
51     protected String JavaDoc keyName;
52     protected String JavaDoc elementClassName;
53     protected Class JavaDoc elementClass;
54     protected transient Field keyField;
55     protected transient Method keyMethod;
56
57     /**
58      * INTERNAL:
59      * Construct a new policy.
60      */

61     public MapContainerPolicy() {
62         super();
63     }
64
65     /**
66      * INTERNAL:
67      * Construct a new policy for the specified class.
68      */

69     public MapContainerPolicy(Class JavaDoc containerClass) {
70         super(containerClass);
71     }
72
73     /**
74      * INTERNAL:
75      * Construct a new policy for the specified class name.
76      */

77     public MapContainerPolicy(String JavaDoc containerClassName) {
78         super(containerClassName);
79     }
80
81     /**
82      * Prepare and validate.
83      * Set the element class.
84      */

85     public void prepare(DatabaseQuery query, AbstractSession session) throws QueryException {
86         if ((getElementClass() == null) && (query.getDescriptor() != null)) {
87             setElementClass(query.getDescriptor().getJavaClass());
88         }
89         
90         super.prepare(query, session);
91     }
92
93     /**
94      * INTERNAL:
95      * Add element into container which implements the Map interface.
96      */

97     public boolean addInto(Object JavaDoc key, Object JavaDoc element, Object JavaDoc container, AbstractSession session) {
98         Object JavaDoc wrapped = element;
99         
100         if (hasElementDescriptor()) {
101             wrapped = getElementDescriptor().getObjectBuilder().wrapObject(element, session);
102         }
103         
104         try {
105             if (key != null) {
106                 return ((Map) container).put(key, wrapped) != null;
107             } else {
108                 return ((Map) container).put(keyFrom(element, session), wrapped) != null;
109             }
110         } catch (ClassCastException JavaDoc ex1) {
111             throw QueryException.mapKeyNotComparable(element, container);
112         }
113     }
114
115     /**
116      * INTERNAL:
117      * Remove all the elements from container.
118      */

119     public void clear(Object JavaDoc container) {
120         try {
121             ((Map)container).clear();
122         } catch (UnsupportedOperationException JavaDoc ex) {
123             throw QueryException.methodNotValid(container, "clear()");
124         }
125     }
126
127     /**
128      * INTERNAL:
129      * Return true if keys are the same in the source as the backup. False otherwise
130      * in the case of readonly compare against the original
131      */

132     public boolean compareKeys(Object JavaDoc sourceValue, AbstractSession session) {
133         Object JavaDoc backUpVersion = null;
134
135         if (((UnitOfWorkImpl)session).isClassReadOnly(sourceValue.getClass())) {
136             backUpVersion = ((UnitOfWorkImpl)session).getOriginalVersionOfObject(sourceValue);
137         } else {
138             backUpVersion = ((UnitOfWorkImpl)session).getBackupClone(sourceValue);
139         }
140         
141         return (keyFrom(backUpVersion, session).equals(keyFrom(sourceValue, session)));
142     }
143
144     /**
145      * INTERNAL:
146      * Return the true if element exists in container.
147      * @return boolean true if container 'contains' element
148      */

149     protected boolean contains(Object JavaDoc element, Object JavaDoc container) {
150         return ((Map)container).containsValue(element);
151     }
152     
153     /**
154      * INTERNAL:
155      * Convert all the class-name-based settings in this ContainerPolicy to
156      * actual class-based settings. This method is used when converting a
157      * project that has been built with class names to a project with classes.
158      * @param classLoader
159      */

160     public void convertClassNamesToClasses(ClassLoader JavaDoc classLoader){
161         super.convertClassNamesToClasses(classLoader);
162         
163         if (elementClassName == null){
164             return;
165         }
166         
167         try {
168             Class JavaDoc elementClass = null;
169             if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
170                 try {
171                     elementClass = (Class JavaDoc)AccessController.doPrivileged(new PrivilegedClassForName(elementClassName, true, classLoader));
172                 } catch (PrivilegedActionException JavaDoc exception) {
173                     throw ValidationException.classNotFoundWhileConvertingClassNames(containerClassName, exception.getException());
174                 }
175             } else {
176                 elementClass = oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.getClassForName(elementClassName, true, classLoader);
177             }
178             setElementClass(elementClass);
179         } catch (ClassNotFoundException JavaDoc exc){
180             throw ValidationException.classNotFoundWhileConvertingClassNames(containerClassName, exc);
181         }
182     }
183
184     /**
185      * INTERNAL:
186      * Returns the element class which defines the map key.
187      */

188     public Class JavaDoc getElementClass() {
189         return elementClass;
190     }
191     
192     /**
193      * INTERNAL:
194      * Returns the element class name which defines the map key.
195      */

196     public String JavaDoc getElementClassName() {
197         return elementClassName;
198     }
199
200     /**
201      * INTERNAL:
202      */

203     public Class JavaDoc getInterfaceType() {
204         return ClassConstants.Map_Class;
205     }
206
207     /**
208      * INTERNAL:
209      * Returns the key name which will return the value of the key to be used
210      * in the container.
211      */

212     public String JavaDoc getKeyName() {
213         return keyName;
214     }
215
216     /**
217      * INTERNAL
218      * Yes this is a MapPolicy
219      */

220     public boolean isMapPolicy() {
221         return true;
222     }
223
224     /**
225      * INTERNAL:
226      * Return an Iterator for the given container.
227      */

228     public Object JavaDoc iteratorFor(Object JavaDoc container) {
229         return ((Map)container).values().iterator();
230     }
231
232     /**
233      * INTERNAL:
234      * Return the key for the specified element.
235      */

236     public Object JavaDoc keyFrom(Object JavaDoc element, AbstractSession session) {
237         // Should only run through this once ...
238
if (keyName != null && keyMethod == null && keyField == null) {
239             try {
240                 keyMethod = Helper.getDeclaredMethod(elementClass, keyName, (Class JavaDoc[]) null);
241             } catch (NoSuchMethodException JavaDoc ex) {
242                 try {
243                     keyField = Helper.getField(elementClass, keyName);
244                 } catch (NoSuchFieldException JavaDoc e) {
245                     throw ValidationException.mapKeyNotDeclaredInItemClass(keyName, elementClass);
246                 }
247             }
248         }
249         
250         Object JavaDoc keyElement = element;
251         
252         if (hasElementDescriptor()) {
253             keyElement = getElementDescriptor().getObjectBuilder().unwrapObject(element, session);
254         }
255         
256         if (keyMethod != null) {
257             try {
258                 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
259                     try {
260                         return AccessController.doPrivileged(new PrivilegedMethodInvoker(keyMethod, keyElement, (Object JavaDoc[])null));
261                     } catch (PrivilegedActionException JavaDoc exception) {
262                         Exception JavaDoc throwableException = exception.getException();
263                         if (throwableException instanceof IllegalAccessException JavaDoc) {
264                             throw QueryException.cannotAccessMethodOnObject(keyMethod, keyElement);
265                         } else {
266                             throw QueryException.calledMethodThrewException(keyMethod, keyElement, throwableException);
267                         }
268                     }
269                 } else {
270                     return PrivilegedAccessHelper.invokeMethod(keyMethod, keyElement, (Object JavaDoc[])null);
271                 }
272             } catch (IllegalAccessException JavaDoc e) {
273                 throw QueryException.cannotAccessMethodOnObject(keyMethod, keyElement);
274             } catch (InvocationTargetException exception) {
275                 throw QueryException.calledMethodThrewException(keyMethod, keyElement, exception);
276             }
277         } else if (keyField != null) {
278             try {
279                 if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
280                     try {
281                         return AccessController.doPrivileged(new PrivilegedGetValueFromField(keyField, keyElement));
282                     } catch (PrivilegedActionException JavaDoc exception) {
283                         throw QueryException.cannotAccessFieldOnObject(keyField, keyElement);
284                     }
285                 } else {
286                     return oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.getValueFromField(keyField, keyElement);
287                 }
288             } catch (IllegalAccessException JavaDoc e) {
289                 throw QueryException.cannotAccessFieldOnObject(keyField, keyElement);
290             }
291         } else {
292             // If we get this far I think it is safe to assume we have
293
// an element descriptor.
294
return ((CMP3Policy) getElementDescriptor().getCMPPolicy()).createPrimaryKeyInstance(keyElement, session);
295         }
296     }
297
298     /**
299      * INTERNAL:
300      * Remove element from container which implements the Map interface.
301      */

302     public boolean removeFrom(Object JavaDoc key, Object JavaDoc element, Object JavaDoc container, AbstractSession session) {
303         try {
304             Object JavaDoc returnValue = null;
305             if (key != null) {
306                 returnValue = ((Map)container).remove(key);
307             } else {
308                 returnValue = ((Map)container).remove(keyFrom(element, session));
309             }
310             if (returnValue == null) {
311                 return false;
312             } else {
313                 return true;
314             }
315         } catch (UnsupportedOperationException JavaDoc ex) {
316             throw QueryException.methodNotValid(container, "remove(Object element)");
317         }
318     }
319
320     /**
321      * INTERNAL:
322      * Remove element from container which implements the Map interface.
323      */

324     public boolean removeFromWithIdentity(Object JavaDoc element, Object JavaDoc container, AbstractSession session) {
325         boolean found = false;
326         Vector knownKeys = new Vector(1);
327         try {
328             Iterator iterator = ((Map)container).keySet().iterator();
329             while (iterator.hasNext()) {
330                 Object JavaDoc key = iterator.next();
331                 if (((Map)container).get(key) == element) {
332                     knownKeys.addElement(key);
333                     found = true;
334                 }
335             }
336             if (found) {
337                 for (int index = 0; index < knownKeys.size(); ++index) {
338                     ((Map)container).remove(knownKeys.elementAt(index));
339                 }
340             }
341             return found;
342         } catch (UnsupportedOperationException JavaDoc ex) {
343             throw QueryException.methodNotValid(container, "remove(Object element)");
344         }
345     }
346
347     /**
348      * INTERNAL:
349      * Sets the element class which defines the method.
350      */

351     public void setElementClass(Class JavaDoc elementClass) {
352         if (elementClass != null) {
353             elementClassName = elementClass.getName();
354         }
355         
356         this.elementClass = elementClass;
357     }
358
359     /**
360      * INTERNAL:
361      * Validate the container type.
362      */

363     public boolean isValidContainer(Object JavaDoc container) {
364         // PERF: Use instanceof which is inlined, not isAssignable which
365
// is very inefficent.
366
return container instanceof Map;
367     }
368     
369     /**
370      * INTERNAL:
371      * Sets the key name to be used to generate the key in a Map type container
372      * class. The key name, may be the name of a field or method.
373      */

374     public void setKeyName(String JavaDoc keyName, String JavaDoc elementClassName) {
375         // The key name and class name must be held as the policy is used
376
// directly from the mapping.
377
this.keyName = keyName;
378         this.elementClassName = elementClassName;
379     }
380     
381     /**
382      * INTERNAL:
383      * Sets the key name to be used to generate the key in a Map type container
384      * class. The key name, maybe the name of a field or method.
385      */

386     public void setKeyName(String JavaDoc keyName) {
387         this.keyName = keyName;
388     }
389     
390     /**
391      * INTERNAL:
392      * Return the size of container.
393      */

394     public int sizeFor(Object JavaDoc container) {
395         return ((Map)container).size();
396     }
397
398     /**
399      * INTERNAL:
400      * If the key has changed, remove the element and add it back into the target.
401      */

402     public void validateElementAndRehashIfRequired(Object JavaDoc sourceValue, Object JavaDoc targetMap, AbstractSession session, Object JavaDoc targetVersionOfSource) {
403         if (session.isUnitOfWork()) {
404             //this must be a unit of work at this point
405
Object JavaDoc backupValue = ((UnitOfWorkImpl)session).getBackupClone(sourceValue);
406             if (!keyFrom(backupValue, session).equals(keyFrom(sourceValue, session))) {
407                 //the key has been changed. Remove the old value and put back the new one
408
removeFrom(backupValue, targetMap, session);
409                 addInto(targetVersionOfSource, targetMap, session);
410             }
411         }
412     }
413 }
414
Popular Tags