1 package org.jicengine.element; 2 3 import java.util.ArrayList ; 4 import java.util.List ; 5 6 import org.jicengine.operation.Context; 7 import org.jicengine.operation.LocalContext; 8 import org.jicengine.operation.Operation; 9 import org.jicengine.operation.OperationException; 10 11 67 68 public class ElementImpl extends AbstractElement { 69 70 75 public class VariableElementImpl implements VariableElement { 76 public String getName() 77 { 78 return ElementImpl.this.getName(); 79 } 80 81 public Location getLocation() 82 { 83 return ElementImpl.this.getLocation(); 84 } 85 86 public boolean isExecuted(Context outerContext, Object parentInstance) throws ElementException 87 { 88 return ElementImpl.this.isExecuted(outerContext,parentInstance); 89 } 90 91 92 public Object getValue(Context context, Object parentInstance) throws ElementException 93 { 94 return ElementImpl.this.execute(context, parentInstance); 95 } 96 97 public Class getInstanceClass() 98 { 99 return ElementImpl.this.getInstanceClass(); 100 } 101 102 public String toString() 103 { 104 return "<" + getName() + ">"; 105 } 106 } 107 108 113 public class ActionElementImpl implements ActionElement { 114 public String getName() 115 { 116 return ElementImpl.this.getName(); 117 } 118 119 public Location getLocation() 120 { 121 return ElementImpl.this.getLocation(); 122 } 123 124 public boolean isExecuted(Context outerContext, Object parentInstance) throws ElementException 125 { 126 return ElementImpl.this.isExecuted(outerContext,parentInstance); 127 } 128 129 public void execute(Context context, Object parentInstance) throws ElementException 130 { 131 ElementImpl.this.execute(context, parentInstance); 132 } 133 134 public String toString() 135 { 136 return "<" + getName() + ">"; 137 } 138 } 139 140 141 protected static final int CHILD_TYPE_CONSTRUCTOR_ARG = 0; 142 protected static final int CHILD_TYPE_ACTION_ARG = 1; 143 protected static final int CHILD_TYPE_ACTION = 2; 144 protected static final int CHILD_TYPE_VARIABLE = 3; 145 146 private Operation condition; 147 148 private String [] variableNames; 149 150 private Operation constructor; 151 private Class instanceClass; 152 153 private String overridableBy; 154 155 private List childElements = new ArrayList (); 156 private List childElementTypes = new ArrayList (); 157 private int lastConstructorArgumentIndex = -1; 158 159 private Operation action; 160 161 public ElementImpl(String name, Location location) 162 { 163 super(name, location); 164 } 165 166 public void setConstructor(Operation operation) throws ElementException 167 { 168 if( this.constructor != null ){ 169 throw new ElementException("Constructor already set to '" + this.constructor + "', new constructor '" + operation + "' not accepted.", getName(), getLocation()); 170 } 171 this.constructor = operation; 172 } 173 174 178 public void deleteConstructor() 179 { 180 this.constructor = null; 181 } 182 183 public void setOverridableBy(String overridingId) 184 { 185 this.overridableBy = overridingId; 186 } 187 188 192 public void setVariableNames(String [] elementNames) throws ElementException 193 { 194 if( this.variableNames != null ){ 195 throw new ElementException("Variables already set.", getName(), getLocation()); 196 } 197 this.variableNames = elementNames; 198 } 199 200 public void setInstanceClass(Class instanceClass) throws ElementException 201 { 202 if( this.instanceClass != null ){ 203 throw new ElementException("Class already set to '" + this.instanceClass + "', new class '" + instanceClass + "' not accepted.", getName(), getLocation()); 204 } 205 this.instanceClass = instanceClass; 206 } 207 208 public void setAction(Operation operation) throws ElementException 209 { 210 if( this.action != null ){ 211 throw new ElementException("Action already set to '" + this.action + "', new action '" + operation + "' not accepted.", getName(), getLocation()); 212 } 213 this.action = operation; 214 } 215 216 public void setIf(Operation condition) throws ElementException 217 { 218 if( this.condition != null ){ 219 throw new ElementException("If condition already set to '" + this.condition + "'", getName(), getLocation()); 220 } 221 this.condition = condition; 222 } 223 224 public Operation getIf() 225 { 226 return this.condition; 227 } 228 229 public Operation getConstructor() 230 { 231 return this.constructor; 232 } 233 234 public Class getInstanceClass() 235 { 236 return this.instanceClass; 237 } 238 239 public Operation getAction() 240 { 241 return this.action; 242 } 243 244 protected boolean isOverridden(Context context) 245 { 246 return (this.overridableBy != null && context.hasObject(org.jicengine.expression.BuildParameterParser.PREFIX + this.overridableBy)); 248 } 249 250 public boolean isElementVariable(String elementName) 251 { 252 if( this.variableNames != null ){ 253 for (int i = 0; i < this.variableNames.length; i++) { 254 if( this.variableNames[i] != null && this.variableNames[i].equals(elementName) ){ 255 return true; 257 } 258 } 259 } 260 return false; 262 } 263 264 public boolean isConstructorVariable(String elementName) 265 { 266 return getConstructor() != null && getConstructor().needsParameter(elementName); 267 } 268 269 public boolean isActionVariable(String elementName) 270 { 271 return getAction() != null && getAction().needsParameter(elementName); 272 } 273 274 281 protected void variablePublished(String name) 282 { 283 if( this.variableNames != null ){ 284 for (int i = 0; i < this.variableNames.length; i++) { 285 if( this.variableNames[i] != null && this.variableNames[i].equals(name) ){ 286 this.variableNames[i] = null; 288 } 289 } 290 } 291 } 292 293 protected void verifyVariablesHaveBeenFound() throws ElementException 294 { 295 if( this.variableNames != null ){ 296 for (int i = 0; i < this.variableNames.length; i++) { 297 if( this.variableNames[i] != null ){ 298 throw new ElementException("Element variable '" + this.variableNames[i] + "' not found.", getName(), "vars", getLocation()); 299 } 300 } 301 } 302 } 303 304 310 private Object getOverridingObject(Context context) throws ElementException 311 { 312 Object overridingObject = null; 313 314 if( isOverridden(context) ) { 315 try { 317 overridingObject = context.getObject(org.jicengine.expression.BuildParameterParser.PREFIX + this.overridableBy); 318 } catch (org.jicengine.operation.ObjectNotFoundException e){ 319 throw new RuntimeException ("Build parameter not found although it should", e); 320 } 321 validateInstance(overridingObject, true); 323 } 324 return overridingObject; 325 } 326 327 337 public Element toRuntimeElement() throws ElementException 338 { 339 if(this.action != null) { 340 return new ActionElementImpl(); 341 } 342 else if(this.constructor != null || this.overridableBy != null) { 343 return new VariableElementImpl(); 344 } 345 else { 346 throw new ElementException("Element without action nor value is not allowed.", getName(), getLocation()); 348 } 349 } 350 351 public String toString() 352 { 353 return "<" + getName() + ">"; 354 } 355 356 360 public boolean isUsed(VariableElement child) 361 { 362 String name = child.getName(); 363 return isConstructorVariable(name) || isActionVariable(name) || isElementVariable(name); 364 } 365 366 374 public void addChildElement(Element child) throws ElementException 375 { 376 if( child instanceof ActionElement ){ 377 addChildElement(child, CHILD_TYPE_ACTION); 379 } 380 else if( child instanceof VariableElement ){ 381 VariableElement valueChild = (VariableElement) child; 382 String childName = valueChild.getName(); 383 384 386 if( isElementVariable(childName) ){ 387 addChildElement(child, CHILD_TYPE_VARIABLE); 389 } 390 else if( isConstructorVariable(childName) ){ 391 addChildElement(child, CHILD_TYPE_CONSTRUCTOR_ARG); 393 } 394 else if( isActionVariable(childName) ){ 395 addChildElement(child, CHILD_TYPE_ACTION_ARG); 397 } 398 else { 399 throw new ElementException("The element " + child + " has no use.", child.getName(), child.getLocation()); 401 } 402 } 403 else { 404 throw new RuntimeException ("unknown child-element type: '" + child.getClass().getName() + "'"); 405 } 406 } 407 408 private void addChildElement(Element child, int type) 409 { 410 this.childElements.add(child); 411 this.childElementTypes.add(new Integer (type)); 412 413 if( type == CHILD_TYPE_CONSTRUCTOR_ARG || 415 (type == CHILD_TYPE_VARIABLE && getConstructor() != null && getConstructor().needsParameter(child.getName()) ) 416 ){ 417 419 this.lastConstructorArgumentIndex = this.childElements.size()-1; 420 } 421 } 422 423 433 private Object obtainElementInstance(Context constructorContext, boolean isOverridden) throws ElementException 434 { 435 Object instance; 436 if(isOverridden) { 437 instance = getOverridingObject(constructorContext); 439 } 440 else if(this.constructor != null) { 441 instance = executeConstructor(constructorContext); 442 } 443 else if(this.overridableBy != null) { 444 throw new ElementException("Required overriding '" + this.overridableBy + "' not found.", getName(), getLocation()); 446 } 447 else { 448 throw new IllegalStateException ("No constructor and no overriding - no instance available (" + getName() + " at " + getLocation() + ")"); 449 } 450 451 return instance; 452 } 453 454 458 private void executeAction(Context actionContext) throws ElementException 459 { 460 if(this.action == null) { 461 throw new IllegalStateException ("Action is null"); 462 } 463 464 try { 465 this.action.execute(actionContext); 466 } catch(OperationException e) { 467 throw new ElementException(e, getName(), ElementCompiler.ATTR_NAME_ACTION, getLocation()); 468 } 469 } 470 471 481 private Object executeConstructor(Context constructorContext) throws ElementException 482 { 483 if(this.constructor == null) { 484 throw new IllegalStateException ("executeConstructor() called although constructor is null. (" + getName() + " at " + getLocation() + ")"); 485 } 486 487 Object instance = null; 489 try { 490 instance = this.constructor.execute(constructorContext); 491 } catch(OperationException e) { 492 throw new ElementException(e, getName(), "instance", getLocation()); 493 } 494 495 validateInstance(instance, false); 496 return instance; 497 } 498 499 512 protected void validateInstance(Object instance, boolean isOverridingObject) throws ElementException 513 { 514 if( instance == null ){ 515 throw new ElementException("Element instance is null - null values not allowed.", getName(), getLocation()); 516 } 517 518 if( this.instanceClass != null && !org.jicengine.operation.ReflectionUtils.isAssignableFrom(this.instanceClass, instance.getClass()) ){ 519 if( isOverridingObject ){ 520 throw new ElementException("The overriding object '" + this.overridableBy + "' was of type '" + instance.getClass().getName() + "', expected '" + this.instanceClass.getName() + "'", getName(), getLocation()); 521 } 522 else { 523 throw new ElementException("Expected the instance to be of type '" + this.instanceClass.getName() + "', was '" + instance.getClass().getName() + "'", getName(), getLocation()); 524 } 525 } 526 } 527 528 public boolean isExecuted(Context outerContext, Object parentInstance) throws ElementException 529 { 530 if( this.condition == null ){ 531 return true; 532 } 533 else { 534 Context ifContext = new LocalContext("<" + getName() + ">//if", outerContext); 535 if( parentInstance != null ){ 536 ifContext.addObject(Element.VARIABLE_NAME_PARENT_INSTANCE, parentInstance); 538 } 539 540 try { 541 Object result = this.condition.execute(ifContext); 542 return toBoolean(result); 543 } catch (OperationException e){ 544 throw new ElementException(e, getName(), "if", getLocation()); 545 } 546 } 547 } 548 549 private boolean toBoolean(Object result) 550 { 551 if( result == null ){ 552 return false; 553 } 554 else if( result instanceof Boolean ){ 555 return ((Boolean )result).booleanValue(); 556 } 557 else { 558 return true; 561 } 562 } 563 564 585 protected Object execute(Context outerContext, Object parentInstance) throws ElementException 586 { 587 Context elementContext = new LocalContext("<" + getName() + ">", outerContext); 588 589 Context constructorContext = new LocalContext("<" + getName() + ">//instance", elementContext); 591 Context actionContext = new LocalContext("<" + getName() + ">//action", elementContext); 592 593 if( parentInstance != null ){ 594 constructorContext.addObject(VARIABLE_NAME_PARENT_INSTANCE, parentInstance); 596 actionContext.addObject(VARIABLE_NAME_PARENT_INSTANCE, parentInstance); 597 } 598 599 boolean isOverridden = isOverridden(outerContext); 600 601 615 617 for (int i = 0; i <= this.lastConstructorArgumentIndex; i++) { 619 Element child = (Element) childElements.get(i); 620 executeChild(child, ((Integer )childElementTypes.get(i)).intValue(), elementContext, null, constructorContext, actionContext, isOverridden); 621 } 622 623 Object instance = null; 624 if( this.constructor != null || this.overridableBy != null) { 625 instance = obtainElementInstance(constructorContext, isOverridden); 629 } 630 631 for (int i = (this.lastConstructorArgumentIndex+1) ; i < childElements.size() ; i++) { 633 Element child = (Element) childElements.get(i); 634 executeChild(child, ((Integer )this.childElementTypes.get(i)).intValue(), elementContext, instance, constructorContext, actionContext, isOverridden); 637 } 638 639 verifyVariablesHaveBeenFound(); 641 642 if( this.action != null ){ 643 644 if( instance != null ){ 645 actionContext.addObject(Element.VARIABLE_NAME_ELEMENT_INSTANCE, instance); 646 } 647 executeAction(actionContext); 648 } 649 650 return instance; 652 } 653 654 665 private void executeChild(Element child, int type, Context elementContext, Object instance, Context constructorContext, Context actionContext, boolean isOverridden) throws ElementException 666 { 667 if( isOverridden ){ 668 if( type == CHILD_TYPE_ACTION_ARG ){ 670 if( child.isExecuted(elementContext, instance) ){ 673 Object value = ((VariableElement) child).getValue(elementContext, instance); 674 actionContext.addObject(child.getName(), value); 675 } 676 } 677 } 678 else if( child.isExecuted(elementContext, instance) ){ 679 if( child instanceof VariableElement ){ 681 Object value = ((VariableElement)child).getValue(elementContext,instance); 683 684 if( type == CHILD_TYPE_CONSTRUCTOR_ARG ){ 686 constructorContext.addObject(child.getName(), value); 687 } 688 else if( type == CHILD_TYPE_VARIABLE ){ 689 elementContext.addObject(child.getName(), value); 690 variablePublished(child.getName()); 691 } 692 else if( type == CHILD_TYPE_ACTION_ARG ){ 693 actionContext.addObject(child.getName(), value); 694 } 695 else { 696 throw new RuntimeException ("illegal variable element type."); 697 } 698 } 699 else { 700 ((ActionElement)child).execute(elementContext, instance); 702 } 703 } 704 else { 705 } 707 } 708 } 709 | Popular Tags |