KickJava   Java API By Example, From Geeks To Geeks.

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


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.project.validator;
21
22 import java.util.Iterator JavaDoc;
23
24 import org.apache.cayenne.access.QueryEngine;
25 import org.apache.cayenne.exp.Expression;
26 import org.apache.cayenne.exp.ExpressionException;
27 import org.apache.cayenne.exp.TraversalHelper;
28 import org.apache.cayenne.map.DataMap;
29 import org.apache.cayenne.map.Entity;
30 import org.apache.cayenne.project.ProjectPath;
31 import org.apache.cayenne.query.Ordering;
32 import org.apache.cayenne.query.PrefetchTreeNode;
33 import org.apache.cayenne.query.Query;
34 import org.apache.cayenne.query.SelectQuery;
35 import org.apache.cayenne.util.Util;
36
37 /**
38  * Validator for SelectQueries.
39  *
40  * @author Andrus Adamchik
41  * @since 1.1
42  */

43 public class SelectQueryValidator extends TreeNodeValidator {
44
45     public void validateObject(ProjectPath treeNodePath, Validator validator) {
46         SelectQuery query = (SelectQuery) treeNodePath.getObject();
47
48         validateName(query, treeNodePath, validator);
49
50         // Resolve root to Entity for further validation
51
Entity root = validateRoot(query, treeNodePath, validator);
52
53         // validate path-based parts
54
if (root != null) {
55             validateQualifier(root, query.getQualifier(), treeNodePath, validator);
56
57             Iterator JavaDoc orderings = query.getOrderings().iterator();
58             while (orderings.hasNext()) {
59                 validateOrdering(
60                         root,
61                         (Ordering) orderings.next(),
62                         treeNodePath,
63                         validator);
64             }
65
66             if (query.getPrefetchTree() != null) {
67                 Iterator JavaDoc prefetches = query
68                         .getPrefetchTree()
69                         .nonPhantomNodes()
70                         .iterator();
71                 while (prefetches.hasNext()) {
72                     validatePrefetch(root, ((PrefetchTreeNode) prefetches.next())
73                             .getPath(), treeNodePath, validator);
74                 }
75             }
76         }
77     }
78
79     protected Entity validateRoot(SelectQuery query, ProjectPath path, Validator validator) {
80         DataMap map = (DataMap) path.firstInstanceOf(DataMap.class);
81         if (query.getRoot() == null && map != null) {
82             validator.registerWarning("Query has no root", path);
83             return null;
84         }
85
86         if (query.getRoot() == map) {
87             // map-level query... everything is clean
88
return null;
89         }
90
91         if (map == null) {
92             // maybe standalone entity, otherwise bail...
93
return (query.getRoot() instanceof Entity) ? (Entity) query.getRoot() : null;
94         }
95
96         if (query.getRoot() instanceof Entity) {
97             return (Entity) query.getRoot();
98         }
99
100         // can't validate Class root - it is likely not accessible from here...
101
if (query.getRoot() instanceof Class JavaDoc) {
102             return null;
103         }
104
105         // resolve entity
106
if (query.getRoot() instanceof String JavaDoc) {
107
108             QueryEngine parent = (QueryEngine) path.firstInstanceOf(QueryEngine.class);
109
110             if (parent != null) {
111                 return parent.getEntityResolver().getObjEntity((String JavaDoc) query.getRoot());
112             }
113         }
114
115         return null;
116     }
117
118     protected void validateName(Query query, ProjectPath path, Validator validator) {
119         String JavaDoc name = query.getName();
120
121         // Must have name
122
if (Util.isEmptyString(name)) {
123             validator.registerError("Unnamed SelectQuery.", path);
124             return;
125         }
126
127         DataMap map = (DataMap) path.getObjectParent();
128         if (map == null) {
129             return;
130         }
131
132         // check for duplicate names in the parent context
133

134         Iterator JavaDoc it = map.getQueries().iterator();
135         while (it.hasNext()) {
136             Query otherQuery = (Query) it.next();
137             if (otherQuery == query) {
138                 continue;
139             }
140
141             if (name.equals(otherQuery.getName())) {
142                 validator.registerError("Duplicate Query name: " + name + ".", path);
143                 break;
144             }
145         }
146     }
147
148     protected void validateQualifier(
149             Entity entity,
150             Expression qualifier,
151             ProjectPath path,
152             Validator validator) {
153
154         try {
155             testExpression(entity, qualifier);
156         }
157         catch (ExpressionException e) {
158             validator.registerWarning(buildValidationMessage(
159                     e,
160                     "Invalid path in qualifier"), path);
161         }
162     }
163
164     protected void validateOrdering(
165             Entity entity,
166             Ordering ordering,
167             ProjectPath path,
168             Validator validator) {
169
170         if (ordering == null) {
171             return;
172         }
173
174         try {
175             testExpression(entity, ordering.getSortSpec());
176         }
177         catch (ExpressionException e) {
178             validator
179                     .registerWarning(buildValidationMessage(e, "Invalid ordering"), path);
180         }
181     }
182
183     protected void validatePrefetch(
184             Entity entity,
185             String JavaDoc prefetch,
186             ProjectPath path,
187             Validator validator) {
188
189         if (prefetch == null) {
190             return;
191         }
192
193         try {
194             testExpression(entity, Expression.fromString(prefetch));
195         }
196         catch (ExpressionException e) {
197             validator
198                     .registerWarning(buildValidationMessage(e, "Invalid prefetch"), path);
199         }
200     }
201
202     private void testExpression(Entity rootEntity, Expression exp)
203             throws ExpressionException {
204
205         if (exp != null) {
206             exp.traverse(new EntityExpressionValidator(rootEntity));
207         }
208     }
209
210     private String JavaDoc buildValidationMessage(ExpressionException e, String JavaDoc prefix) {
211         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(prefix);
212         if (e.getExpressionString() != null) {
213             buffer.append(": '").append(e.getExpressionString()).append("'");
214         }
215
216         buffer.append(".");
217         return buffer.toString();
218     }
219
220     final class EntityExpressionValidator extends TraversalHelper {
221
222         Entity rootEntity;
223
224         EntityExpressionValidator(Entity rootEntity) {
225             this.rootEntity = rootEntity;
226         }
227
228         public void startNode(Expression node, Expression parentNode) {
229             // check if path nodes are compatibe with root entity
230
if (node.getType() == Expression.OBJ_PATH
231                     || node.getType() == Expression.DB_PATH) {
232                 // this will throw an exception if the path is invalid
233
node.evaluate(rootEntity);
234             }
235         }
236     }
237 }
238
Popular Tags