1 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 ; 44 import java.util.Map ; 45 46 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 uf.isUseLess = 88 (children.length == 1) && 89 (qn instanceof FilteredQueryTree 90 ? qn.getQueryFilter() == null 91 : true); 92 93 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 UsedFields child = isUseless(children[0]); 107 if (debug) log.log(BasicLevel.DEBUG, "child: isUseLess:" + child.isUseLess + " ndfield: " + child.fields.length); 108 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 } 122 else { 123 if (debug) log.log(BasicLevel.DEBUG, "useful"); 124 Map childrenUseLess = new HashMap (); 126 for (i = 0; i < children.length; i++) { 127 childrenUseLess.put(children[i], isUseless(children[i])); 128 } 129 130 133 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 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 (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 if (qn instanceof FilteredQueryTree) { 178 Expression e = qn.getQueryFilter(); 179 if (replaceInFilter(e, childrenUseLess)) 180 qn.setQueryFilter(e); 181 } 182 183 } 185 186 if (debug) log.log(BasicLevel.DEBUG, "return " + printFields(uf.fields)); 187 return uf; 188 } 189 190 protected boolean replaceInFilter(Expression e, Map 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 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 printFields(Field[] fs) { 248 String 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 |