KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > project > validator > SelectQueryValidator


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56 package org.objectstyle.cayenne.project.validator;
57
58 import java.util.Iterator JavaDoc;
59
60 import org.objectstyle.cayenne.access.QueryEngine;
61 import org.objectstyle.cayenne.exp.Expression;
62 import org.objectstyle.cayenne.exp.ExpressionException;
63 import org.objectstyle.cayenne.exp.TraversalHelper;
64 import org.objectstyle.cayenne.map.DataMap;
65 import org.objectstyle.cayenne.map.Entity;
66 import org.objectstyle.cayenne.project.ProjectPath;
67 import org.objectstyle.cayenne.query.Ordering;
68 import org.objectstyle.cayenne.query.Query;
69 import org.objectstyle.cayenne.query.SelectQuery;
70 import org.objectstyle.cayenne.util.Util;
71
72 /**
73  * Validator for SelectQueries.
74  *
75  * @author Andrei Adamchik
76  * @since 1.1
77  */

78 public class SelectQueryValidator extends TreeNodeValidator {
79
80     public void validateObject(ProjectPath treeNodePath, Validator validator) {
81         SelectQuery query = (SelectQuery) treeNodePath.getObject();
82
83         validateName(query, treeNodePath, validator);
84
85         // Resolve root to Entity for further validation
86
Entity root = validateRoot(query, treeNodePath, validator);
87
88         // validate path-based parts
89
if (root != null) {
90             validateQualifier(root, query.getQualifier(), treeNodePath, validator);
91
92             Iterator JavaDoc orderings = query.getOrderings().iterator();
93             while (orderings.hasNext()) {
94                 validateOrdering(
95                         root,
96                         (Ordering) orderings.next(),
97                         treeNodePath,
98                         validator);
99             }
100
101             Iterator JavaDoc prefecthes = query.getPrefetches().iterator();
102             while (prefecthes.hasNext()) {
103                 validatePrefetch(
104                         root,
105                         (String JavaDoc) prefecthes.next(),
106                         treeNodePath,
107                         validator);
108             }
109         }
110     }
111
112     protected Entity validateRoot(Query query, ProjectPath path, Validator validator) {
113         DataMap map = (DataMap) path.firstInstanceOf(DataMap.class);
114         if (query.getRoot() == null && map != null) {
115             validator.registerWarning("Query has no root", path);
116             return null;
117         }
118
119         if (query.getRoot() == map) {
120             // map-level query... everything is clean
121
return null;
122         }
123
124         if (map == null) {
125             // maybe standalone entity, otherwise bail...
126
return (query.getRoot() instanceof Entity) ? (Entity) query.getRoot() : null;
127         }
128
129         // can't validate Class root - it is likely not accessible from here...
130
if (query.getRoot() instanceof Class JavaDoc) {
131             return null;
132         }
133
134         // resolve entity
135
QueryEngine parent = (QueryEngine) path.firstInstanceOf(QueryEngine.class);
136
137         if (parent == null) {
138             return null;
139         }
140
141         Entity entity = parent.getEntityResolver().lookupObjEntity(query);
142         if (entity == null) {
143             entity = parent.getEntityResolver().lookupDbEntity(query);
144         }
145
146         // if no entity is found register warning and return null
147
if (entity == null) {
148             validator.registerWarning("Unknown query root.", path);
149             return null;
150         }
151
152         return entity;
153     }
154
155     protected void validateName(Query query, ProjectPath path, Validator validator) {
156         String JavaDoc name = query.getName();
157
158         // Must have name
159
if (Util.isEmptyString(name)) {
160             validator.registerError("Unnamed SelectQuery.", path);
161             return;
162         }
163
164         DataMap map = (DataMap) path.getObjectParent();
165         if (map == null) {
166             return;
167         }
168
169         // check for duplicate names in the parent context
170

171         Iterator JavaDoc it = map.getQueries().iterator();
172         while (it.hasNext()) {
173             Query otherQuery = (Query) it.next();
174             if (otherQuery == query) {
175                 continue;
176             }
177
178             if (name.equals(otherQuery.getName())) {
179                 validator.registerError("Duplicate Query name: " + name + ".", path);
180                 break;
181             }
182         }
183     }
184
185     protected void validateQualifier(
186             Entity entity,
187             Expression qualifier,
188             ProjectPath path,
189             Validator validator) {
190
191         try {
192             testExpression(entity, qualifier);
193         }
194         catch (ExpressionException e) {
195             validator.registerWarning(buildValidationMessage(
196                     e,
197                     "Invalid path in qualifier"), path);
198         }
199     }
200
201     protected void validateOrdering(
202             Entity entity,
203             Ordering ordering,
204             ProjectPath path,
205             Validator validator) {
206
207         if (ordering == null) {
208             return;
209         }
210
211         try {
212             testExpression(entity, ordering.getSortSpec());
213         }
214         catch (ExpressionException e) {
215             validator
216                     .registerWarning(buildValidationMessage(e, "Invalid ordering"), path);
217         }
218     }
219
220     protected void validatePrefetch(
221             Entity entity,
222             String JavaDoc prefetch,
223             ProjectPath path,
224             Validator validator) {
225
226         if (prefetch == null) {
227             return;
228         }
229
230         try {
231             testExpression(entity, Expression.fromString(prefetch));
232         }
233         catch (ExpressionException e) {
234             validator
235                     .registerWarning(buildValidationMessage(e, "Invalid prefetch"), path);
236         }
237     }
238
239     private void testExpression(Entity rootEntity, Expression exp)
240             throws ExpressionException {
241
242         if (exp != null) {
243             exp.traverse(new EntityExpressionValidator(rootEntity));
244         }
245     }
246
247     private String JavaDoc buildValidationMessage(ExpressionException e, String JavaDoc prefix) {
248         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(prefix);
249         if (e.getExpressionString() != null) {
250             buffer.append(": '").append(e.getExpressionString()).append("'");
251         }
252
253         buffer.append(".");
254         return buffer.toString();
255     }
256
257     final class EntityExpressionValidator extends TraversalHelper {
258
259         Entity rootEntity;
260
261         EntityExpressionValidator(Entity rootEntity) {
262             this.rootEntity = rootEntity;
263         }
264
265         public void startNode(Expression node, Expression parentNode) {
266             // check if path nodes are compatibe with root entity
267
if (node.getType() == Expression.OBJ_PATH
268                     || node.getType() == Expression.DB_PATH) {
269                 // this will throw an exception if the path is invalid
270
node.evaluate(rootEntity);
271             }
272         }
273     }
274 }
Popular Tags