KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > ejb > query > ResolveContext


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.ejb.query;
13
14 import com.versant.core.metadata.ModelMetaData;
15 import com.versant.core.metadata.FieldMetaData;
16 import com.versant.core.metadata.ClassMetaData;
17 import com.versant.core.common.BindingSupportImpl;
18 import com.versant.core.common.Debug;
19
20 import java.util.HashMap JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.io.PrintStream JavaDoc;
25
26 /**
27  * Information collected and used during a Node.resolve call (e.g.
28  * identification variables and so on).
29  */

30 public class ResolveContext {
31
32     private final ModelMetaData mmd;
33     private final Map JavaDoc idVarMap = new HashMap JavaDoc(16);
34     private NavRoot[] roots = new NavRoot[2];
35     private int rootCount;
36
37     private Map JavaDoc paramMap; // param name or Integer number -> ParamUsage list
38
private boolean usingPositionalParameters;
39
40     private ParamUsage[] NO_PARAMS = new ParamUsage[0];
41
42     /**
43      * Tracks usage of a parameter within the query String. Each time
44      * a parameter is used one of these is added to its list in
45      * paramMap.
46      */

47     public static class ParamUsage {
48
49         private ParameterNode paramNode;
50         private ParamUsage next;
51         private int index;
52         public Object JavaDoc storeObject;
53
54         public ParamUsage(ParameterNode paramNode, int index) {
55             this.paramNode = paramNode;
56             this.index = index;
57         }
58
59         public ParameterNode getParamNode() {
60             return paramNode;
61         }
62
63         public ParamUsage getNext() {
64             return next;
65         }
66
67         /**
68          * This defines the order that the parameters where addded in with
69          * the first having index 0.
70          */

71         public int getIndex() {
72             return index;
73         }
74     }
75
76     public ResolveContext(ModelMetaData mmd) {
77         this.mmd = mmd;
78     }
79
80     public ModelMetaData getModelMetaData() {
81         return mmd;
82     }
83
84     /**
85      * Throw a user exception of some kind. This is invoked for user errors
86      * in the query (e.g. duplicate identification variables). The node
87      * parameter is used to provide a line and column reference to the
88      * original query string.
89      */

90     public RuntimeException JavaDoc createUserException(String JavaDoc msg, Node node) {
91         return BindingSupportImpl.getInstance().invalidOperation(msg);
92     }
93
94     /**
95      * Get the identification variable for the identifier or null if
96      * not found.
97      */

98     public NavBase getIdVar(String JavaDoc identifier) {
99         return (NavBase)idVarMap.get(identifier);
100     }
101
102     /**
103      * Add an identification variable for an identifier.
104      */

105     public void addIdVar(String JavaDoc identifier, NavBase navBase) {
106         idVarMap.put(identifier, navBase);
107         if (navBase instanceof NavRoot) {
108             if (rootCount == roots.length) {
109                 NavRoot[] a = new NavRoot[rootCount * 2];
110                 System.arraycopy(roots, 0, a, 0, rootCount);
111                 roots = a;
112             }
113             roots[rootCount++] = (NavRoot)navBase;
114         }
115     }
116
117     /**
118      * Get the number of roots.
119      */

120     public int getRootCount() {
121         return rootCount;
122     }
123
124     /**
125      * Get the root with index.
126      */

127     public NavRoot getRoot(int index) {
128         if (Debug.DEBUG) {
129             if (index >= rootCount) {
130                 throw BindingSupportImpl.getInstance().internal(
131                         "index >= rootCount: " + index + " >= " + rootCount);
132             }
133         }
134         return roots[index];
135     }
136
137     /**
138      * Throw a duplicate ID var exception if identifier already exists.
139      */

140     public void checkIdVarDoesNotExist(String JavaDoc identifier, Node node) {
141         NavBase dup = getIdVar(identifier);
142         if (dup != null) {
143             throw createUserException("Duplicate identification variable: " +
144                     identifier, node);
145         }
146     }
147
148     /**
149      * Get the identification variable for the identifier or throw an
150      * exception if not found.
151      */

152     public NavBase checkIdVarExists(String JavaDoc identifier, Node node) {
153         NavBase ans = getIdVar(identifier);
154         if (ans == null) {
155             throw createUserException("Unknown identification variable: " +
156                     identifier, node);
157         }
158         return ans;
159     }
160
161     /**
162      * Resolve a path into a NavField. A new path is created in the tree
163      * starting at the identification variable if necessary.
164      */

165     public NavBase resolveJoinPath(PathNode path, boolean outer, boolean fetch) {
166         return resolveJoinPath(path, outer, fetch, path.size());
167     }
168
169     /**
170      * Resolve a path sz identifiers deep into a NavBase. A new path is
171      * created in the tree starting at the identification variable if
172      * necessary.
173      */

174     public NavBase resolveJoinPath(PathNode path, boolean outer, boolean fetch,
175             int sz) {
176         String JavaDoc idVarName = path.get(0);
177         NavBase pos = checkIdVarExists(idVarName, path);
178         for (int i = 1; i < sz; i++) {
179             String JavaDoc name = path.get(i);
180             NavField f = pos.findChild(name, outer, fetch);
181             if (f == null) {
182                 ClassMetaData cmd = pos.getNavClassMetaData();
183                 if (cmd == null) {
184                     throw createUserException("Field " + f.getFmd().getQName() +
185                             " may not be navigated", path);
186                 }
187                 FieldMetaData fmd = cmd.getFieldMetaData(name);
188                 if (fmd == null) {
189                     throw createUserException("No such field '" + name +
190                             "' on " + cmd.qname, path);
191                 }
192                 f = new NavField(fmd, pos, outer, fetch);
193             }
194             pos = f;
195         }
196         return pos;
197     }
198
199     public ParamUsage addParameterNode(ParameterNode param) {
200         if (paramMap == null) {
201             usingPositionalParameters = param.isPositional();
202             paramMap = new HashMap JavaDoc(8);
203         } else {
204             if (usingPositionalParameters != param.isPositional()) {
205                 throw createUserException(
206                         "Positional and named parameters may not be mixed", param);
207             }
208         }
209         ParamUsage ans = new ParamUsage(param, paramMap.size());
210         Object JavaDoc key = param.getName();
211         ParamUsage u = (ParamUsage)paramMap.get(key);
212         if (u != null) {
213             for (; u.next != null; u = u.next);
214             u.next = ans;
215         } else {
216             paramMap.put(key, ans);
217         }
218         return ans;
219     }
220
221     /**
222      * Is this query using positional parameters?
223      */

224     public boolean isUsingPositionalParameters() {
225         return usingPositionalParameters;
226     }
227
228     /**
229      * Get the parameters used in the query sorted in the order that they
230      * appear. Returns empty array if the query uses no parameters.
231      */

232     public ParamUsage[] getParameters() {
233         if (paramMap == null) {
234             return NO_PARAMS;
235         }
236         ParamUsage[] ans = new ParamUsage[paramMap.size()];
237         for (Iterator JavaDoc i = paramMap.entrySet().iterator(); i.hasNext(); ) {
238             Map.Entry JavaDoc e = (Map.Entry JavaDoc)i.next();
239             ParamUsage u = (ParamUsage)e.getValue();
240             ans[u.index] = u;
241         }
242         return ans;
243     }
244
245     /**
246      * Find the first usage of a parameter in the query String. Throws
247      * an exception if none found (should not be possible).
248      */

249     public ParamUsage getFirstParamUsage(Object JavaDoc nameOrPosition) {
250         ParamUsage ans = (ParamUsage)paramMap.get(nameOrPosition);
251         if (ans == null) {
252             throw BindingSupportImpl.getInstance().internal(
253                     "No usage found for " + nameOrPosition);
254         }
255         return ans;
256     }
257
258     /**
259      * Dump debugging info.
260      */

261     public void dump(PrintStream JavaDoc out) {
262         out.println("Roots (" + rootCount + ")");
263         for (int i = 0; i < rootCount; i++) {
264             out.println("[" + i + "] " + getRoot(i));
265         }
266     }
267
268 }
269
270
Popular Tags