Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/objectstyle/cayenne/map/Entity.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.Collection;
59  import java.util.Collections;
60  import java.util.Iterator;
61  import java.util.Map;
62  import java.util.StringTokenizer;
63  
64  import org.objectstyle.cayenne.exp.Expression;
65  import org.objectstyle.cayenne.exp.ExpressionException;
66  import org.objectstyle.cayenne.query.Query;
67  import org.objectstyle.cayenne.query.SelectQuery;
68  import org.objectstyle.cayenne.util.CayenneMap;
69  
70  /**
71   * An Entity is an abstract descriptor for an entity mapping concept.
72   * Entity can represent either a descriptor of database table or
73   * a persistent object.
74   *
75   * @author Andrei Adamchik
76   */
77  public abstract class Entity extends MapObject {
78      public static final String PATH_SEPARATOR = ".";
79  
80      protected CayenneMap attributes = new CayenneMap(this);
81    protected Map attributesMapRef = Collections.unmodifiableMap(attributes);
82    protected Collection attributesRef = Collections.unmodifiableCollection(attributes.values());
83      protected CayenneMap relationships = new CayenneMap(this);
84      protected Collection relationshipsRef = Collections.unmodifiableCollection(relationships.values());
85      protected CayenneMap queries = new CayenneMap(this);
86  
87      /**
88       * @return parent DataMap of this entity.
89       */
90      public DataMap getDataMap() {
91          return (DataMap) getParent();
92      }
93  
94      /**
95       * Sets parent DataMap of this entity.
96       */
97      public void setDataMap(DataMap dataMap) {
98          this.setParent(dataMap);
99      }
100 
101     /**
102      * Returns a named query associated with this entity.
103      */
104     public SelectQuery getQuery(String queryName) {
105         return (SelectQuery) queries.get(queryName);
106     }
107 
108     /**
109      * Creates a named association of a SelectQuery with this entity. Throws
110      * IllegalArgumentException if query root can not be resolved to this
111      * entity.
112      */
113     public void addQuery(String queryName, SelectQuery query) {
114         if (query == null) {
115             throw new IllegalArgumentException("Attempt to add null query.");
116         }
117 
118         if (queryName == null) {
119             throw new IllegalArgumentException("Attempt to add query with null name.");
120         }
121 
122         // check if this is the right query
123         this.validateQueryRoot(query);
124         queries.put(queryName, query);
125     }
126 
127     /**
128      * Removes a named query from this Entity.
129      */
130     public void removeQuery(String queryName) {
131       queries.remove(queryName);
132     }
133 
134     public void clearQueries() {
135         queries.clear();
136     }
137 
138     /**
139      * Helper method that checks that a Query belongs to this entity by
140      * validating query root object.
141      *
142      * @throws IllegalArgumentException if query does not belong to this entity.
143      */
144     protected abstract void validateQueryRoot(Query query)
145         throws IllegalArgumentException;
146 
147     /**
148      * Returns attribute with name <code>attrName</code>.
149      * Will return null if no attribute with this name exists.
150      */
151     public Attribute getAttribute(String attrName) {
152         return (Attribute) attributes.get(attrName);
153     }
154 
155     /**
156      * Adds new attribute to the entity. If attribute has no name,
157      * IllegalArgumentException is thrown.
158      *
159      * Also sets <code>attr</code>'s entity to be this entity.
160      */
161     public void addAttribute(Attribute attr) {
162         if (attr.getName() == null) {
163             throw new IllegalArgumentException("Attempt to insert unnamed attribute.");
164         }
165 
166         attributes.put(attr.getName(), attr);
167     }
168 
169     /** Removes an attribute named <code>attrName</code>.*/
170     public void removeAttribute(String attrName) {
171         attributes.remove(attrName);
172     }
173 
174     public void clearAttributes() {
175         attributes.clear();
176     }
177 
178     /**
179      * Returns relationship with name <code>relName</code>.
180      * Will return null if no relationship with this name
181      * exists in the entity.
182      */
183     public Relationship getRelationship(String relName) {
184         return (Relationship) relationships.get(relName);
185     }
186 
187     /** Adds new relationship to the entity. */
188     public void addRelationship(Relationship rel) {
189         relationships.put(rel.getName(), rel);
190     }
191 
192     /** Removes a relationship named <code>attrName</code>.*/
193     public void removeRelationship(String relName) {
194         relationships.remove(relName);
195     }
196 
197     public void clearRelationships() {
198         relationships.clear();
199     }
200 
201     public Map getRelationshipMap() {
202         return Collections.unmodifiableMap(relationships);
203     }
204 
205   /**
206    * Returns a collection of Relationships that exist in this entity.
207    */
208   public Collection getRelationships() {
209     return relationshipsRef;
210   }
211 
212     /**
213      * Returns entity attributes as an unmodifiable map.
214      */
215     public Map getAttributeMap() {
216       return attributesMapRef;
217     }
218 
219   /**
220    * Returns entity attributes.
221    */
222   public Collection getAttributes() {
223     return attributesRef;
224   }
225 
226     /**
227      * Processes expression <code>objPathExp</code> and returns an Iterator
228      * of path components that contains a sequence of Attributes and Relationships.
229      * Note that if path is invalid and can not be resolved from this entity,
230      * this method will still return an Iterator, but an attempt to read the first
231      * invalid path component will result in ExpressionException.
232      *
233      * @see org.objectstyle.cayenne.exp.Expression#OBJ_PATH for definition of OBJ_PATH.
234      *
235      * @throws org.objectstyle.cayenne.exp.ExpressionException Exception is thrown if
236      * <code>objPathExp</code> is not of type OBJ_PATH
237      */
238     public Iterator resolvePathComponents(Expression pathExp)
239         throws ExpressionException {
240         if (pathExp.getType() != Expression.OBJ_PATH
241             && pathExp.getType() != Expression.DB_PATH) {
242             StringBuffer msg = new StringBuffer();
243             msg
244                 .append("Invalid expression type: '")
245                 .append(pathExp.getType())
246                 .append("' ('")
247                 .append(Expression.OBJ_PATH)
248                 .append(" or ")
249                 .append(Expression.DB_PATH)
250                 .append("' is expected).");
251 
252             throw new ExpressionException(msg.toString());
253         }
254 
255         return new PathIterator(this, (String) pathExp.getOperand(0));
256     }
257 
258     public Iterator resolvePathComponents(String path)
259         throws ExpressionException {
260         return new PathIterator(this, path);
261     }
262 
263     // Used to return an iterator to callers of 'resolvePathComponents'
264     protected final class PathIterator implements Iterator {
265         private StringTokenizer toks;
266         private Entity currentEnt;
267 
268         PathIterator(Entity ent, String path) {
269           super();
270       this.currentEnt = ent;
271             this.toks = new StringTokenizer(path, PATH_SEPARATOR);
272         }
273 
274         public boolean hasNext() {
275             return toks.hasMoreTokens();
276         }
277 
278         public Object next() {
279             String pathComp = toks.nextToken();
280 
281             // see if this is an attribute
282             Attribute attr = currentEnt.getAttribute(pathComp);
283             if (attr != null) {
284                 // do a sanity check...
285                 if (toks.hasMoreTokens()) {
286                     throw new ExpressionException(
287                         "Attribute must be the last component of the path: '"
288                             + pathComp
289                             + "'.");
290                 }
291 
292                 return attr;
293             }
294 
295             Relationship rel = currentEnt.getRelationship(pathComp);
296             if (rel != null) {
297                 currentEnt = rel.getTargetEntity();
298                 return rel;
299             }
300 
301             // build error message
302             StringBuffer buf = new StringBuffer();
303             buf
304                 .append("Can't resolve path component: [")
305                 .append(currentEnt.getName())
306                 .append('.')
307                 .append(pathComp)
308                 .append("].");
309             throw new ExpressionException(buf.toString());
310         }
311 
312         public void remove() {
313             throw new UnsupportedOperationException("'remove' operation is not supported.");
314         }
315     }
316 }