1 2 12 package com.versant.core.jdo.query.mem; 13 14 import com.versant.core.jdo.query.*; 15 import com.versant.core.jdo.query.MemVisitor; 16 import com.versant.core.metadata.FieldMetaData; 17 import com.versant.core.metadata.ClassMetaData; 18 import com.versant.core.metadata.MDStatics; 19 20 import com.versant.lib.bcel.generic.*; 21 import com.versant.lib.bcel.Constants; 22 23 import com.versant.core.common.BindingSupportImpl; 24 import com.versant.core.jdo.QueryStateWrapper; 25 26 29 public class ByteCodeQCompareVisitor implements MemVisitor { 30 31 private ClassMetaData candidateClass; 32 private ClassGen cg; 33 private ConstantPoolGen cp; 34 private InstructionList il; 35 private MethodGen mg; 36 private InstructionFactory factory; 37 38 private boolean first = true; 39 40 private static final String NAME_Q_STATE_WRAPPER = QueryStateWrapper.class.getName(); 41 private static final String M_NAME_GETSTATE = "getState"; 42 43 44 private static final String NAME_COMPARABLE = Comparable .class.getName(); 45 46 private static final Type[] ARG_TYPES_INT = new Type[] {Type.INT}; 47 private static final Type[] ARG_TYPES_OBJECT = new Type[] {Type.OBJECT}; 48 49 50 private int stateParamNo = 1; 51 private boolean ascending = false; 52 private int var1Index; 53 54 55 public ByteCodeQCompareVisitor(ClassGen classGen, InstructionFactory factory, String name, ClassMetaData candidateClass) { 56 this.candidateClass = candidateClass; 57 cg = classGen; 58 this.factory = factory; 59 cp = cg.getConstantPool(); 60 61 this.il = new InstructionList(); 62 mg = new MethodGen(Constants.ACC_PUBLIC, Type.INT, new Type[] {new ObjectType(NAME_Q_STATE_WRAPPER), new ObjectType(NAME_Q_STATE_WRAPPER)}, 65 new String [] {"state1", "state2"}, "compare", name, this.il, cp); 68 69 70 il.append(InstructionConstants.ICONST_0); 72 LocalVariableGen var1 = mg.addLocalVariable("compResult", 73 Type.INT, null, null); 74 var1Index = var1.getIndex(); 75 il.append(new ISTORE(var1Index)); 76 var1.setStart(il.append(new NOP())); 77 } 78 79 public void finish() { 80 il.append(new ILOAD(var1Index)); 81 il.append(InstructionConstants.IRETURN); 82 mg.removeNOPs(); 83 mg.setMaxLocals(); 84 mg.setMaxStack(); 85 cg.addMethod(mg.getMethod()); 86 il.dispose(); 87 } 88 89 public Field visitNode(Node node, Object obj) { 90 throw BindingSupportImpl.getInstance().notImplemented(null); 91 } 92 93 99 public Field visitLiteralNode(LiteralNode node, Object obj) { 100 throw BindingSupportImpl.getInstance().notImplemented(null); 101 } 102 103 109 public Field visitFieldNavNode(FieldNavNode node, Object obj) { 110 return visitStateFieldNavNodeRoot(node, candidateClass); 111 } 112 113 private Field visitStateFieldNavNodeRoot(FieldNavNode node, ClassMetaData currentClass) { 114 FieldMetaData f = null; 115 f = currentClass.getFieldMetaData(node.lexeme); 116 if(f == null){ 117 throw BindingSupportImpl.getInstance().runtime("Class "+currentClass+ 118 " does not have a field "+ node.lexeme); 119 } 120 switch(f.category){ 121 case FieldMetaData.CATEGORY_REF: 122 InstructionHandle ih = null; 123 il.append(new ALOAD(stateParamNo)); il.append(new PUSH(cp, f.stateFieldNo)); 125 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, M_NAME_GETSTATE, 126 new ObjectType(NAME_Q_STATE_WRAPPER), ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 127 first = false; 128 if (node.childList instanceof FieldNavNode) { 129 visitStateFieldNavNode((FieldNavNode) node.childList, f.typeMetaData, ih); 130 } else { 131 visitFieldNode((FieldNode) node.childList, f.typeMetaData); 132 } 133 break; 134 default: 135 throw BindingSupportImpl.getInstance().internal("Only PersistenceCapable fields can be navigated"); 136 } 137 return null; 138 } 139 140 private Field visitStateFieldNavNode(FieldNavNode node, ClassMetaData currentClass, InstructionHandle ih) { 141 Field result = null; 142 FieldMetaData f = currentClass.getFieldMetaData(node.lexeme); 143 if(f == null){ 144 throw BindingSupportImpl.getInstance().runtime("Class "+currentClass+ 145 " does not have a field "+ node.lexeme); 146 } 147 switch(f.category){ 148 case FieldMetaData.CATEGORY_REF: 149 il.append(new PUSH(cp, f.stateFieldNo)); 150 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, M_NAME_GETSTATE, 151 new ObjectType(NAME_Q_STATE_WRAPPER), ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 152 if (node.childList instanceof FieldNavNode) { 153 result = visitStateFieldNavNode((FieldNavNode) node.childList, f.typeMetaData, ih); 154 } else { 155 result = visitFieldNode((FieldNode) node.childList, f.typeMetaData); 156 } 157 break; 158 default: 159 throw BindingSupportImpl.getInstance().internal("Only PersistenceCapable fields can be navigated"); 160 } 161 return result; 162 } 163 164 public Field visitMethodNode(MethodNode node, Object obj) { 165 throw BindingSupportImpl.getInstance().notImplemented(null); 166 } 167 168 public Field visitPrimaryExprNode(PrimaryExprNode node, Object obj) { 169 return null; 170 } 171 172 public Field visitFieldNode(FieldNode node, ClassMetaData cmd) { 173 if (cmd == null) { 174 return visitFieldNodeImp(candidateClass.getFieldMetaData(node.lexeme), node); 175 } else { 176 return visitFieldNodeImp(cmd.getFieldMetaData(node.lexeme), node); 177 } 178 } 179 180 private Field visitFieldNodeImp(FieldMetaData fmd, FieldNode node) { 181 if (fmd == null) { 182 throw BindingSupportImpl.getInstance().runtime("Class " + candidateClass.qname + " does not have a field: " + node.lexeme); 183 } 184 if (first) { 185 first = false; 186 il.append(new ALOAD(stateParamNo)); il.append(new PUSH(cp, fmd.stateFieldNo)); 188 } else { 189 il.append(new PUSH(cp, fmd.stateFieldNo)); 190 } 191 il.append(factory.createInvoke(NAME_Q_STATE_WRAPPER, fmd.stateGetMethodName, getBCellStateFieldType(fmd), 192 ARG_TYPES_INT, Constants.INVOKEVIRTUAL)); 193 194 if (stateParamNo == 2) { 195 if (fmd.type.isPrimitive()) { 196 switch (fmd.typeCode) { 197 case MDStatics.BYTE: 198 case MDStatics.SHORT: 199 case MDStatics.CHAR: 200 case MDStatics.INT: 201 il.append(InstructionConstants.ISUB); 202 break; 203 case MDStatics.LONG: 204 il.append(InstructionConstants.LSUB); 205 il.append(InstructionConstants.L2I); 206 break; 207 case MDStatics.FLOAT: 208 il.append(factory.createInvoke(Float .class.getName(), "compare", Type.INT, 209 new Type[] {Type.FLOAT, Type.FLOAT}, Constants.INVOKEVIRTUAL)); 210 break; 211 case MDStatics.DOUBLE: 212 il.append(factory.createInvoke(Double .class.getName(), "compare", Type.INT, 213 new Type[] {Type.DOUBLE, Type.DOUBLE}, Constants.INVOKEVIRTUAL)); 214 215 break; 216 default: 217 throw BindingSupportImpl.getInstance().notImplemented(null); 218 } 219 220 } else { 221 il.append(factory.createInvoke(NAME_COMPARABLE, "compareTo", Type.INT, 222 ARG_TYPES_OBJECT, Constants.INVOKEINTERFACE)); 223 } 224 225 if (ascending) { 226 il.append(InstructionConstants.ICONST_M1); 227 il.append(InstructionConstants.IMUL); 228 } 229 il.append(new ISTORE(var1Index)); 230 231 il.append(new ILOAD(var1Index)); 232 BranchInstruction bInstr = new IFEQ(null); 233 il.append(bInstr); 234 235 il.append(new ILOAD(var1Index)); 236 il.append(InstructionConstants.IRETURN); 237 238 InstructionHandle endHandle = il.append(InstructionConstants.NOP); 239 bInstr.setTarget(endHandle); 240 241 } 242 return null; 243 } 244 245 public Field visitFieldNode(FieldNode node, Object obj) { 246 return visitFieldNodeImp(candidateClass.getFieldMetaData(node.lexeme), node); 247 } 248 249 private static final Type getBCellStateFieldType(FieldMetaData fmd) { 250 switch (fmd.category) { 251 case MDStatics.CATEGORY_SIMPLE: 252 return getTypeFromTypeCode(fmd.typeCode); 253 default: 254 return Type.OBJECT; 255 } 256 } 257 258 private static Type getTypeFromTypeCode(int typeCode) { 259 switch (typeCode) { 260 case MDStatics.INT: 261 return Type.INT; 262 case MDStatics.LONG: 263 return Type.LONG; 264 case MDStatics.SHORT: 265 return Type.SHORT; 266 case MDStatics.STRING: 267 return Type.STRING; 268 case MDStatics.BOOLEAN: 269 return Type.BOOLEAN; 270 case MDStatics.BYTE: 271 return Type.BYTE; 272 case MDStatics.CHAR: 273 return Type.CHAR; 274 case MDStatics.DOUBLE: 275 return Type.DOUBLE; 276 case MDStatics.FLOAT: 277 return Type.FLOAT; 278 default: 279 return Type.OBJECT; 280 } 281 } 282 283 public Field visitEqualNode(EqualNode node, Object obj) { 284 throw BindingSupportImpl.getInstance().notImplemented(null); 285 } 286 287 public Field visitNotEqualNode(NotEqualNode node, Object obj) { 288 throw BindingSupportImpl.getInstance().notImplemented(null); 289 } 290 291 public Field visitLikeNode(LikeNode node, Object obj) { 292 return null; 293 } 294 295 public Field visitAndNode(AndNode node, Object obj) { 296 throw BindingSupportImpl.getInstance().notImplemented(null); 297 } 298 299 public Field visitOrNode(OrNode node, Object obj) { 300 throw BindingSupportImpl.getInstance().notImplemented(null); 301 } 302 303 public Field visitMultiplyNode(MultiplyNode node, Object obj) { 304 throw BindingSupportImpl.getInstance().notImplemented(null); 305 } 306 307 public Field visitAddNode(AddNode node, Object obj) { 308 throw BindingSupportImpl.getInstance().notImplemented(null); 309 } 310 311 public Field visitUnaryOpNode(UnaryOpNode node, Object obj) { 312 throw BindingSupportImpl.getInstance().notImplemented(null); 313 } 314 315 public Field visitCompareOpNode(CompareOpNode node, Object obj) { 316 throw BindingSupportImpl.getInstance().notImplemented(null); 317 } 318 319 public Field visitUnaryNode(UnaryNode node, Object obj) { 320 node.childList.visit(this,obj); 321 return null; 322 } 323 324 public Field visitBinaryNode(BinaryNode node, Object obj) { 325 return null; 326 } 327 328 public Field visitMultiNode(Node node, Object obj) { 329 return null; 330 } 331 332 public Field visitCastNode(CastNode node, Object obj) { 333 return null; 334 } 335 336 public Field visitParamNode(ParamNode node, Object obj) { 337 throw BindingSupportImpl.getInstance().notImplemented(null); 338 } 339 340 public Field visitParamNodeProxy(ParamNodeProxy node, Object obj) { 341 return node.getParamNode().visit(this, obj); 342 } 343 344 public Field visitArgNode(ArgNode node, Object obj) { 345 return null; 346 } 347 348 public Field visitArrayNode(ArrayNode node, Object obj) { 349 return null; 350 } 351 352 public Field visitImportNode(ImportNode node, Object obj) { 353 return null; 354 } 355 356 public Field visitLeafNode(LeafNode node, Object obj) { 357 return null; 358 } 359 360 public Field visitOrderNode(OrderNode node, Object obj) { 361 if (node.order == OrderNode.ORDER_ASCENDING) { 362 ascending = true; 363 } else { 364 ascending = false; 365 } 366 first = true; 367 stateParamNo = 1; 368 node.childList.visit(this, obj); 369 first = true; 370 stateParamNo = 2; 371 node.childList.visit(this, obj); 372 return null; 373 } 374 375 public Field visitVarNode(VarNode node, Object obj) { 376 return null; 377 } 378 379 public Field visitVarNodeProxy(VarNodeProxy node, Object obj) { 380 return node.getVarNode().visit(this, obj); 381 } 382 383 public Field visitReservedFieldNode(ReservedFieldNode node, Object obj) { 384 return null; 385 } 386 } 387 | Popular Tags |