KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > medor > optim > jorm > JormGoUpDecodeRule


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, S. Chassande-Barrioz, A. Lefebvre
22  */

23
24 package org.objectweb.medor.optim.jorm;
25
26 import org.objectweb.medor.api.Field;
27 import org.objectweb.medor.expression.api.MalformedExpressionException;
28 import org.objectweb.medor.api.MedorException;
29 import org.objectweb.medor.filter.api.FieldOperand;
30 import org.objectweb.medor.expression.api.Operator;
31 import org.objectweb.medor.expression.api.ParameterOperand;
32 import org.objectweb.medor.expression.api.Expression;
33 import org.objectweb.medor.expression.api.ExpressionException;
34 import org.objectweb.medor.filter.jorm.lib.CompositePName;
35 import org.objectweb.medor.filter.jorm.lib.EncodePName;
36 import org.objectweb.medor.filter.jorm.lib.SinglePName;
37 import org.objectweb.medor.expression.lib.And;
38 import org.objectweb.medor.filter.lib.BasicFieldOperand;
39 import org.objectweb.medor.expression.lib.Equal;
40 import org.objectweb.medor.filter.lib.MemberOf;
41 import org.objectweb.medor.expression.lib.NotEqual;
42 import org.objectweb.medor.optim.lib.BasicRule;
43 import org.objectweb.medor.query.api.CalculatedField;
44 import org.objectweb.medor.query.api.PropagFromNestedField;
45 import org.objectweb.medor.query.api.PropagatedField;
46 import org.objectweb.medor.query.api.QueryNode;
47 import org.objectweb.medor.query.api.QueryTree;
48 import org.objectweb.medor.query.api.QueryTreeField;
49 import org.objectweb.medor.query.lib.Project;
50 import org.objectweb.util.monolog.api.BasicLevel;
51
52 import java.util.ArrayList JavaDoc;
53 import java.util.HashMap JavaDoc;
54 import java.util.Iterator JavaDoc;
55 import java.util.Map JavaDoc;
56
57 /**
58  * The aim of this rule is to remove comparaisons between PNames and move
59  * up the Decode operators (i.e. SinglePName and CompositePName) at the root of
60  * the QueryTree.
61  * <p>
62  * This rule is applied in one shot on the tree.
63  * <p>The Decode operators (SinglePName and CompositePName) are produced by
64  * the JormLeafRewriter rule.
65  * @author S. Chassande-Barrioz
66  * @see JormLeafRewriter
67  */

68 public class JormGoUpDecodeRule extends BasicRule {
69
70     public JormGoUpDecodeRule() {
71         super("JormGoUpDecodeRule");
72     }
73
74     /**
75      * Rewrites a QueryTree by removing comparisons between PNames and moving
76      * up the Decode operators at the root of the QueryTree.
77      * <p>It relies on the goUpDecode method to perform the real work.
78      * @param qt the QueryTree to be rewritten
79      * @return the rewritten QueryTree
80      * @throws MedorException
81      */

82     public QueryTree rewrite(QueryTree qt, QueryNode _parent)
83             throws MedorException {
84         debug = log != null && log.isLoggable(BasicLevel.DEBUG);
85         Field[] fields = qt.getTupleStructure().getFields();
86         if (!(qt instanceof QueryNode))
87             return qt;
88         //Performs the "real" work
89
Map JavaDoc map = goUpDecode((QueryNode) qt, true);
90         if (map.size() == 0)
91             return qt;
92         QueryTree result = new Project("");
93         //On the root node, the useful decode operators are added.
94
for (Iterator JavaDoc it = map.entrySet().iterator(); it.hasNext();) {
95             Map.Entry JavaDoc me = (Map.Entry JavaDoc) it.next();
96             Field decodefield = (Field) me.getKey();
97             //debug("root: decodefield=" + decodefield.getName());
98
Object JavaDoc neos = me.getValue();
99             //Fetch the expression of the old decodefield
100
Expression e = getCalculatedField(decodefield).getExpression();
101             //Re-assign the field in the FieldOperand
102
if (e instanceof CompositePName) {
103                 FieldOperand[] fos = ((CompositePName) e).getFields();
104                 String JavaDoc[] cofns = ((CompositePName) e).getCompositeFieldName();
105                 for (int i = 0; i < fos.length; i++) {
106                     fos[i].setField((Field) ((Map JavaDoc) neos).get(cofns[i]));
107                 }
108             }
109             else if (e instanceof SinglePName) {
110                 ((SinglePName) e).getField().setField((Field) neos);
111             }
112             else
113                 throw new MedorException("Umanaged case: PName field decoder in complex expression");
114             //Add the field on the root
115
((QueryNode) result).addCalculatedField(
116                 decodefield.getName(),
117                 decodefield.getType(),
118                 e);
119         }
120         //Propagate the other fields
121
for (int i = 0; i < fields.length; i++) {
122             String JavaDoc fn = fields[i].getName();
123             if (qt.getTupleStructure().contains(fn)
124                 && !result.getTupleStructure().contains(fn)) {
125                 QueryTreeField prev = (QueryTreeField)
126                     qt.getTupleStructure().getField(fn);
127                 debug("root: propag=" + prev.getName());
128                 ((QueryNode) result).addPropagatedField(
129                     prev.getName(),
130                     prev.getType(),
131                     new QueryTreeField[]{prev});
132             }
133         }
134         return result;
135     }
136
137     /**
138      * This recursive method performs the real work of the rule.
139      * @param qn is the QueryNode on which the rule must be applied.
140      * @param isRoot is a boolean which indicates if the qn is the root of the
141      * QueryTree.
142      * @return a map with the following characteristics:
143      * <ul><li>
144      * key = an old projected field of a child. The old field is a PName decode
145      * or a Propagated field.</li>
146      * <li>value = A map of composite field name associated to the new projected
147      * fields of the child. These fields replace the PName identifier. They are
148      * the PName fields. (key=composite fname, value=field)
149      * </li></ul>
150      */

151     public Map JavaDoc goUpDecode(QueryNode qn, boolean isRoot) throws MedorException {
152         Map JavaDoc childMap = new HashMap JavaDoc();
153         Map JavaDoc map = new HashMap JavaDoc();
154         //Call children and collaspe the result into a single map
155
QueryTree[] qts = qn.getChildren();
156         for (int i = 0; i < qts.length; i++) {
157             if (qts[i] instanceof QueryNode)
158                 childMap.putAll(goUpDecode((QueryNode) qts[i], false));
159         }
160
161         //Use the map of the children to replace in filter the FieldOperands
162
//which reference (directly or not) a PName field.
163
Expression filter = qn.getQueryFilter();
164         if (filter != null) {
165             debug("replaceFieldOperand in filter");
166             try {
167                 qn.setQueryFilter(replaceFieldOperand(filter, childMap).e);
168             }
169             catch (ExpressionException e) {
170                 throw new MedorException(e);
171             }
172         }
173
174         // Replace the fields which used the pname and fill a new map with the
175
// couples:
176
// (old_field_in_this_node, Map(composite field name, new_fields_in_this_node))
177
Field[] fields = qn.getTupleStructure().getFields();
178         for (int i = 0; i < fields.length; i++) {
179             debug("Field " + fields[i].getName() + " " + fields[i].getType());
180             // replace the decode into CalculatedFields
181
if (!isRoot && fields[i] instanceof CalculatedField) {
182                 Expression e = ((CalculatedField) fields[i]).getExpression();
183                 if (e instanceof CompositePName) {
184                     debug("CalculatedField(CompositePName): begin");
185                     qn.removeField(fields[i].getName());
186 /*
187                     if (qn.getTupleStructure().contains(fields[i].getName())) {
188                         throw new MedorException("Field not correctly removed.");
189                     }
190 */

191                     FieldOperand[] fops = ((CompositePName) e).getFields();
192                     String JavaDoc[] cofns =
193                         ((CompositePName) e).getCompositeFieldName();
194                     Map JavaDoc al = new HashMap JavaDoc(fops.length);
195                     debug("CompositePName: " + fops.length);
196                     for (int j = 0; j < fops.length; j++) {
197                         Field prev = fops[j].getField();
198                         Field neo = null;
199                         if (!qn.getTupleStructure().contains(prev.getName())) {
200                             debug("Field " + prev.getName() + " of CompositePName of not already projected.");
201                             neo = qn.addPropagatedField(
202                                 prev.getName(),
203                                 prev.getType(),
204                                 new QueryTreeField[]{(QueryTreeField) prev});
205                         }
206                         else {
207                             debug("Field " + prev.getName() + " of CompositePName was already propagated.");
208                             neo =
209                                 qn.getTupleStructure().getField(prev.getName());
210                         }
211                         debug("put(" + cofns[j] + "," + neo + ")");
212                         al.put(cofns[j], neo);
213                     }
214                     // Put in the result the association between the removed
215
// calculated field and the new fields
216
map.put(fields[i], al);
217                     debug("CalculatedField(CompositePName): end");
218                 }
219                 else if (e instanceof SinglePName) {
220                     debug("CalculatedField(SinglePName): begin");
221                     qn.removeField(fields[i].getName());
222                     Field prev = ((SinglePName) e).getField().getField();
223                     Field neo = null;
224                     if (!qn.getTupleStructure().contains(prev.getName()))
225                         neo = qn.addPropagatedField(
226                             prev.getName(),
227                             prev.getType(),
228                             new QueryTreeField[]{(QueryTreeField) prev});
229                     else
230                         neo = qn.getTupleStructure().getField(prev.getName());
231                     // Put in the result the association between the removed
232
// calculated field and the new fields
233
map.put(fields[i], neo);
234                     debug("CalculatedField(SinglePName): end");
235                 }
236             }
237
238             //replace the propagated fields which project a PName.
239
else if (fields[i] instanceof PropagatedField) {
240                 debug("PropagatedField: begin");
241                 Field[] prev =
242                     ((PropagatedField) fields[i]).getPreviousFields();
243                 for (int j = 0; j < prev.length; j++) {
244                     Object JavaDoc o = childMap.get(prev[j]);
245                     //debug("prev[j]= " + prev[j].getName() + " / al=" + al);
246
//Is the field uses a removed field of children
247
if (o != null) {
248                         //replacing ...
249
qn.removeField(fields[i].getName());
250                         if (o instanceof Map JavaDoc) {
251                             Map JavaDoc neos = new HashMap JavaDoc();
252                             for (Iterator JavaDoc it = ((Map JavaDoc) o).entrySet().iterator();
253                                  it.hasNext();) {
254                                 Map.Entry JavaDoc me = (Map.Entry JavaDoc) it.next();
255                                 Field p = (Field) me.getValue();
256                                 Field neo = null;
257                                 if (!qn.getTupleStructure().contains(
258                                     p.getName()))
259                                     neo = qn.addPropagatedField(
260                                         p.getName(),
261                                         p.getType(),
262                                         new QueryTreeField[]
263                                         {(QueryTreeField) p});
264                                 else
265                                     neo = qn.getTupleStructure().getField(
266                                         p.getName());
267                                 neos.put(me.getKey(), neo);
268                             }
269                             // Put in the result the association between the
270
//removed spropagated field and the new fields
271
map.put(fields[i], neos);
272                         }
273                         else if (o instanceof Field) {
274                             Field p = (Field) o;
275                             Field neo = null;
276                             if (!qn.getTupleStructure().contains(p.getName()))
277                                 neo = qn.addPropagatedField(
278                                     p.getName(),
279                                     p.getType(),
280                                     new QueryTreeField[]{(QueryTreeField) p});
281                             else
282                                 neo = qn.getTupleStructure().getField(
283                                     p.getName());
284                             map.put(fields[i], neo);
285                         }
286                     }
287                 }
288                 debug("PropagatedField: end");
289             }
290         }
291         return map;
292     }
293
294     /**
295      * Replaces PName FieldOperands in an Expression with Operands on the
296      * the corresponding Fields
297      * @param e the Expression in which to replace the PName FieldOperands
298      * @param map the Map, produced by goUpDecode, between the PNames and the
299      * Fields composing the PNames (see goUpDecode)
300      * @return a ModifiedExpression
301      * @throws MedorException if PNames are incompatible
302      */

303     private ModifiedExpression replaceFieldOperand(Expression e, Map JavaDoc map)
304         throws MedorException, ExpressionException {
305         //debug("replaceFieldOperand: ", e, map);
306
ModifiedExpression me = new ModifiedExpression();
307         if (e instanceof Equal
308             || e instanceof NotEqual
309             || e instanceof MemberOf) {
310             Operator bo = (Operator) e;
311             Expression le = bo.getExpression(0);
312             Expression re = bo.getExpression(1);
313             Object JavaDoc lf = null;
314             if (le instanceof FieldOperand) {
315                 lf = map.get(((FieldOperand) le).getField());
316             }
317             Object JavaDoc rf = null;
318             if (re instanceof FieldOperand) {
319                 rf = map.get(((FieldOperand) re).getField());
320             }
321             if (lf != null && rf != null) {
322                 if (!lf.getClass().equals(rf.getClass()))
323                     throw new MedorException("incompatible PNames (single versus composite)");
324                 Expression expr = null;
325                 if (lf instanceof Map JavaDoc) {
326                     debug("lf=" + lf);
327                     //Composite name
328
if (e instanceof MemberOf) {
329                         ArrayList JavaDoc l1 =
330                             new ArrayList JavaDoc(((Map JavaDoc) lf).entrySet().size());
331                         ArrayList JavaDoc l2 =
332                             new ArrayList JavaDoc(((Map JavaDoc) lf).entrySet().size());
333                         for (Iterator JavaDoc it = ((Map JavaDoc) lf).entrySet().iterator();
334                              it.hasNext();) {
335                             Map.Entry JavaDoc mape = (Map.Entry JavaDoc) it.next();
336                             l1.add(mape.getValue());
337                             l2.add(((Map JavaDoc) rf).get(mape.getKey()));
338                         }
339                         if (me.e == null)
340                             me.e = new MemberOf(l1, l2);
341                         else
342                             me.e = new And(new MemberOf(l1, l2), me.e);
343                     }
344                     else
345                         for (Iterator JavaDoc it = ((Map JavaDoc) lf).entrySet().iterator();
346                              it.hasNext();) {
347                             Map.Entry JavaDoc mape = (Map.Entry JavaDoc) it.next();
348                             expr = getExpr(e,
349                                 new BasicFieldOperand((Field) mape.getValue()),
350                                 new BasicFieldOperand((Field)
351                                 ((Map JavaDoc) rf).get(mape.getKey()))
352                             );
353                             if (me.e == null)
354                                 me.e = expr;
355                             else
356                                 me.e = new And(expr, me.e);
357                         }
358                 }
359                 else {
360                     //single name
361
expr = getExpr(e,
362                         new BasicFieldOperand((Field) lf),
363                         new BasicFieldOperand((Field) rf));
364                     if (me.e == null)
365                         me.e = expr;
366                     else
367                         me.e = new And(expr, me.e);
368                 }
369                 me.isModified = true;
370                 return me;
371             }
372             else if (le instanceof ParameterOperand && rf != null) {
373                 Expression expr = null;
374                 if (rf instanceof Map JavaDoc) {
375                     for (Iterator JavaDoc it = ((Map JavaDoc) rf).entrySet().iterator();
376                          it.hasNext();) {
377                         Map.Entry JavaDoc mape = (Map.Entry JavaDoc) it.next();
378                         Field f = (Field) mape.getValue();
379                         expr = getExpr(e,
380                             new EncodePName(
381                                 f.getType(),
382                                 ((ParameterOperand) le).getName(),
383                                 (String JavaDoc) mape.getKey()),
384                             new BasicFieldOperand(f)
385                         );
386                         if (me.e == null)
387                             me.e = expr;
388                         else
389                             me.e = new And(expr, me.e);
390                     }
391                 }
392                 else {
393                     Field f = (Field) rf;
394                     expr = getExpr(e,
395                         new EncodePName(
396                             f.getType(),
397                             ((ParameterOperand) le).getName()),
398                         new BasicFieldOperand(f)
399                     );
400                     if (me.e == null)
401                         me.e = expr;
402                     else
403                         me.e = new And(expr, me.e);
404                 }
405                 me.isModified = true;
406                 return me;
407             }
408             else if (re instanceof ParameterOperand && lf != null) {
409                 Expression expr = null;
410                 if (lf instanceof Map JavaDoc) {
411                     for (Iterator JavaDoc it = ((Map JavaDoc) lf).entrySet().iterator();
412                          it.hasNext();) {
413                         Map.Entry JavaDoc mape = (Map.Entry JavaDoc) it.next();
414                         Field f = (Field) mape.getValue();
415                         expr = getExpr(e,
416                             new BasicFieldOperand(f),
417                             new EncodePName(
418                                 f.getType(),
419                                 ((ParameterOperand) re).getName(),
420                                 (String JavaDoc) mape.getKey())
421                         );
422                         if (me.e == null)
423                             me.e = expr;
424                         else
425                             me.e = new And(expr, me.e);
426                     }
427                 }
428                 else {
429                     Field f = (Field) lf;
430                     expr = getExpr(e,
431                         new BasicFieldOperand(f),
432                         new EncodePName(
433                             f.getType(),
434                             ((ParameterOperand) re).getName())
435                     );
436                     if (me.e == null)
437                         me.e = expr;
438                     else
439                         me.e = new And(expr, me.e);
440                 }
441                 me.isModified = true;
442                 return me;
443             }
444         }
445         if (e instanceof Operator) {
446             Operator op = (Operator) e;
447             me = new ModifiedExpression(e, false);
448             ModifiedExpression _me = null;
449             for (int i = 0; i < op.getOperandNumber(); i++) {
450                 _me = replaceFieldOperand(op.getExpression(i), map);
451                 if (_me.isModified) {
452                     me.isModified = true;
453                     op.setExpression(i, _me.e);
454                 }
455             }
456         }
457         else {
458             me.isModified = false;
459         }
460         me.e = e;
461         return me;
462     }
463
464     /**
465      *
466      * @param operator
467      * @param loperand
468      * @param roperand
469      * @return
470      */

471     private Expression getExpr(Expression operator,
472                                Expression loperand,
473                                Expression roperand)
474         throws MalformedExpressionException {
475         if (operator instanceof Equal)
476             return new Equal(loperand, roperand);
477         else if (operator instanceof NotEqual)
478             return new NotEqual(loperand, roperand);
479         else {//it is a MemberOf
480
ArrayList JavaDoc l1 = new ArrayList JavaDoc(1);
481             l1.add(loperand);
482             ArrayList JavaDoc l2 = new ArrayList JavaDoc(1);
483             l2.add(roperand);
484             return new MemberOf(l1, l2);
485         }
486     }
487
488     /**
489      * It tries to reach the CalculatedField with a field.
490      * @param f
491      * @throws MedorException
492      */

493     private CalculatedField getCalculatedField(Field f) throws MedorException {
494         if (f == null)
495             return null;
496         if (f instanceof PropagatedField)
497             return getCalculatedField(
498                 ((PropagatedField) f).getPreviousFields()[0]);
499         else if (f instanceof CalculatedField)
500             return (CalculatedField) f;
501         else if (f instanceof PropagFromNestedField)
502             return getCalculatedField(
503                 ((PropagFromNestedField) f).getPreviousFlatField()[0]);
504         else
505             throw new MedorException("Medor Internal error: Unknown field");
506     }
507     private void debug(String JavaDoc msg) {
508         //log.log(BasicLevel.DEBUG, msg);
509
}
510
511 /*
512     private static void debug(String msg, Expression e, Map map) {
513
514         //msg += " / expression=" + TestExpressionHelper.e2str(e);
515         msg += " / map(";
516         Iterator it = map.entrySet().iterator();
517         while (it.hasNext()) {
518             Map.Entry me = (Map.Entry) it.next();
519             msg += "(" + ((Field) me.getKey()).getName() + "=>" + me.getValue() + ")";
520         }
521         msg += ")";
522         debug(msg);
523
524     }
525 */

526 }
527
Popular Tags