KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > medor > optim > lib > DropUselessNodeRule


1 /**
2  * MEDOR: Middleware Enabling Distributed Object Requests
3  *
4  * Copyright (C) 2001-2003 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.lib;
25
26 import org.objectweb.medor.api.Field;
27 import org.objectweb.medor.api.MedorException;
28 import org.objectweb.medor.filter.api.FieldOperand;
29 import org.objectweb.medor.expression.api.Operator;
30 import org.objectweb.medor.expression.api.Expression;
31 import org.objectweb.medor.filter.jorm.lib.CompositePName;
32 import org.objectweb.medor.filter.jorm.lib.SinglePName;
33 import org.objectweb.medor.query.api.CalculatedField;
34 import org.objectweb.medor.query.api.FilteredQueryTree;
35 import org.objectweb.medor.query.api.PropagFromNestedField;
36 import org.objectweb.medor.query.api.PropagatedField;
37 import org.objectweb.medor.query.api.QueryLeaf;
38 import org.objectweb.medor.query.api.QueryNode;
39 import org.objectweb.medor.query.api.QueryTree;
40 import org.objectweb.medor.query.api.QueryTreeField;
41 import org.objectweb.util.monolog.api.BasicLevel;
42
43 import java.util.HashMap JavaDoc;
44 import java.util.Map JavaDoc;
45
46 /**
47  * This rule removes the query node which are useless.
48  * <p> A node is useless when
49  * it does not have any filter and all fields are propagated fields which
50  * have only one ancestor.
51  *
52  * @author S. Chassande-Barrioz
53  */

54 public class DropUselessNodeRule extends BasicRule {
55     public class UsedFields {
56         public boolean isUseLess;
57         public Field[] fields;
58     }
59
60     public DropUselessNodeRule() {
61         super("DropUselessNodeRule");
62     }
63
64     public QueryTree rewrite(QueryTree qt, QueryNode _parent)
65             throws MedorException {
66         debug = log != null && log.isLoggable(BasicLevel.DEBUG);
67         UsedFields uf = isUseless(qt);
68         return (uf.isUseLess
69             ? ((QueryTreeField) uf.fields[0]).getQueryTree()
70             : qt);
71     }
72
73     protected UsedFields isUseless(QueryTree qt) throws MedorException {
74
75         UsedFields uf = new UsedFields();
76         uf.fields = qt.getTupleStructure().getFields();
77         uf.isUseLess = false;
78         if (debug) log.log(BasicLevel.DEBUG, "Fields: " + printFields(uf.fields));
79         if (qt instanceof QueryLeaf) {
80             if (debug) log.log(BasicLevel.DEBUG, "useful");
81             if (debug) log.log(BasicLevel.DEBUG, "return " + printFields(uf.fields));
82             return uf;
83         }
84         QueryNode qn = (QueryNode) qt;
85         QueryTree[] children = qn.getChildren();
86         // Look if the current QueryNode is useless
87
uf.isUseLess =
88             (children.length == 1) &&
89             (qn instanceof FilteredQueryTree
90             ? qn.getQueryFilter() == null
91             : true);
92
93         // All fields must be an instanceof of PropagatedField
94
int i = 0;
95         while (i < uf.fields.length
96             && uf.fields[i] instanceof PropagatedField
97             && !(uf.fields[i] instanceof PropagFromNestedField)
98             && ((PropagatedField) uf.fields[i]).getPreviousFields().length == 1)
99             i++;
100         uf.isUseLess &= i == uf.fields.length;
101
102         if (uf.isUseLess) {
103             if (debug) log.log(BasicLevel.DEBUG, "useless");
104             //The current node is useless then it have only one child
105
// => Fetch the field which must be used instead of the current
106
UsedFields child = isUseless(children[0]);
107             if (debug) log.log(BasicLevel.DEBUG, "child: isUseLess:" + child.isUseLess + " ndfield: " + child.fields.length);
108             // Reorganize the children field in the same order that the current
109
// propagated fields
110
Field[] fields = new Field[uf.fields.length];
111             for (i = 0; i < uf.fields.length; i++) {
112                 QueryTreeField qtf = (QueryTreeField)
113                     ((PropagatedField) uf.fields[i]).getPreviousFields()[0];
114                 int idx =
115                     qtf.getQueryTree().getTupleStructure().getFieldRank(qtf);
116                 if (debug) log.log(BasicLevel.DEBUG, "idx=" + idx);
117                 fields[i] = child.fields[idx - 1];
118             }
119             uf.fields = fields;
120             //The returned uf contains the fields of the child
121
}
122         else {
123             if (debug) log.log(BasicLevel.DEBUG, "useful");
124             // Propagate the call to the method.
125
Map JavaDoc childrenUseLess = new HashMap JavaDoc();
126             for (i = 0; i < children.length; i++) {
127                 childrenUseLess.put(children[i], isUseless(children[i]));
128             }
129
130             // The current node is not useless but the children can be useless.
131
// Replace the use of the old fields by the newer if needed
132

133             //in the fields:
134
//--------------
135
for (i = 0; i < uf.fields.length; i++) {
136                 if (debug) log.log(BasicLevel.DEBUG, "useful: field " + uf.fields[i].getName());
137                 if (uf.fields[i] instanceof PropagatedField) {
138                     //Note: The PropagFromNestedField is also PropagatedField
139
PropagatedField pf = (PropagatedField) uf.fields[i];
140                     Field[] ancs = pf.getPreviousFields();
141                     QueryTreeField[] neoAncs = new QueryTreeField[ancs.length];
142                     boolean mustReplace = false;
143                     for (int j = 0; j < ancs.length; j++) {
144                         if (debug) log.log(BasicLevel.DEBUG, "useful: field " + uf.fields[i].getName() + " / ancestor: " + ancs[j].getName());
145                         if (debug) log.log(BasicLevel.DEBUG, "-> for QueryTree " + qt);
146                         QueryTree qtof =
147                             ((QueryTreeField) ancs[j]).getQueryTree();
148                         UsedFields childUF =
149                             (UsedFields) childrenUseLess.get(qtof);
150                         if (debug) log.log(BasicLevel.DEBUG, "childUF.fields " + childUF.fields.length);
151                         //if (debug) QueryTreePrinter.printQueryTree(qtof, log);
152
if (childUF != null) {
153                             int idx =
154                                 qtof.getTupleStructure().getFieldRank(ancs[j]);
155                             mustReplace = true;
156                             neoAncs[j] = (QueryTreeField) childUF.fields[idx - 1];
157                         }
158                         else
159                             neoAncs[j] = (QueryTreeField) ancs[j];
160                     }
161                     if (mustReplace) {
162                         if (debug) log.log(BasicLevel.DEBUG, "replace " + printFields(pf.getPreviousFields()) + " by " + printFields(neoAncs));
163                         qn.updatePropagatedField(pf.getName(), neoAncs);
164                     }
165                 }
166                 else if (uf.fields[i] instanceof CalculatedField) {
167                     Expression e =
168                         ((CalculatedField) uf.fields[i]).getExpression();
169                     if (replaceInFilter(e, childrenUseLess))
170                         qn.updateCalculatedField(uf.fields[i].getName(), e);
171                 }
172             }
173
174
175             //in the filter:
176
//--------------
177
if (qn instanceof FilteredQueryTree) {
178                 Expression e = qn.getQueryFilter();
179                 if (replaceInFilter(e, childrenUseLess))
180                     qn.setQueryFilter(e);
181             }
182
183             //The returned uf contains the fields of the current node
184
}
185
186         if (debug) log.log(BasicLevel.DEBUG, "return " + printFields(uf.fields));
187         return uf;
188     }
189
190     protected boolean replaceInFilter(Expression e, Map JavaDoc map)
191         throws MedorException {
192         if (e instanceof CompositePName) {
193             FieldOperand[] fs = ((CompositePName) e).getFields();
194             boolean replaced = false;
195             for (int i = 0; i < fs.length; i++) {
196                 QueryTreeField qtf = (QueryTreeField) fs[i].getField();
197                 Field neo = replaceField(qtf, map);
198                 if (neo != qtf) {
199                     fs[i].setField(neo);
200                     replaced = true;
201                     if (debug) log.log(BasicLevel.DEBUG, "Replace in CompositePName " + qtf.getName() + " by " + neo.getName());
202                 }
203             }
204             return replaced;
205         }
206         else if (e instanceof SinglePName) {
207             FieldOperand fo = ((SinglePName) e).getField();
208             QueryTreeField qtf = (QueryTreeField) fo.getField();
209             Field neo = replaceField(qtf, map);
210             if (neo != qtf) {
211                 fo.setField(neo);
212                 if (debug) log.log(BasicLevel.DEBUG, "Replace in SinglePName " + qtf.getName() + " by " + neo.getName());
213                 return true;
214             }
215         }
216         else if (e instanceof Operator) {
217             boolean result = false;
218             for (int i = 0; i < ((Operator) e).getOperandNumber(); i++) {
219                 result |= replaceInFilter(((Operator) e).getExpression(i), map);
220             }
221             return result;
222         }
223         else if (e instanceof FieldOperand) {
224             QueryTreeField qtf = (QueryTreeField) ((FieldOperand) e).getField();
225             Field neo = replaceField(qtf, map);
226             if (neo != qtf) {
227                 ((FieldOperand) e).setField(neo);
228                 if (debug) log.log(BasicLevel.DEBUG, "Replace in FieldOperand " + qtf.getName() + " by " + neo.getName());
229                 return true;
230             }
231         }
232         return false;
233     }
234
235     protected Field replaceField(QueryTreeField qtf, Map JavaDoc map)
236         throws MedorException {
237         QueryTree qtChild = qtf.getQueryTree();
238         UsedFields childUF = (UsedFields) map.get(qtChild);
239         if (childUF != null) {
240             int idx = qtChild.getTupleStructure().getFieldRank(qtf);
241             return childUF.fields[idx - 1];
242         }
243         else
244             return qtf;
245     }
246
247     private String JavaDoc printFields(Field[] fs) {
248         String JavaDoc m = "";
249         for (int i = 0; i < fs.length; i++) {
250             m += (i == 0 ? "" : ",") + fs[i].getName();
251         }
252         return m;
253     }
254
255 }
256
Popular Tags