KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > DataObjectUtils


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

19
20 package org.apache.cayenne;
21
22 import java.util.Collections JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import org.apache.cayenne.map.DbAttribute;
27 import org.apache.cayenne.map.DbEntity;
28 import org.apache.cayenne.map.ObjEntity;
29 import org.apache.cayenne.query.ObjectIdQuery;
30 import org.apache.cayenne.query.Query;
31
32 /**
33  * A collection of utility methods to work with DataObjects.
34  * <p>
35  * <i>DataObjects and Primary Keys: All methods that allow to extract primary key values
36  * or use primary keys to find objects are provided for convenience. Still the author's
37  * belief is that integer sequential primary keys are meaningless in the object model and
38  * are pure database artifacts. Therefore relying heavily on direct access to PK provided
39  * via this class (or other such Cayenne API) is not a clean design practice in many
40  * cases, and sometimes may actually lead to security issues. </i>
41  * </p>
42  *
43  * @since 1.1
44  * @author Andrus Adamchik
45  */

46 public final class DataObjectUtils {
47
48     /**
49      * Returns an int primary key value for a persistent object. Only works for single
50      * column numeric primary keys. If an object is transient or has an ObjectId that can
51      * not be converted to an int PK, an exception is thrown.
52      */

53     public static int intPKForObject(Persistent dataObject) {
54         Object JavaDoc value = pkForObject(dataObject);
55
56         if (!(value instanceof Number JavaDoc)) {
57             throw new CayenneRuntimeException("PK is not a number: "
58                     + dataObject.getObjectId());
59         }
60
61         return ((Number JavaDoc) value).intValue();
62     }
63
64     /**
65      * Returns a primary key value for a persistent object. Only works for single column
66      * primary keys. If an object is transient or has a compound ObjectId, an exception is
67      * thrown.
68      */

69     public static Object JavaDoc pkForObject(Persistent dataObject) {
70         Map JavaDoc pk = extractObjectId(dataObject);
71
72         if (pk.size() != 1) {
73             throw new CayenneRuntimeException("Expected single column PK, got "
74                     + pk.size()
75                     + " columns, ID: "
76                     + pk);
77         }
78
79         Map.Entry JavaDoc pkEntry = (Map.Entry JavaDoc) pk.entrySet().iterator().next();
80         return pkEntry.getValue();
81     }
82
83     /**
84      * Returns a primary key map for a persistent object. This method is the most generic
85      * out of all methods for primary key retrieval. It will work for all possible types
86      * of primary keys. If an object is transient, an exception is thrown.
87      */

88     public static Map JavaDoc compoundPKForObject(Persistent dataObject) {
89         return Collections.unmodifiableMap(extractObjectId(dataObject));
90     }
91
92     static Map JavaDoc extractObjectId(Persistent dataObject) {
93         if (dataObject == null) {
94             throw new IllegalArgumentException JavaDoc("Null DataObject");
95         }
96
97         ObjectId id = dataObject.getObjectId();
98         if (!id.isTemporary()) {
99             return id.getIdSnapshot();
100         }
101
102         // replacement ID is more tricky... do some sanity check...
103
if (id.isReplacementIdAttached()) {
104             ObjEntity objEntity = dataObject
105                     .getObjectContext()
106                     .getEntityResolver()
107                     .lookupObjEntity(dataObject);
108
109             if (objEntity != null) {
110                 DbEntity entity = objEntity.getDbEntity();
111                 if (entity != null && entity.isFullReplacementIdAttached(id)) {
112                     return id.getReplacementIdMap();
113                 }
114             }
115         }
116
117         throw new CayenneRuntimeException("Can't get primary key from temporary id.");
118     }
119
120     /**
121      * Returns an object matching an int primary key. If the object is mapped to use
122      * non-integer PK or a compound PK, CayenneRuntimeException is thrown.
123      * <p>
124      * If this object is already cached in the ObjectStore, it is returned without a
125      * query. Otherwise a query is built and executed against the database.
126      * </p>
127      *
128      * @see #objectForPK(ObjectContext, ObjectId)
129      */

130     public static Object JavaDoc objectForPK(ObjectContext context, Class JavaDoc dataObjectClass, int pk) {
131         return objectForPK(context, buildId(context, dataObjectClass, new Integer JavaDoc(pk)));
132     }
133
134     /**
135      * Returns an object matching an Object primary key. If the object is mapped to use a
136      * compound PK, CayenneRuntimeException is thrown.
137      * <p>
138      * If this object is already cached in the ObjectStore, it is returned without a
139      * query. Otherwise a query is built and executed against the database.
140      * </p>
141      *
142      * @see #objectForPK(ObjectContext, ObjectId)
143      */

144     public static Object JavaDoc objectForPK(
145             ObjectContext context,
146             Class JavaDoc dataObjectClass,
147             Object JavaDoc pk) {
148
149         return objectForPK(context, buildId(context, dataObjectClass, pk));
150     }
151
152     /**
153      * Returns an object matching a primary key. PK map parameter should use database PK
154      * column names as keys.
155      * <p>
156      * If this object is already cached in the ObjectStore, it is returned without a
157      * query. Otherwise a query is built and executed against the database.
158      * </p>
159      *
160      * @see #objectForPK(ObjectContext, ObjectId)
161      */

162     public static Object JavaDoc objectForPK(ObjectContext context, Class JavaDoc dataObjectClass, Map JavaDoc pk) {
163
164         ObjEntity entity = context.getEntityResolver().lookupObjEntity(dataObjectClass);
165         if (entity == null) {
166             throw new CayenneRuntimeException("Non-existent ObjEntity for class: "
167                     + dataObjectClass);
168         }
169
170         return objectForPK(context, new ObjectId(entity.getName(), pk));
171     }
172
173     /**
174      * Returns an object matching an int primary key. If the object is mapped to use
175      * non-integer PK or a compound PK, CayenneRuntimeException is thrown.
176      * <p>
177      * If this object is already cached in the ObjectStore, it is returned without a
178      * query. Otherwise a query is built and executed against the database.
179      * </p>
180      *
181      * @see #objectForPK(ObjectContext, ObjectId)
182      */

183     public static Object JavaDoc objectForPK(ObjectContext context, String JavaDoc objEntityName, int pk) {
184         return objectForPK(context, buildId(context, objEntityName, new Integer JavaDoc(pk)));
185     }
186
187     /**
188      * Returns an object matching an Object primary key. If the object is mapped to use a
189      * compound PK, CayenneRuntimeException is thrown.
190      * <p>
191      * If this object is already cached in the ObjectStore, it is returned without a
192      * query. Otherwise a query is built and executed against the database.
193      * </p>
194      *
195      * @see #objectForPK(ObjectContext, ObjectId)
196      */

197     public static Object JavaDoc objectForPK(
198             ObjectContext context,
199             String JavaDoc objEntityName,
200             Object JavaDoc pk) {
201         return objectForPK(context, buildId(context, objEntityName, pk));
202     }
203
204     /**
205      * Returns an object matching a primary key. PK map parameter should use database PK
206      * column names as keys.
207      * <p>
208      * If this object is already cached in the ObjectStore, it is returned without a
209      * query. Otherwise a query is built and executed against the database.
210      * </p>
211      *
212      * @see #objectForPK(ObjectContext, ObjectId)
213      */

214     public static Object JavaDoc objectForPK(ObjectContext context, String JavaDoc objEntityName, Map JavaDoc pk) {
215         if (objEntityName == null) {
216             throw new IllegalArgumentException JavaDoc("Null ObjEntity name.");
217         }
218
219         return objectForPK(context, new ObjectId(objEntityName, pk));
220     }
221
222     /**
223      * Returns an object matching ObjectId. If this object is already cached in the
224      * ObjectStore, it is returned without a query. Otherwise a query is built and
225      * executed against the database.
226      *
227      * @return A persistent object that matched the id, null if no matching objects were
228      * found
229      * @throws CayenneRuntimeException if more than one object matched ObjectId.
230      */

231     public static Object JavaDoc objectForPK(ObjectContext context, ObjectId id) {
232         return DataObjectUtils.objectForQuery(context, new ObjectIdQuery(
233                 id,
234                 false,
235                 ObjectIdQuery.CACHE));
236     }
237
238     /**
239      * Returns an object or a DataRow that is a result of a given query. If query returns
240      * more than one object, an exception is thrown. If query returns no objects, null is
241      * returned.
242      *
243      * @since 1.2
244      */

245     public static Object JavaDoc objectForQuery(ObjectContext context, Query query) {
246         List JavaDoc objects = context.performQuery(query);
247
248         if (objects.size() == 0) {
249             return null;
250         }
251         else if (objects.size() > 1) {
252             throw new CayenneRuntimeException(
253                     "Expected zero or one object, instead query matched: "
254                             + objects.size());
255         }
256
257         return objects.get(0);
258     }
259
260     static ObjectId buildId(ObjectContext context, String JavaDoc objEntityName, Object JavaDoc pk) {
261         if (pk == null) {
262             throw new IllegalArgumentException JavaDoc("Null PK");
263         }
264
265         if (objEntityName == null) {
266             throw new IllegalArgumentException JavaDoc("Null ObjEntity name.");
267         }
268
269         ObjEntity entity = context.getEntityResolver().getObjEntity(objEntityName);
270         if (entity == null) {
271             throw new CayenneRuntimeException("Non-existent ObjEntity: " + objEntityName);
272         }
273
274         DbEntity dbEntity = entity.getDbEntity();
275         if (dbEntity == null) {
276             throw new CayenneRuntimeException("No DbEntity for ObjEntity: "
277                     + entity.getName());
278         }
279
280         List JavaDoc pkAttributes = dbEntity.getPrimaryKey();
281         if (pkAttributes.size() != 1) {
282             throw new CayenneRuntimeException("PK contains "
283                     + pkAttributes.size()
284                     + " columns, expected 1.");
285         }
286
287         DbAttribute attr = (DbAttribute) pkAttributes.get(0);
288         return new ObjectId(objEntityName, attr.getName(), pk);
289     }
290
291     static ObjectId buildId(ObjectContext context, Class JavaDoc dataObjectClass, Object JavaDoc pk) {
292         if (pk == null) {
293             throw new IllegalArgumentException JavaDoc("Null PK");
294         }
295
296         if (dataObjectClass == null) {
297             throw new IllegalArgumentException JavaDoc("Null DataObject class.");
298         }
299
300         ObjEntity entity = context.getEntityResolver().lookupObjEntity(dataObjectClass);
301         if (entity == null) {
302             throw new CayenneRuntimeException("Unmapped DataObject Class: "
303                     + dataObjectClass.getName());
304         }
305
306         DbEntity dbEntity = entity.getDbEntity();
307         if (dbEntity == null) {
308             throw new CayenneRuntimeException("No DbEntity for ObjEntity: "
309                     + entity.getName());
310         }
311
312         List JavaDoc pkAttributes = dbEntity.getPrimaryKey();
313         if (pkAttributes.size() != 1) {
314             throw new CayenneRuntimeException("PK contains "
315                     + pkAttributes.size()
316                     + " columns, expected 1.");
317         }
318
319         DbAttribute attr = (DbAttribute) pkAttributes.get(0);
320         return new ObjectId(entity.getName(), attr.getName(), pk);
321     }
322
323     // not intended for instantiation
324
private DataObjectUtils() {
325     }
326 }
327
Popular Tags