KickJava   Java API By Example, From Geeks To Geeks.

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


1 /**
2  * MEDOR: Middleware Enabling Distributed Object Requests
3  *
4  * Copyright (C) 2001-2005 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 java.util.ArrayList JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Map JavaDoc;
30
31 import org.objectweb.medor.api.Field;
32 import org.objectweb.medor.api.MedorException;
33 import org.objectweb.medor.expression.api.Expression;
34 import org.objectweb.medor.expression.api.Operator;
35 import org.objectweb.medor.filter.api.FieldOperand;
36 import org.objectweb.medor.query.api.CalculatedField;
37 import org.objectweb.medor.query.api.FilteredQueryTree;
38 import org.objectweb.medor.query.api.NestQueryNode;
39 import org.objectweb.medor.query.api.NestedField;
40 import org.objectweb.medor.query.api.PropagatedField;
41 import org.objectweb.medor.query.api.QueryLeaf;
42 import org.objectweb.medor.query.api.QueryNode;
43 import org.objectweb.medor.query.api.QueryTree;
44 import org.objectweb.medor.query.api.QueryTreeField;
45 import org.objectweb.medor.query.lib.QueryTreePrinter;
46 import org.objectweb.medor.query.rdb.api.RdbExpField;
47 import org.objectweb.medor.query.rdb.api.RdbExpQueryLeaf;
48 import org.objectweb.util.monolog.api.BasicLevel;
49
50 /**
51  * This class represents the rule to drop projected fields which are not used.
52  * <p>This rule is to be called on the root of the tree to be optimized.
53  * The projected fields of the root node will not be deleted (they are
54  * requested by the user).
55  * <p>
56  * As a remark, the user should be careful and not request unnecessary fields!
57  */

58 public class DropUnusedProjFieldsRule extends BasicRule {
59
60     public DropUnusedProjFieldsRule() {
61         super("DropUnusedProjFieldsRule");
62     }
63
64     /**
65      * Relies on a Map which associates to each child the list of required
66      * Fields for that child.
67      */

68     public QueryTree rewrite(QueryTree qt, QueryNode _parent)
69             throws MedorException {
70         debug = log != null && log.isLoggable(BasicLevel.DEBUG);
71         if (qt instanceof QueryNode) {
72             Field[] myFields = qt.getTupleStructure().getFields();
73             dropUnusedProjFields(qt, array2arrayList(myFields));
74         }
75         return qt;
76     }
77
78     private void dropUnusedProjFields(QueryTree qt,
79                                       ArrayList JavaDoc wanted)
80         throws MedorException {
81         if (debug) log.log(BasicLevel.DEBUG, "-Current node is " + qt);
82         if (debug) log.log(BasicLevel.DEBUG, "Query tree before dropping fields:");
83         if (debug) QueryTreePrinter.printQueryTree(qt, log);
84
85         Map JavaDoc qt2ReqFields = new HashMap JavaDoc();
86
87         if (debug) log.log(BasicLevel.DEBUG, " Drop unused fields from projected fields in according to usage");
88         //drop unused fields from projected fields
89
Field[] myFields = qt.getTupleStructure().getFields();
90         for (int i = 0; i < myFields.length; i++) {
91             if (debug) log.log(BasicLevel.DEBUG, "\tfield=" + myFields[i].getName());
92             if (!wanted.contains(myFields[i])) {
93                 if (debug) log.log(BasicLevel.DEBUG, "\tDropping field " + myFields[i].getName() + " (" + myFields[i] + ") " + " qt=" + qt);
94                 if (qt instanceof QueryNode) {
95                     ((QueryNode) qt).removeField(myFields[i].getName());
96                 }
97                 else if (qt instanceof RdbExpQueryLeaf)
98                     ((RdbExpQueryLeaf) qt).removeRdbField(
99                         (RdbExpField) myFields[i]);
100             }
101         }
102
103         if (debug) log.log(BasicLevel.DEBUG, "Query tree after dropping fields:");
104         if (debug) QueryTreePrinter.printQueryTree(qt, log);
105
106         if (qt instanceof QueryLeaf)
107             return;
108
109         //calculate the Map (qt child => { field }
110
if (debug) log.log(BasicLevel.DEBUG, " calculate the Map (qt child => { field }");
111         myFields = qt.getTupleStructure().getFields();
112         for (int i = 0; i < myFields.length; i++) {
113             if (debug) log.log(BasicLevel.DEBUG, "\tfield " + myFields[i].getName() + " is " + myFields[i]);
114             if (myFields[i] instanceof CalculatedField)
115                 addFieldFromExpression(qt2ReqFields,
116                     ((CalculatedField) myFields[i]).getExpression());
117             else
118                 addFieldInMap(qt2ReqFields, (QueryTreeField) myFields[i]);
119             //if other case, too bad
120
}
121         
122         if (qt instanceof NestQueryNode) {
123             myFields = ((NestQueryNode) qt).getNestingFields();
124             for (int i = 0; i < myFields.length; i++) {
125                 addAncestorsToMap(qt2ReqFields, new Field[] {(QueryTreeField) myFields[i]});
126             }
127         }
128
129         if (debug) log.log(BasicLevel.DEBUG, "Add field from the query filter");
130         addFieldFromExpression(qt2ReqFields,
131             ((FilteredQueryTree) qt).getQueryFilter());
132
133         if (debug) log.log(BasicLevel.DEBUG, "Recall on children");
134         //call on children
135
for (Iterator JavaDoc it = qt2ReqFields.entrySet().iterator(); it.hasNext();) {
136             Map.Entry JavaDoc e = (Map.Entry JavaDoc) it.next();
137             dropUnusedProjFields((QueryTree) e.getKey(),
138                 (ArrayList JavaDoc) e.getValue());
139         }
140     }
141
142     /**
143      * Adds the fields which are contained in a FieldOperand.
144      */

145     private void addFieldFromExpression(Map JavaDoc qt2ReqFields, Expression exp) {
146         if (exp instanceof FieldOperand) {
147             QueryTreeField f = (QueryTreeField) ((FieldOperand) exp).getField();
148             QueryTree qt = f.getQueryTree();
149             ArrayList JavaDoc fields = (ArrayList JavaDoc) qt2ReqFields.get(qt);
150             if (fields == null) {
151                 if (debug) log.log(BasicLevel.DEBUG, "addFieldFromExpression: FieldOperand, new Qt in map");
152                 fields = new ArrayList JavaDoc(1);
153                 fields.add(f);
154                 qt2ReqFields.put(qt, fields);
155             }
156             else if (!(fields.contains(f))) {
157                 if (debug) log.log(BasicLevel.DEBUG, "addFieldFromExpression: FieldOperand, Qt exists in map");
158                 fields.add(f);
159             } else {
160                 if (debug) log.log(BasicLevel.DEBUG, "addFieldFromExpression: FieldOperand already referenced");
161             }
162         } else if (exp instanceof Operator) {
163             if (debug) log.log(BasicLevel.DEBUG, "addFieldFromExpression: Operator");
164             for(int i=0; i<((Operator) exp).getOperandNumber(); i++) {
165                 addFieldFromExpression(qt2ReqFields,
166                     ((Operator) exp).getExpression(i));
167             }
168         }
169     }
170
171     private void addFieldInMap(Map JavaDoc qt2ReqFields, QueryTreeField field) {
172         if (debug) log.log(BasicLevel.DEBUG, "addFieldInMap: field " + field);
173         Field[] anc = null;
174         if (field instanceof PropagatedField) {
175             anc = ((PropagatedField) field).getPreviousFields();
176             if (debug) log.log(BasicLevel.DEBUG, "addFieldInMap: PropagatedField " + field.getName());
177         }
178         else if (field instanceof NestedField) {
179             anc = ((NestedField) field).getFields();
180             if (debug) log.log(BasicLevel.DEBUG, "addFieldInMap: NestedField " + field.getName());
181         }
182         else
183             anc = new Field[0];
184         addAncestorsToMap(qt2ReqFields, anc);
185     }
186     
187     private void addAncestorsToMap(Map JavaDoc qt2ReqFields, Field[] anc) {
188         if (debug) log.log(BasicLevel.DEBUG, "addFieldInMap: registered previous, nb=" + anc.length);
189         for (int i = 0; i < anc.length; i++) {
190             QueryTree qt = ((QueryTreeField) anc[i]).getQueryTree();
191             ArrayList JavaDoc fields = (ArrayList JavaDoc) qt2ReqFields.get(qt);
192             if (fields == null) {
193                 if (debug) log.log(BasicLevel.DEBUG, "addFieldInMap: Field, new Qt exists map");
194                 fields = new ArrayList JavaDoc(1);
195                 fields.add(anc[i]);
196                 qt2ReqFields.put(qt, fields);
197             }
198             else if (!(fields.contains(anc[i]))) {
199                 if (debug) log.log(BasicLevel.DEBUG, "addFieldInMap: Field, Qt exists in map");
200                 fields.add(anc[i]);
201             }
202             else {
203                 if (debug) log.log(BasicLevel.DEBUG, "addFieldInMap: Field already referenced");
204             }
205         }
206     }
207
208     private ArrayList JavaDoc array2arrayList(Object JavaDoc[] array) {
209         ArrayList JavaDoc alist = new ArrayList JavaDoc(array.length);
210         for (int i = 0; i < array.length; i++) {
211             alist.add(array[i]);
212         }
213         return alist;
214     }
215 }
216
Popular Tags