KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > genimen > djeneric > repository > oql > DjOqlWhereTranslator


1 package com.genimen.djeneric.repository.oql;
2
3 import java.io.UnsupportedEncodingException JavaDoc;
4 import java.util.ArrayList JavaDoc;
5 import java.util.HashMap JavaDoc;
6 import java.util.Iterator JavaDoc;
7 import java.util.StringTokenizer JavaDoc;
8
9 import com.genimen.djeneric.language.Messages;
10 import com.genimen.djeneric.repository.DjExtent;
11 import com.genimen.djeneric.repository.DjProperty;
12 import com.genimen.djeneric.repository.DjPropertyType;
13 import com.genimen.djeneric.repository.DjRelation;
14 import com.genimen.djeneric.repository.exceptions.ObjectNotDefinedException;
15 import com.genimen.djeneric.repository.oql.core.DjOqlParserEngine;
16 import com.genimen.djeneric.repository.oql.core.ParseException;
17 import com.genimen.djeneric.repository.oql.core.SimpleNode;
18 import com.genimen.djeneric.repository.oql.core.TokenMgrError;
19 import com.genimen.djeneric.repository.oql.core.util.JoinDefinition;
20 import com.genimen.djeneric.util.DjLogger;
21
22 public class DjOqlWhereTranslator
23 {
24   ArrayList JavaDoc _parameters = null;
25   HashMap JavaDoc _allJoins;
26   HashMap JavaDoc _allExtents;
27   HashMap JavaDoc _path2AliasMapping;
28   SimpleNode _tree;
29   String JavaDoc _rootAlias;
30   boolean _resultIsUnique = true;
31
32   public String JavaDoc translateWhere(DjExtent extent, String JavaDoc rootAlias, String JavaDoc where) throws ParseException
33   {
34     try
35     {
36       rootAlias = rootAlias.toLowerCase();
37       _rootAlias = rootAlias;
38       _tree = DjOqlParserEngine.parseExpression(where);
39
40       ArrayList JavaDoc allPaths = new ArrayList JavaDoc();
41       _tree.addPaths(allPaths);
42
43       _allJoins = collectAllJoins(extent, allPaths);
44
45       int uidCounter = 1;
46
47       // First set the fromAlias of the root extent to ROOT_ALIAS
48
uidCounter = setRootAliasses(_allJoins, rootAlias, uidCounter);
49
50       // Now chain ahead into the join structure; starting from the root
51
chainAliasses(_allJoins, uidCounter);
52
53       // Collect all extents and their alias from the joins
54
_allExtents = collectExtents(_allJoins, rootAlias, extent);
55
56       // Collect the mappings from a path to an extent alias
57
_path2AliasMapping = collectMappings(_allJoins, rootAlias);
58
59       StringBuffer JavaDoc result = new StringBuffer JavaDoc(where.length() * 2 + 100);
60
61       constructFromWhere(_tree, _allJoins, _allExtents, _path2AliasMapping, result);
62
63       _parameters = new ArrayList JavaDoc();
64       _tree.collectParameters(_parameters);
65
66       return result.toString();
67     }
68     catch (UnsupportedEncodingException JavaDoc e)
69     {
70       DjLogger.log(e);
71       throw new ParseException(e.getMessage());
72     }
73     catch (ObjectNotDefinedException e)
74     {
75       throw new ParseException(e, 0, 0);
76     }
77     catch (TokenMgrError e)
78     {
79       throw new ParseException(e.getMessage(), e.line, e.column);
80     }
81   }
82
83   public String JavaDoc translateAgain(DjExtent extent) throws ParseException
84   {
85     try
86     {
87       _allExtents.put(_rootAlias, extent);
88       StringBuffer JavaDoc result = new StringBuffer JavaDoc(500);
89       constructFromWhere(_tree, _allJoins, _allExtents, _path2AliasMapping, result);
90       return result.toString();
91     }
92     catch (ObjectNotDefinedException e)
93     {
94       throw new ParseException(e, 0, 0);
95     }
96   }
97
98   private void constructFromWhere(SimpleNode tree, HashMap JavaDoc allJoins, HashMap JavaDoc allExtents, HashMap JavaDoc path2AliasMapping,
99                                   StringBuffer JavaDoc result) throws ParseException, ObjectNotDefinedException
100   {
101     result.append("from ");
102     Iterator JavaDoc it = allExtents.keySet().iterator();
103     while (it.hasNext())
104     {
105       String JavaDoc alias = it.next().toString();
106       DjExtent ext = (DjExtent) allExtents.get(alias);
107       result.append(ext.getName());
108       result.append(" ");
109       result.append(alias);
110       if (it.hasNext())
111       {
112         result.append(",\n ");
113       }
114     }
115     result.append("\nwhere (");
116
117     tree.translate(result, path2AliasMapping);
118     result.append(")");
119     if (allJoins.size() > 0)
120     {
121       result.append("\nand (");
122       it = allJoins.keySet().iterator();
123       while (it.hasNext())
124       {
125         String JavaDoc key = it.next().toString();
126         JoinDefinition jd = (JoinDefinition) allJoins.get(key);
127         result.append(jd.getJoin());
128         if (it.hasNext()) result.append("\nand ");
129       }
130       result.append(")");
131     }
132   }
133
134   private HashMap JavaDoc collectAllJoins(DjExtent extent, ArrayList JavaDoc allPaths) throws ObjectNotDefinedException, ParseException
135   {
136     HashMap JavaDoc allJoins = new HashMap JavaDoc();
137
138     Iterator JavaDoc it = allPaths.iterator();
139     while (it.hasNext())
140     {
141       String JavaDoc path = it.next().toString();
142
143       // Is a join needed for this path/property?
144
if (path.indexOf('.') != -1)
145       {
146         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(path, ".");
147         DjExtent currentExtent = extent;
148         StringBuffer JavaDoc pathPart = new StringBuffer JavaDoc(100);
149
150         while (st.hasMoreTokens())
151         {
152           String JavaDoc propertyName = st.nextToken();
153
154           if (pathPart.length() > 0) pathPart.append(".");
155           pathPart.append(propertyName);
156
157           DjPropertyType type;
158
159           boolean reverseJoin = false;
160           if (currentExtent.hasDetailRelation(propertyName))
161           {
162             DjRelation rel = currentExtent.getDetailRelation(propertyName);
163             type = rel.getDetailExtent();
164             propertyName = rel.getDetailProperty().getName();
165             reverseJoin = true;
166             // The result might include duplicates so mark this query as non unique
167
_resultIsUnique = false;
168           }
169           else
170           {
171             DjProperty property = currentExtent.getProperty(propertyName);
172             type = property.getType();
173           }
174
175           DjExtent toExtent = null;
176           if (st.hasMoreTokens())
177           {
178             if (!(type instanceof DjExtent))
179             {
180               throw new ParseException(Messages.getString("DjOqlWhereTranslator.PropertyInPathNotObject", propertyName,
181                                                           path));
182             }
183             toExtent = (DjExtent) type;
184           }
185           if (toExtent != null)
186           {
187             JoinDefinition join = new JoinDefinition(currentExtent, toExtent, propertyName, reverseJoin);
188             allJoins.put(pathPart.toString(), join);
189           }
190           currentExtent = toExtent;
191         }
192       }
193     }
194     return allJoins;
195   }
196
197   private HashMap JavaDoc collectMappings(HashMap JavaDoc allJoins, String JavaDoc rootAlias)
198   {
199     HashMap JavaDoc result = new HashMap JavaDoc();
200     // First add the root extent (for properties without a path)
201
result.put("", rootAlias);
202
203     Iterator JavaDoc it = allJoins.keySet().iterator();
204     while (it.hasNext())
205     {
206       String JavaDoc path = it.next().toString();
207       JoinDefinition join = (JoinDefinition) allJoins.get(path);
208       result.put(path, join.getToAlias());
209     }
210
211     return result;
212   }
213
214   private HashMap JavaDoc collectExtents(HashMap JavaDoc allJoins, String JavaDoc rootAlias, DjExtent rootExtent)
215   {
216     HashMap JavaDoc result = new HashMap JavaDoc();
217
218     // first make sure that the root extent is there
219

220     result.put(rootAlias, rootExtent);
221
222     Iterator JavaDoc it = allJoins.keySet().iterator();
223     while (it.hasNext())
224     {
225       String JavaDoc path = it.next().toString();
226       JoinDefinition join = (JoinDefinition) allJoins.get(path);
227       String JavaDoc alias = join.getAlias();
228       if (alias.equals(rootAlias) && join.getExtent() != rootExtent)
229       {
230         System.err.println("Internal error: alias clashes with root extent " + join.getExtent());
231         Thread.dumpStack();
232       }
233       else
234       {
235         result.put(alias, join.getExtent());
236       }
237     }
238
239     // And now add the extents that are on the outer end of the joins
240
it = allJoins.keySet().iterator();
241     while (it.hasNext())
242     {
243       String JavaDoc path = it.next().toString();
244       JoinDefinition join = (JoinDefinition) allJoins.get(path);
245       String JavaDoc alias = join.getToAlias();
246       if (!result.containsKey(alias))
247       {
248         if (alias.equals(rootAlias) && join.getExtent() != rootExtent)
249         {
250           System.err.println("Internal error: alias clashes with root extent " + join.getExtent());
251           Thread.dumpStack();
252         }
253         else result.put(alias, join.getToExtent());
254       }
255     }
256
257     return result;
258   }
259
260   private int chainAliasses(HashMap JavaDoc allJoins, int uid) throws ParseException
261   {
262
263     boolean doneOne = true;
264
265     while (doneOne)
266     {
267       doneOne = false;
268       Iterator JavaDoc it = allJoins.keySet().iterator();
269       while (it.hasNext())
270       {
271         String JavaDoc path = it.next().toString();
272         JoinDefinition tail = (JoinDefinition) allJoins.get(path);
273         if (!tail.isFromAliasSet())
274         {
275           int idx = path.lastIndexOf('.');
276           String JavaDoc fromPath = path.substring(0, idx);
277           JoinDefinition head = (JoinDefinition) allJoins.get(fromPath);
278           if (head.isToAliasSet())
279           {
280             tail.setFromAlias(head.getToAlias());
281             tail.setToAlias(uid++);
282             doneOne = true;
283           }
284         }
285       }
286     }
287
288     // Sanity check
289
Iterator JavaDoc it = allJoins.keySet().iterator();
290     while (it.hasNext())
291     {
292       String JavaDoc path = it.next().toString();
293       JoinDefinition join = (JoinDefinition) allJoins.get(path);
294       if (!join.aliassesSet()) throw new ParseException(Messages.getString("DjOqlWhereTranslator.CouldNotSetAliasFor",
295                                                                            join));
296     }
297
298     return uid;
299   }
300
301   private int setRootAliasses(HashMap JavaDoc allJoins, String JavaDoc alias, int uid)
302   {
303     Iterator JavaDoc it = allJoins.keySet().iterator();
304     while (it.hasNext())
305     {
306       String JavaDoc path = it.next().toString();
307       if (path.indexOf('.') == -1)
308       {
309         JoinDefinition join = (JoinDefinition) allJoins.get(path);
310         join.setFromAlias(alias);
311         join.setToAlias(uid++);
312       }
313     }
314     return uid;
315   }
316
317   public ArrayList JavaDoc getParameters()
318   {
319     return _parameters;
320   }
321
322   public SimpleNode getTree()
323   {
324     return _tree;
325   }
326
327   public boolean isResultUnique()
328   {
329     return _resultIsUnique;
330   }
331 }
Popular Tags