1 package org.objectweb.medor.query.jorm.lib; 2 3 import org.objectweb.jorm.metainfo.api.Class; 4 import org.objectweb.jorm.metainfo.api.ClassRef; 5 import org.objectweb.jorm.metainfo.api.GenClassRef; 6 import org.objectweb.jorm.metainfo.api.Reference; 7 import org.objectweb.jorm.metainfo.api.TypedElement; 8 import org.objectweb.medor.api.Field; 9 import org.objectweb.medor.api.MedorException; 10 import org.objectweb.medor.api.TupleStructure; 11 import org.objectweb.medor.expression.api.Expression; 12 import org.objectweb.medor.expression.lib.And; 13 import org.objectweb.medor.expression.lib.Equal; 14 import org.objectweb.medor.filter.lib.BasicFieldOperand; 15 import org.objectweb.medor.lib.Log; 16 import org.objectweb.medor.query.api.PropagatedField; 17 import org.objectweb.medor.query.api.QueryTree; 18 import org.objectweb.medor.query.api.QueryTreeField; 19 import org.objectweb.medor.query.lib.JoinProject; 20 import org.objectweb.medor.query.jorm.api.JormExtent; 21 import org.objectweb.util.monolog.api.Logger; 22 23 import java.util.Map ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 27 32 33 public class QueryBuilder { 34 35 public static Logger log = Log.getLoggerFactory() 36 .getLogger("org.objectweb.medor.query.jorm.lib.QueryBuilder"); 37 38 private static final String GENCLASS_ELEMENT_NAME = "genClassElement"; 39 40 private QueryBuilder m_parent = null; 42 43 private JoinProject m_join = new JoinProject(); 45 46 private int m_id = 0; 48 49 private Map m_fields = new HashMap (); 52 53 private Map m_projected = new HashMap (); 55 56 private Map m_joins = new HashMap (); 58 59 62 63 public QueryBuilder() { 64 this(null); 65 } 66 67 73 74 public QueryBuilder(QueryBuilder parent) { 75 m_parent = parent; 76 } 77 78 82 83 public QueryTree getQueryTree() { 84 return m_join; 85 } 86 87 93 94 public boolean contains(String path) { 95 return m_fields.containsKey(path); 96 } 97 98 105 106 public void define(String name, QueryTreeField field) 107 throws MedorException { 108 if (m_fields.containsKey(name)) { 109 throw new IllegalArgumentException 110 ("duplicate definition: " + name + 111 ", old value: " + m_fields.get(name) + 112 ", new value: " + field); 113 } 114 m_fields.put(name, field); 115 } 116 117 124 125 public QueryTreeField project(QueryTreeField qtf) throws MedorException { 126 QueryTreeField result = (QueryTreeField) m_projected.get(qtf); 127 if (result == null) { 128 result = m_join.addPropagatedField 129 (qtf.getName(), qtf.getType(), new QueryTreeField[] { qtf }); 130 m_projected.put(qtf, result); 131 } 132 return result; 133 } 134 135 139 140 private String name(String [] path, int length) { 141 StringBuffer buf = new StringBuffer (); 142 String sep = ""; 143 for (int i = 0; i < length; i++) { 144 buf.append(sep); 145 buf.append(path[i]); 146 sep = "."; 147 } 148 return buf.toString(); 149 } 150 151 private int id() { 152 if (m_parent == null) { 153 return m_id++; 154 } else { 155 return m_parent.id(); 156 } 157 } 158 159 163 164 private PNameField getPNameField(Field field) { 165 if (field instanceof PNameField) { 166 return (PNameField) field; 167 } else if (field instanceof PropagatedField) { 168 return getPNameField 169 (((PropagatedField) field).getPreviousFields()[0]); 170 } else { 171 return null; 172 } 173 } 174 175 188 189 private PNameField join(QueryTreeField parent) 190 throws MedorException { 191 PNameField ppnf = getPNameField(parent); 192 if (ppnf.isClassPName()) { 193 return ppnf; 194 } 195 196 PNameField pnf = (PNameField) m_joins.get(parent); 197 if (pnf != null) { return pnf; } 198 199 JormExtent ext; 200 Reference ref = ppnf.getReference(); 201 String name = parent.getName(); 202 String pnfname = "object" + id(); 203 if (ref instanceof ClassRef) { 204 ClassRef cref = (ClassRef) ref; 205 ext = new ClassExtent(cref.getMOClass(), name, pnfname, true); 206 } else if (ref instanceof GenClassRef) { 207 GenClassRef gcref = (GenClassRef) ref; 208 ext = new GenClassExtent 209 (gcref, name, pnfname, GENCLASS_ELEMENT_NAME); 210 } else { 211 throw new IllegalStateException 212 ("unknown ref type: " + ref.getClass()); 213 } 214 pnf = (PNameField) ext.getTupleStructure().getField 215 (ext.getPNameFieldName()); 216 217 Expression cond = new Equal 218 (new BasicFieldOperand(parent), new BasicFieldOperand(pnf)); 219 Expression filter = m_join.getQueryFilter(); 220 if (filter == null) { 221 filter = cond; 222 } else { 223 filter = new And(filter, cond); 224 } 225 m_join.setQueryFilter(filter); 226 227 m_joins.put(parent, pnf); 228 229 return pnf; 230 } 231 232 243 244 private QueryTreeField navigate(QueryTreeField parent, String field) 245 throws MedorException { 246 PNameField pnf = join(parent); 247 248 QueryTreeField qtf; 249 QueryTree qt = pnf.getQueryTree(); 250 TupleStructure ts = qt.getTupleStructure(); 251 String fq = qt.getName() + "." + field; 252 if (ts.contains(fq)) { 253 qtf = (QueryTreeField) ts.getField(fq); 254 } else if (qt instanceof ClassExtent) { 255 ClassExtent extent = (ClassExtent) qt; 256 Class klass = (Class ) extent.getMetaObject(); 257 TypedElement te = klass.getTypedElement(field); 258 if (te == null) { 259 StringBuffer buf = new StringBuffer (); 260 buf.append("No such field '").append(field); 261 buf.append("' in '").append(klass.getFQName()); 262 buf.append("' from ").append(parent); 263 for (Iterator it = klass.getAllFields().iterator(); 264 it.hasNext(); ) { 265 TypedElement el = (TypedElement) it.next(); 266 buf.append(", ").append(el.getName()); 267 } 268 throw new IllegalArgumentException (buf.toString()); 269 } else { 270 qtf = extent.addField(te); 271 } 272 } else { 273 throw new IllegalStateException 274 ("wrong extent type: " + qt.getClass() + 275 "\nfor field: " + field); 276 } 277 278 return qtf; 279 } 280 281 private boolean isGenClassReference(QueryTreeField qtf) { 282 PNameField pnf = getPNameField(qtf); 283 if (pnf == null) { return false; } 284 if (!pnf.isClassPName()) { 285 return pnf.getReference() instanceof GenClassRef; 286 } 287 return false; 288 } 289 290 300 301 private QueryTreeField navigate(String [] path, int length) 302 throws MedorException { 303 String name = name(path, length); 304 QueryTreeField qtf = (QueryTreeField) m_fields.get(name); 305 if (qtf != null) { return qtf; } 307 308 if (length == 0) { 309 throw new IllegalArgumentException 310 ("no such path: " + name(path, path.length)); 311 } 312 313 QueryTreeField parent = navigate(path, length - 1); 314 qtf = navigate(parent, path[length - 1]); 315 if (isGenClassReference(qtf)) { 316 qtf = navigate(qtf, GENCLASS_ELEMENT_NAME); 317 } 318 define(name, qtf); 319 320 return qtf; 321 } 322 323 331 332 public QueryTreeField navigate(String [] path) throws MedorException { 333 return navigate(path, path.length); 334 } 335 336 private static final String DOT = "\\."; 337 338 346 347 public QueryTreeField navigate(String path) throws MedorException { 348 String [] parts = path.split(DOT); 349 return navigate(parts); 350 } 351 352 } 353 | Popular Tags |