KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > medor > query > lib > BasicQueryNode


1 /**
2  * MEDOR: Middleware Enabling Distributed Object Requests
3  *
4  * Copyright (C) 2001-2004 France Telecom R&D
5  * Contact: alexandre.lefebvre@rd.francetelecom.com
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  * Initial developers: M. Alia, A. Lefebvre
22  */

23
24 package org.objectweb.medor.query.lib;
25
26 import org.objectweb.jorm.type.api.PType;
27 import org.objectweb.medor.api.Field;
28 import org.objectweb.medor.api.MedorException;
29 import org.objectweb.medor.clone.api.Cloneable;
30 import org.objectweb.medor.expression.api.Expression;
31 import org.objectweb.medor.expression.api.Operator;
32 import org.objectweb.medor.filter.api.FieldOperand;
33 import org.objectweb.medor.query.api.CalculatedField;
34 import org.objectweb.medor.query.api.NestedField;
35 import org.objectweb.medor.query.api.PropagatedField;
36 import org.objectweb.medor.query.api.QueryNode;
37 import org.objectweb.medor.query.api.QueryTree;
38 import org.objectweb.medor.query.api.QueryTreeField;
39 import org.objectweb.medor.tuple.api.TupleLoader;
40 import org.objectweb.util.monolog.api.BasicLevel;
41
42 import java.util.ArrayList JavaDoc;
43 import java.util.HashSet JavaDoc;
44 import java.util.Iterator JavaDoc;
45 import java.util.Map JavaDoc;
46
47 /**
48  * A BasicQueryNode is an implementation of QueryNode.
49  * It also implements QueryIndexGenerator and RWTupleStructure (it is its own
50  * TupleStructure).
51  * @author Sebastien Chassande-Barrioz
52  */

53 public abstract class BasicQueryNode extends BasicQueryTree
54     implements QueryNode {
55
56     protected ArrayList JavaDoc children = new ArrayList JavaDoc();
57     protected HashSet JavaDoc inner = new HashSet JavaDoc();
58     protected TupleLoader tupleLoader = null;
59     protected Expression filter = null;
60     /**
61      * Contains ranges of attribute to be projected from the tuple resulting
62      * of the concatenation of the tuples from the children QueryTrees.
63      */

64     protected int[] indexes;
65
66     public BasicQueryNode() {
67     }
68
69     public BasicQueryNode(String JavaDoc name) {
70         super(name);
71     }
72
73     public Object JavaDoc clone(Object JavaDoc clone,
74                         Map JavaDoc obj2clone) throws CloneNotSupportedException JavaDoc {
75         clone = super.clone(clone, obj2clone);
76         BasicQueryNode bqn = (BasicQueryNode) clone;
77         bqn.filter = (Expression) getClone(filter, obj2clone);
78         bqn.tupleLoader = tupleLoader;
79         bqn.children = new ArrayList JavaDoc(children.size());
80         for(int i=0; i<children.size(); i++) {
81             bqn.children.add(getClone((Cloneable JavaDoc) children.get(i), obj2clone));
82         }
83                 bqn.inner = new HashSet JavaDoc(inner.size());
84                 for (Iterator JavaDoc it = inner.iterator(); it.hasNext(); ) {
85                     bqn.inner.add(getClone((Cloneable JavaDoc) it.next(), obj2clone));
86                 }
87         if (indexes != null) {
88             bqn.indexes = new int[indexes.length];
89             System.arraycopy(indexes, 0, bqn.indexes, 0, indexes.length);
90         }
91         return clone;
92     }
93
94     /**
95      * Creates and adds a PropagatedField to the TupleStructure of the
96      * QueryNode.
97      * @param name is the name of the Field to be added.
98      * @param type is the PType of the Field to be added.
99      * @param anc are the origin Fields for the PropagatedField to be created.
100      * @return the newly created PropagatedField
101      * @throws MedorException when a Field with the same name already exists.
102      */

103     public PropagatedField addPropagatedField(String JavaDoc name, PType type,
104                                               QueryTreeField[] anc)
105         throws MedorException {
106         String JavaDoc fn = getFieldName(this.name, name);
107         if (name2field.containsKey(fn))
108             throw new MedorException("Two fields with the same name: " + fn);
109         PropagatedField newField = new BasicPropagatedField(fn, type, this, anc);
110         //adds a Field to the TupleStructure
111
this.addField(newField);
112         //add the QueryTree of the ancestors to the set of Children
113
for (int i = 0; i < anc.length; i++) {
114             addChild(anc[i].getQueryTree());
115         }
116         return newField;
117     }
118
119     /**
120      * Creates and adds a CalculatedField to the TupleStructure of the
121      * QueryNode.
122      * @param name is the name of the Field to be added.
123      * @param type is the PType of the Field to be added.
124      * @param exp is the Expression for calculating the new Field.
125      * @return the newly created CalculatedField
126      * @throws MedorException when a Field with the same name already exists.
127      */

128     public CalculatedField addCalculatedField(String JavaDoc name, PType type,
129                                               Expression exp)
130         throws MedorException {
131         String JavaDoc fn = getFieldName(this.name, name);
132         if (name2field.containsKey(fn))
133             throw new MedorException("Two fields with the same name: " + fn);
134         CalculatedField newField = new BasicCalculatedField(fn, type, this, exp);
135         this.addField(newField);
136         //add the QueryTree of the FieldOperand present in the Expression to
137
//the set of Children
138
addChildrenFromExpression(exp);
139         return newField;
140     }
141
142     /**
143      * Removes a Field.
144      * @param name is the name of the Field to be removed.
145      * @return the Field which has been removed, or null if no such Field could
146      * be removed.
147      */

148     public QueryTreeField removeField(String JavaDoc name) throws MedorException {
149         boolean debug = logger != null && logger.isLoggable(BasicLevel.DEBUG);
150         if (debug) {
151             logger.log(BasicLevel.DEBUG, "QueryNode: Removing field " + name);
152         }
153         Field toRemove = this.getField(name);
154         if (debug) {
155             logger.log(BasicLevel.DEBUG, "Found the field " + toRemove);
156         }
157         if (removeField(toRemove)) {
158             //updates the children list from the other Fields and from the
159
//query filter
160
updateChildren();
161             return (QueryTreeField)toRemove;
162         }
163         else return null;
164     }
165
166     public QueryTree[] getChildren() {
167         boolean debug = logger != null && logger.isLoggable(BasicLevel.DEBUG);
168         if (debug) logger.log(BasicLevel.DEBUG, "Calculating children for QueryNode " + this);
169         QueryTree[] theChildren = (QueryTree[]) children.toArray(new QueryTree[0]);
170         if (debug) {
171             logger.log(BasicLevel.DEBUG, "Found " + theChildren.length + " child(ren)");
172             for (int i = 0; i < theChildren.length; i++) {
173                 logger.log(BasicLevel.DEBUG, "Child: " + theChildren[i]);
174             }
175         }
176         return theChildren;
177     }
178
179     public boolean isOuter(QueryTree child) {
180         if (!children.contains(child)) {
181             throw new IllegalArgumentException JavaDoc("not a child: " + child);
182         }
183         return !inner.contains(child);
184     }
185
186     public void setOuter(QueryTree child, boolean value) {
187         if (!children.contains(child)) {
188             throw new IllegalArgumentException JavaDoc("not a child: " + child);
189         }
190         if (value) {
191             inner.remove(child);
192         } else {
193             inner.add(child);
194         }
195     }
196
197     public QueryTreeField replace(QueryTreeField old, QueryTreeField neo) {
198         boolean debug = logger != null && logger.isLoggable(BasicLevel.DEBUG);
199         if (debug) logger.log(BasicLevel.DEBUG, "Replacing field");
200
201         int idx = this.fields.indexOf(old);
202         if (idx == -1) {
203             if (debug) logger.log(BasicLevel.DEBUG, "Have not found field " + old);
204             return null;
205         }
206         fields.set(idx, neo);
207         name2field.remove(old.getName());
208         name2field.put(neo.getName(), neo);
209         updateChildren();
210         return old;
211     }
212
213     /**
214      * The setQueryFilter method will be overwritten for implementations
215      * which do not support the operation.
216      */

217     public void setQueryFilter(Expression filter)
218         throws UnsupportedOperationException JavaDoc {
219         this.filter = filter;
220         //add the QueryTree of the FieldOperands present in the Expression to
221
//the Children
222
updateChildren();
223     }
224
225     public Expression getQueryFilter() {
226         return filter;
227     }
228
229     public abstract short getType();
230
231     public TupleLoader getTupleLoader() {
232         return tupleLoader;
233     }
234
235     public void setTupleLoader(TupleLoader loader) {
236         tupleLoader = loader;
237     }
238
239     public void updatePropagatedField(String JavaDoc name, QueryTreeField[] previous)
240         throws MedorException {
241         Field f = (Field) name2field.get(name);
242         if (f ==null)
243             throw new MedorException("No field found");
244         if (!(f instanceof PropagatedField))
245             throw new MedorException("Bad type: " + f.getClass().getName());
246         ((PropagatedField) f).replacePreviousField(previous);
247         updateChildren();
248     }
249
250     public void updateCalculatedField(String JavaDoc name, Expression e)
251         throws MedorException {
252         Field f = (Field) name2field.get(name);
253         if (f ==null)
254             throw new MedorException("No field found");
255         if (!(f instanceof CalculatedField))
256             throw new MedorException("Bad type: " + f.getClass().getName());
257         ((CalculatedField) f).setExpression(e);
258         updateChildren();
259     }
260
261     /**
262      * Adds a Field to the current RWTupleStructure
263      * @param f The Field to be added.
264      */

265     protected synchronized void addField(Field f) {
266         name2field.put(f.getName(), f);
267         fields.add(f);
268     }
269
270     /**
271      * Removes a Field from the current RWTupleStructure.
272      * @param f The Field to be removed.
273      * @return false if the Field could not be removed (was not part of the
274      * TupleStructure).
275      */

276     private boolean removeField(Field f) {
277         if (name2field.remove(f.getName()) == null)
278             return false;
279         else {
280             fields.remove(f);
281             return true;
282         }
283     }
284
285     /**
286      * Updates the list of children by screening all Fields and the
287      * query filter.
288      */

289     protected void updateChildren() {
290         children.clear();
291         Field[] fs = this.getFields();
292         //add children from Fields
293
for (int i = 0; i < fs.length; i++) {
294             if (fs[i] instanceof PropagatedField) {
295                 Field[] anc = ((PropagatedField)fs[i]).getPreviousFields();
296                 for (int j = 0; j < anc.length; j++) {
297                     addChild(((QueryTreeField)anc[j]).getQueryTree());
298                 }
299             }
300             else if (fs[i] instanceof NestedField) {
301                 Field[] grouped = ((NestedField)fs[i]).getFields();
302                 for (int j = 0; j < grouped.length; j++) {
303                     addChild(((QueryTreeField)grouped[j]).getQueryTree());
304                 }
305             }
306             else if (fs[i] instanceof CalculatedField) {
307                 addChildrenFromExpression(((CalculatedField)fs[i]).getExpression());
308             }
309         }
310         addChildrenFromExpression(this.getQueryFilter());
311     }
312
313     /**
314      * Parses an Expression and adds the QueryTrees of the FieldOperands to
315      * the children of the current QueryNode.
316      * @param exp is the Expression to be parsed.
317      */

318     private void addChildrenFromExpression(Expression exp) {
319         if (exp instanceof FieldOperand) {
320             addChild(((QueryTreeField)((FieldOperand)exp).getField()).getQueryTree());
321         }
322         else if (exp instanceof Operator) {
323             Operator op = (Operator) exp;
324             for (int i=0; i<op.getOperandNumber(); i++) {
325                 addChildrenFromExpression(op.getExpression(i));
326             }
327         }
328     }
329
330     protected String JavaDoc getFieldName(String JavaDoc nodeName, String JavaDoc fieldName) {
331         if (nodeName==null || nodeName.length()==0)
332             return fieldName;
333         else
334             return nodeName + "." + fieldName;
335     }
336
337     protected void addChild(QueryTree qt) {
338         if (!children.contains(qt)) {
339             children.add(qt);
340         }
341     }
342 }
343
Popular Tags