Source code: org/objectstyle/cayenne/map/ObjEntity.java
1 /* ====================================================================
2 *
3 * The ObjectStyle Group Software License, Version 1.0
4 *
5 * Copyright (c) 2002-2003 The ObjectStyle Group
6 * and individual authors of the software. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution, if
21 * any, must include the following acknowlegement:
22 * "This product includes software developed by the
23 * ObjectStyle Group (http://objectstyle.org/)."
24 * Alternately, this acknowlegement may appear in the software itself,
25 * if and wherever such third-party acknowlegements normally appear.
26 *
27 * 4. The names "ObjectStyle Group" and "Cayenne"
28 * must not be used to endorse or promote products derived
29 * from this software without prior written permission. For written
30 * permission, please contact andrus@objectstyle.org.
31 *
32 * 5. Products derived from this software may not be called "ObjectStyle"
33 * nor may "ObjectStyle" appear in their names without prior written
34 * permission of the ObjectStyle Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the ObjectStyle Group. For more
52 * information on the ObjectStyle Group, please see
53 * <http://objectstyle.org/>.
54 *
55 */
56 package org.objectstyle.cayenne.map;
57
58 import java.util.HashMap;
59 import java.util.Iterator;
60 import java.util.List;
61 import java.util.Map;
62
63 import org.objectstyle.cayenne.CayenneException;
64 import org.objectstyle.cayenne.CayenneRuntimeException;
65 import org.objectstyle.cayenne.ObjectId;
66 import org.objectstyle.cayenne.query.Query;
67 import org.objectstyle.cayenne.util.Util;
68
69 /**
70 * ObjEntity is a mapping descriptor for a DataObject Java class.
71 * It contains the information about the Java class itself, as well
72 * as its mapping to the DbEntity layer.
73 *
74 * @author Misha Shengaout
75 * @author Andrei Adamchik
76 */
77 public class ObjEntity extends Entity {
78 protected String superClassName;
79 protected String className;
80 protected DbEntity dbEntity;
81 protected boolean readOnly;
82
83 public ObjEntity() {
84 super();
85 }
86
87 public ObjEntity(String name) {
88 this();
89 this.setName(name);
90 }
91
92 /**
93 * Returns Java class of persistent objects described by this entity.
94 * Casts any thrown exceptions into CayenneRuntimeException.
95 */
96 public Class getJavaClass() {
97 try {
98 return Class.forName(this.getClassName());
99 } catch (ClassNotFoundException e) {
100 throw new CayenneRuntimeException(
101 "Failed to load class for name '"
102 + this.getClassName()
103 + "': "
104 + e.getMessage(),
105 e);
106 }
107 }
108
109 /** Returns the name of the corresponding data object class */
110 public String getClassName() {
111 return className;
112 }
113
114 /** Sets the name of the data object class described by this obj entity*/
115 public void setClassName(String className) {
116 this.className = className;
117 }
118 /**
119 *
120 * Returns the fully qualified name of the super class of the data object class for this entity
121 * Used in the modeller and in class generation only, not at "runtime"
122 * @return String
123 */
124 public String getSuperClassName() {
125 return superClassName;
126 }
127
128 /**
129 * Sets the name of the super class of the data object class for this entity
130 * Used in the modeller and in class generation only, not at "runtime"
131 * @param superClassName fully qualified class namee
132 */
133 public void setSuperClassName(String parentClassName) {
134 this.superClassName = parentClassName;
135 }
136
137 /** Returns a DbEntity that this ObjEntity is mapped to. */
138 public DbEntity getDbEntity() {
139 return dbEntity;
140 }
141
142 /** Sets the DbEntity used by this ObjEntity. */
143 public void setDbEntity(DbEntity dbEntity) {
144 this.dbEntity = dbEntity;
145 }
146
147 /**
148 * Returns ObjAttribute of this entity that maps to <code>dbAttr</code>
149 * parameter. Returns null if no such attribute is found.
150 */
151 public ObjAttribute getAttributeForDbAttribute(DbAttribute dbAttr) {
152 Iterator it = getAttributeMap().values().iterator();
153 while (it.hasNext()) {
154 ObjAttribute objAttr = (ObjAttribute) it.next();
155 if (objAttr.getDbAttribute() == dbAttr)
156 return objAttr;
157 }
158 return null;
159 }
160
161 /**
162 * Returns ObjRelationship of this entity that maps to
163 * <code>dbRel</code> parameter. Returns null if no
164 * such relationship is found.
165 */
166 public ObjRelationship getRelationshipForDbRelationship(DbRelationship dbRel) {
167 Iterator it = getRelationshipMap().values().iterator();
168 while (it.hasNext()) {
169 ObjRelationship objRel = (ObjRelationship) it.next();
170 List relList = objRel.getDbRelationships();
171 if (relList.size() != 1)
172 continue;
173
174 if (relList.get(0) == dbRel)
175 return objRel;
176 }
177 return null;
178 }
179
180 /**
181 * Creates an id snapshot (the key/value pairs for the pk of the object)
182 * from the values in object snapshot.
183 * If needed attributes are missing in a snapshot or if it is null,
184 * CayenneRuntimeException is thrown.
185 */
186 public Map idSnapshotMapFromSnapshot(Map objectSnapshot) {
187 Map idMap = new HashMap();
188 Iterator it = getDbEntity().getPrimaryKey().iterator();
189 while (it.hasNext()) {
190 DbAttribute attr = (DbAttribute) it.next();
191 Object val = objectSnapshot.get(attr.getName());
192 if (val == null) {
193 throw new CayenneRuntimeException(
194 "Null value for '"
195 + attr.getName()
196 + "'. Snapshot: "
197 + objectSnapshot);
198 }
199
200 idMap.put(attr.getName(), val);
201 }
202 return idMap;
203 }
204
205 /**
206 * Creates an object id from the values in object snapshot.
207 * If needed attributes are missing in a snapshot or if it is null,
208 * CayenneRuntimeException is thrown.
209 */
210 public ObjectId objectIdFromSnapshot(Map objectSnapshot) {
211 Map idMap = this.idSnapshotMapFromSnapshot(objectSnapshot);
212 Class objClass;
213 try {
214 objClass = Class.forName(this.getClassName());
215 } catch (ClassNotFoundException e) {
216 throw new CayenneRuntimeException(
217 "Failed to load class for name "
218 + this.getClassName()
219 + " because "
220 + e.getMessage());
221 }
222 ObjectId id = new ObjectId(objClass, idMap);
223 return id;
224 }
225
226 /** Clears all the mapping between this obj entity and its current db entity.
227 * Clears mapping between entities, attributes and relationships. */
228 public void clearDbMapping() {
229 if (dbEntity == null)
230 return;
231
232 Iterator it = getAttributeMap().values().iterator();
233 while (it.hasNext()) {
234 ObjAttribute objAttr = (ObjAttribute) it.next();
235 DbAttribute dbAttr = objAttr.getDbAttribute();
236 if (null != dbAttr) {
237 objAttr.setDbAttribute(null);
238 }
239 }
240
241 Iterator rels = this.getRelationships().iterator();
242 while (rels.hasNext()) {
243 ((ObjRelationship) rels.next()).clearDbRelationships();
244 }
245
246 dbEntity = null;
247 }
248
249 /**
250 * Returns <code>true</code> if this ObjEntity represents
251 * a set of read-only objects.
252 *
253 * @return boolean
254 */
255 public boolean isReadOnly() {
256 return readOnly;
257 }
258
259 public void setReadOnly(boolean readOnly) {
260 this.readOnly = readOnly;
261 }
262
263 protected void validateQueryRoot(Query query)
264 throws IllegalArgumentException {
265
266 if ((query.getRoot() instanceof Class)
267 && ((Class) query.getRoot()).getName().equals(getClassName())) {
268 return;
269 }
270
271 if (query.getRoot() == this) {
272 return;
273 }
274
275 if (Util.nullSafeEquals(getName(), query.getRoot())) {
276 return;
277 }
278
279 throw new IllegalArgumentException(
280 "Wrong query root for ObjEntity: " + query.getRoot());
281 }
282
283 public void validate() throws CayenneException {
284 if (getName() == null)
285 throw new CayenneException("ObjEntity name not defined.");
286
287 String head = "ObjEntity: " + getName();
288
289 if (getDbEntity() == null)
290 throw new CayenneException(head + "DbEntity not defined.");
291
292 if (getClassName() == null)
293 throw new CayenneException(head + "ObjEntity's class not defined.");
294
295 Iterator it = getAttributeMap().values().iterator();
296 while (it.hasNext()) {
297 ObjAttribute objAttr = (ObjAttribute) it.next();
298 objAttr.validate();
299
300 if (!readOnly
301 && objAttr.isCompound()
302 && !objAttr.mapsToDependentDbEntity()) {
303 throw new CayenneException(
304 head
305 + "ObjAttribute: "
306 + objAttr.getName()
307 + " compound, read only.");
308 }
309 }
310 }
311 }