1 10 11 package org.mmbase.bridge.util; 12 13 import java.util.*; 14 import java.io.*; 15 16 import java.text.Collator ; 17 18 import org.mmbase.bridge.*; 19 import org.mmbase.bridge.implementation.BasicFieldValue; 20 import org.mmbase.datatypes.DataType; 21 import org.mmbase.util.functions.*; 22 import org.mmbase.util.logging.*; 23 import org.mmbase.util.*; 24 25 import org.w3c.dom.Element ; 26 import org.w3c.dom.Document ; 27 28 38 public abstract class AbstractNode implements Node { 39 private static final Logger log = Logging.getLoggerInstance(AbstractNode.class); 40 41 protected static final int ACTION_CREATE = 1; protected static final int ACTION_EDIT = 2; protected static final int ACTION_DELETE = 3; protected static final int ACTION_COMMIT = 10; 46 protected abstract void edit(int action); 47 48 public boolean isRelation() { 49 return false; 50 } 51 52 public Relation toRelation() { 53 throw new ClassCastException ("The node " + this + " is not a relation, (but a " + getClass() + ")"); 54 } 55 56 public boolean isNodeManager() { 57 return false; 58 } 59 60 public NodeManager toNodeManager() { 61 throw new ClassCastException ("The node " + this + " is not a node manager , (but a " + getClass() + ")"); 62 } 63 64 public boolean isRelationManager() { 65 return false; 66 } 67 68 public RelationManager toRelationManager() { 69 throw new ClassCastException ("The node " + this + " is not a relation manager , (but a " + getClass() + ")"); 70 } 71 72 public boolean isNull(String fieldName) { 73 return getValueWithoutProcess(fieldName) == null; 74 } 75 76 public int getNumber() { 77 return Casting.toInt(getValueWithoutProcess("number")); 78 } 79 80 85 public final void setValue(String fieldName, Object value) { 86 Field field = getNodeManager().getField(fieldName); 87 if (value == null) { 88 setValueWithoutProcess(fieldName, value); 89 } else { 90 value = field.getDataType().cast(value, this, field); 91 switch(field.getDataType().getBaseType()) { 92 case Field.TYPE_STRING: setStringValue(fieldName, (String ) value); break; 93 case Field.TYPE_INTEGER: setIntValue(fieldName, Casting.toInt(value)); break; 94 case Field.TYPE_BINARY: { 95 long length = getSize(fieldName); 96 setInputStreamValue(fieldName, Casting.toInputStream(value), length); break; 97 } 98 case Field.TYPE_FLOAT: setFloatValue(fieldName, Casting.toFloat(value)); break; 99 case Field.TYPE_DOUBLE: setDoubleValue(fieldName, Casting.toDouble(value)); break; 100 case Field.TYPE_LONG: setLongValue(fieldName, Casting.toLong(value)); break; 101 case Field.TYPE_XML: setXMLValue(fieldName, (Document ) value); break; 102 case Field.TYPE_NODE: setNodeValue(fieldName, Casting.toNode(value, getCloud())); break; 103 case Field.TYPE_DATETIME: setDateValue(fieldName, (Date) value); break; 104 case Field.TYPE_BOOLEAN: setBooleanValue(fieldName, Casting.toBoolean(value)); break; 105 case Field.TYPE_LIST: setListValue(fieldName, (List) value); break; 106 default: setObjectValue(fieldName, value); 107 } 108 } 109 } 110 111 119 public void setValueWithoutProcess(String fieldName, Object value) { 120 edit(ACTION_EDIT); 121 if ("owner".equals(fieldName)) { 122 setContext(Casting.toString(value)); 123 return; 124 } 125 if ("number".equals(fieldName) || "otype".equals(fieldName)) { 126 throw new BridgeException("Not allowed to change field '" + fieldName + "'."); 127 } 128 setValueWithoutChecks(fieldName, value); 129 } 130 131 protected abstract void setValueWithoutChecks(String fieldName, Object value); 132 133 public final void setObjectValue(String fieldName, Object value) { 134 Field field = getNodeManager().getField(fieldName); 135 value = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_UNKNOWN).process(this, field, value); 136 setValueWithoutProcess(fieldName, value); 137 } 138 139 public final void setBooleanValue(String fieldName,final boolean value) { 140 Field field = getNodeManager().getField(fieldName); 141 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_BOOLEAN).process(this, field, Boolean.valueOf(value)); 142 setValueWithoutProcess(fieldName, v); 143 } 144 145 public final void setDateValue(String fieldName, final Date value) { 146 Field field = getNodeManager().getField(fieldName); 147 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_DATETIME).process(this, field, value); 148 setValueWithoutProcess(fieldName, v); 149 } 150 151 public final void setListValue(String fieldName, final List value) { 152 Field field = getNodeManager().getField(fieldName); 153 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_LIST).process(this, field, value); 154 setValueWithoutProcess(fieldName, v); 155 } 156 157 161 protected Integer toNodeNumber(Object v) { 162 if (v == null) { 163 return null; 164 } else if (v instanceof Node) { 165 return new Integer (((Node)v).getNumber()); 166 } else { 167 return new Integer (getCloud().getNode(v.toString()).getNumber()); 169 } 170 } 171 172 public final void setNodeValue(String fieldName, final Node value) { 173 Field field = getNodeManager().getField(fieldName); 174 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_NODE).process(this, field, value); 175 setValueWithoutProcess(fieldName, toNodeNumber(v)); 176 } 177 178 public final void setIntValue(String fieldName, final int value) { 179 Field field = getNodeManager().getField(fieldName); 180 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_INTEGER).process(this, field, new Integer (value)); 181 setValueWithoutProcess(fieldName, v); 182 } 183 184 public final void setLongValue(String fieldName, final long value) { 185 Field field = getNodeManager().getField(fieldName); 186 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_LONG).process(this, field, new Long (value)); 187 setValueWithoutProcess(fieldName, v); 188 } 189 190 public final void setFloatValue(String fieldName, final float value) { 191 Field field = getNodeManager().getField(fieldName); 192 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_FLOAT).process(this, field, new Float (value)); 193 setValueWithoutProcess(fieldName, v); 194 } 195 196 public final void setDoubleValue(String fieldName, final double value) { 197 Field field = getNodeManager().getField(fieldName); 198 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_DOUBLE).process(this, field, new Double (value)); 199 setValueWithoutProcess(fieldName, v); 200 } 201 202 public final void setByteValue(String fieldName, final byte[] value) { 203 Field field = getNodeManager().getField(fieldName); 204 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_BINARY).process(this, field, value); 205 setValueWithoutProcess(fieldName, v); 206 } 207 208 protected abstract void setSize(String fieldName, long size); 209 210 private static final int readLimit = 10 * 1024 * 1024; 211 212 public final void setInputStreamValue(String fieldName, final InputStream value, long size) { 213 setSize(fieldName, size); 214 Field field = getNodeManager().getField(fieldName); 215 if (log.isDebugEnabled()) { 216 log.debug("Setting binary value for " + field); 217 } 218 Object v = value; 219 try { 220 if (value.markSupported() && size < readLimit) { 221 if (log.isDebugEnabled()) { 222 log.debug("Mark supported and using " + field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_BINARY)); 223 } 224 value.mark(readLimit); 225 v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_BINARY).process(this, field, value); 226 value.reset(); 227 } else { 228 if (field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_BINARY) != null) { 229 if (log.isDebugEnabled()) { 230 log.debug("Mark not supported but using " + field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_BINARY)); 231 } 232 ByteArrayOutputStream b = new ByteArrayOutputStream((int) size); 234 int c; 235 while((c = value.read()) > -1) { 236 b.write(c); 237 } 238 byte[] byteArray = b.toByteArray(); 239 v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_BINARY).process(this, field, byteArray); 240 } else { 241 log.debug("Mark not support but no need for processing"); 242 v = value; 243 } 244 } 245 } catch (IOException ioe) { 246 log.error(ioe); 247 } 248 setValueWithoutProcess(fieldName, v); 249 } 250 251 public final void setStringValue(final String fieldName, final String value) { 252 Field field = getNodeManager().getField(fieldName); 253 Object setValue = field.getDataType().preCast(value, this, field); Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_STRING).process(this, field, setValue); 255 setValueWithoutProcess(fieldName, v); 256 } 257 258 public final void setXMLValue(String fieldName, final Document value) { 259 Field field = getNodeManager().getField(fieldName); 260 Object v = field.getDataType().getProcessor(DataType.PROCESS_SET, Field.TYPE_XML).process(this, field, value); 261 setValueWithoutProcess(fieldName, v); 262 } 263 264 public final Object getValue(String fieldName) { 265 Object value = getValueWithoutProcess(fieldName); 266 if (value == null) return null; 267 NodeManager nm = getNodeManager(); 268 if (nm.hasField(fieldName)) { 269 int type = nm.getField(fieldName).getType(); 270 switch(type) { 271 case Field.TYPE_STRING: return getStringValue(fieldName); 272 case Field.TYPE_BINARY: return getByteValue(fieldName); 273 case Field.TYPE_INTEGER: return new Integer (getIntValue(fieldName)); 274 case Field.TYPE_FLOAT: return new Float (getFloatValue(fieldName)); 275 case Field.TYPE_DOUBLE: return new Double (getDoubleValue(fieldName)); 276 case Field.TYPE_LONG: return new Long (getLongValue(fieldName)); 277 case Field.TYPE_XML: return getXMLValue(fieldName); 278 case Field.TYPE_NODE: { 279 if ("number".equals(fieldName)) { 283 return new Long (getLongValue(fieldName)); 284 } else { 285 return getNodeValue(fieldName); 286 } 287 } 288 case Field.TYPE_BOOLEAN: return Boolean.valueOf(getBooleanValue(fieldName)); 289 case Field.TYPE_DATETIME:return getDateValue(fieldName); 290 case Field.TYPE_LIST: return getListValue(fieldName); 291 default: 292 log.error("Unknown fieldtype '" + type + "'"); 293 return value; 294 } 295 } else { 296 return value; 298 } 299 300 } 301 302 public final Object getObjectValue(String fieldName) { 303 Object result = getValueWithoutProcess(fieldName); 304 NodeManager nodeManager = getNodeManager(); 305 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 307 Object r = field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_UNKNOWN).process(this, field, result); 308 if ((result != null && (! result.equals(r)))) { 309 log.info("getObjectvalue was processed! " + result + " != " + r); 310 result = r; 311 } 312 } 313 return result; 314 } 315 316 public boolean getBooleanValue(String fieldName) { 317 Boolean result = Casting.toBoolean(getValueWithoutProcess(fieldName)) ? Boolean.TRUE : Boolean.FALSE; NodeManager nodeManager = getNodeManager(); 319 if (nodeManager.hasField(fieldName)) { Field field = getNodeManager().getField(fieldName); 321 result = (Boolean ) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_BOOLEAN).process(this, field, result); 322 } 323 return result.booleanValue(); 324 } 325 326 public Date getDateValue(String fieldName) { 327 Date result = Casting.toDate(getValueWithoutProcess(fieldName)); 328 NodeManager nodeManager = getNodeManager(); 329 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 331 result = (Date) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_DATETIME).process(this, field, result); 332 } 333 return result; 334 } 335 336 public List getListValue(String fieldName) { 337 List result = Casting.toList(getValueWithoutProcess(fieldName)); 338 NodeManager nodeManager = getNodeManager(); 339 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 341 result = (List) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_LIST).process(this, field, result); 342 } 343 return result; 344 } 345 346 public int getIntValue(String fieldName) { 347 Integer result = Casting.toInteger(getValueWithoutProcess(fieldName)); 348 NodeManager nodeManager = getNodeManager(); 349 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 351 result = (Integer ) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_INTEGER).process(this, field, result); 352 } 353 return result.intValue(); 354 } 355 356 public float getFloatValue(String fieldName) { 357 Float result = new Float (Casting.toFloat(getValueWithoutProcess(fieldName))); 358 NodeManager nodeManager = getNodeManager(); 359 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 361 result = (Float ) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_FLOAT).process(this, field, result); 362 } 363 return result.floatValue(); 364 } 365 366 public long getLongValue(String fieldName) { 367 Long result = new Long (Casting.toLong(getValueWithoutProcess(fieldName))); 368 NodeManager nodeManager = getNodeManager(); 369 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 371 result = (Long ) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_LONG).process(this, field, result); 372 } 373 return result.longValue(); 374 } 375 376 public double getDoubleValue(String fieldName) { 377 Double result = new Double (Casting.toDouble(getValueWithoutProcess(fieldName))); 378 NodeManager nodeManager = getNodeManager(); 379 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 381 result = (Double ) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_DOUBLE).process(this, field, result); 382 } 383 return result.doubleValue(); 384 } 385 386 public byte[] getByteValue(String fieldName) { 387 byte[] result = Casting.toByte(getValueWithoutProcess(fieldName)); 388 NodeManager nodeManager = getNodeManager(); 389 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 391 result = (byte[]) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_BINARY).process(this, field, result); 392 } 393 return result; 394 } 395 396 public java.io.InputStream getInputStreamValue(String fieldName) { 397 java.io.InputStream result = Casting.toInputStream(getValueWithoutProcess(fieldName)); 398 NodeManager nodeManager = getNodeManager(); 399 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 401 result = (java.io.InputStream ) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_BINARY).process(this, field, result); 402 } 403 return result; 404 } 405 406 public String getStringValue(String fieldName) { 407 String result = Casting.toString(getValueWithoutProcess(fieldName)); 408 NodeManager nodeManager = getNodeManager(); 409 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 411 result = (String ) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_STRING).process(this, field, result); 412 } 413 return result; 414 } 415 416 public Document getXMLValue(String fieldName) { 417 Document result = Casting.toXML(getValueWithoutProcess(fieldName)); 418 NodeManager nodeManager = getNodeManager(); 419 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 421 result = (Document ) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_XML).process(this, field, result); 422 } 423 return result; 424 } 425 426 public Node getNodeValue(String fieldName) { 427 Node result = Casting.toNode(getValueWithoutProcess(fieldName), getCloud()); 428 NodeManager nodeManager = getNodeManager(); 429 if (nodeManager.hasField(fieldName)) { Field field = nodeManager.getField(fieldName); 431 result = (Node) field.getDataType().getProcessor(DataType.PROCESS_GET, Field.TYPE_NODE).process(this, field, result); 432 } 433 return result; 434 } 435 436 public final FieldValue getFieldValue(String fieldName) throws NotFoundException { 437 return new BasicFieldValue(this, getNodeManager().getField(fieldName)); 438 } 439 440 public final FieldValue getFieldValue(Field field) { 441 return new BasicFieldValue(this, field); 442 } 443 444 public final Element getXMLValue(String fieldName, Document tree) { 445 Document doc = getXMLValue(fieldName); 446 if (doc == null) { 447 return null; 448 } 449 return (Element )tree.importNode(doc.getDocumentElement(), true); 450 } 451 452 protected final void processCommit() { 453 FieldIterator fi = getNodeManager().getFields().fieldIterator(); 454 while (fi.hasNext()) { 455 Field field = fi.nextField(); 456 field.getDataType().getCommitProcessor().commit(this, field); 457 } 458 } 459 460 public Collection validate() { 461 List errors = new ArrayList(); 462 FieldIterator fi = getNodeManager().getFields().fieldIterator(); 463 Locale locale = getCloud().getLocale(); 464 while (fi.hasNext()) { 465 Field field = fi.nextField(); 466 if (! field.isReadOnly() && !field.isVirtual()) { 467 Object value = getValueWithoutProcess(field.getName()); 471 Collection fieldErrors = field.getDataType().validate(value, this, field); 472 Iterator i = fieldErrors.iterator(); 473 while(i.hasNext()) { 474 LocalizedString error = (LocalizedString) i.next(); 475 errors.add("field '" + field.getName() + "' with value '" + value + "': " + error.get(locale)); 477 } 478 } 479 } 480 return errors; 481 } 482 483 public final void delete() { 484 delete(false); 485 } 486 487 public final void deleteRelations() { 488 deleteRelations("object"); 489 } 490 491 public final RelationList getRelations() { 492 return getRelations(null, (String ) null); 493 } 494 495 public final RelationList getRelations(String role) { 496 return getRelations(role, (String ) null); 497 } 498 499 public final RelationList getRelations(String role, NodeManager nodeManager) { 500 if (nodeManager == null) { 501 return getRelations(role); 502 } else { 503 return getRelations(role, nodeManager.getName()); 504 } 505 } 506 507 public final int countRelations() { 508 return countRelatedNodes(getCloud().getNodeManager("object"), null, "BOTH"); 509 } 510 511 public final int countRelations(String type) { 512 return countRelatedNodes(getCloud().getNodeManager("object"), type, "BOTH"); 514 } 515 516 public final NodeList getRelatedNodes() { 517 return getRelatedNodes("object", null, null); 518 } 519 520 public final NodeList getRelatedNodes(String type) { 521 return getRelatedNodes(type, null, null); 522 } 523 524 public final NodeList getRelatedNodes(NodeManager nodeManager) { 525 return getRelatedNodes(nodeManager, null, null); 526 } 527 528 public final NodeList getRelatedNodes(String type, String role, String searchDir) { 529 return getRelatedNodes(getCloud().getNodeManager(type), role, searchDir); 530 } 531 532 public Relation createRelation(Node destinationNode, RelationManager relationManager) { 533 Relation relation = relationManager.createRelation(this, destinationNode); 534 return relation; 535 } 536 537 550 public final int compareTo(Object o) { 551 Node n = (Node)o; 552 String s1 = ""; 553 if (this instanceof NodeManager) { 554 s1 = ((NodeManager)this).getGUIName(); 555 } else { 556 s1 = getFunctionValue("gui", null).toString(); 557 } 558 String s2 = ""; 559 if (n instanceof NodeManager) { 560 s2 = ((NodeManager)n).getGUIName(); 561 } else { 562 s2 = n.getFunctionValue("gui", null).toString(); 563 } 564 Collator col = Collator.getInstance(getCloud().getLocale()); 565 col.setStrength(Collator.PRIMARY); 566 int res = col.compare(s1, s2); 567 if (res != 0) { 568 return res; 569 } else { 570 res = s1.compareTo(s2); 571 if (res != 0) return res; 572 573 int n1 = getNumber(); 574 int n2 = n.getNumber(); 575 if (n2 > n1) { 576 return -1; 577 } else if (n2 < n1) { 578 return -1; 579 } else { 580 Cloud c = getCloud(); 581 if (c instanceof Comparable ) { 582 return ((Comparable ) c).compareTo(n.getCloud()); 583 } else { 584 return 0; 585 } 586 } 587 } 588 } 589 590 public boolean isNew() { 591 return false; 592 } 593 594 public boolean isChanged(String fieldName) { 595 return false; 596 } 597 598 public boolean isChanged() { 599 return false; 600 } 601 public Set getChanged() { 602 return Collections.EMPTY_SET; 603 } 604 605 public void commit() { 606 throw new UnsupportedOperationException ("Cannot edit virtual node"); 607 } 608 609 public void cancel() { 610 } 611 612 public void delete(boolean deleteRelations) { 613 throw new UnsupportedOperationException ("Cannot edit virtual node"); 614 } 615 616 public void deleteRelations(String type) throws NotFoundException { 617 } 618 619 public RelationList getRelations(String role, NodeManager nodeManager, String searchDir) throws NotFoundException { 620 return BridgeCollections.EMPTY_RELATIONLIST; 621 } 622 public RelationList getRelations(String role, String nodeManager) throws NotFoundException { 623 return BridgeCollections.EMPTY_RELATIONLIST; 624 } 625 626 public boolean hasRelations() { 627 return false; 628 } 629 630 public int countRelatedNodes(NodeManager otherNodeManager, String role, String direction) { 631 return 0; 632 } 633 634 public int countRelatedNodes(String type) { 635 return 0; 636 } 637 638 public NodeList getRelatedNodes(NodeManager nodeManager, String role, String searchDir) { 639 return BridgeCollections.EMPTY_NODELIST; 640 } 641 642 public StringList getAliases() { 643 return BridgeCollections.EMPTY_STRINGLIST; 644 } 645 646 public void createAlias(String aliasName) { 647 throw new UnsupportedOperationException ("Virtual nodes have no aliases"); 648 } 649 650 public void deleteAlias(String aliasName) { 651 throw new UnsupportedOperationException ("Virtual nodes have no aliases"); 652 } 653 654 public void setContext(String context) { 655 throw new UnsupportedOperationException ("Virtual nodes have no security context"); 656 } 657 658 public String getContext() { 660 throw new UnsupportedOperationException ("Virtual nodes have no security context"); 661 } 662 663 public StringList getPossibleContexts() { 665 return BridgeCollections.EMPTY_STRINGLIST; 666 } 667 668 public boolean mayWrite() { 669 return false; 670 } 671 672 public boolean mayDelete() { 673 return false; 674 } 675 676 public boolean mayChangeContext() { 677 return false; 678 } 679 680 687 public final boolean equals(Object o) { 688 return (o instanceof Node) && getNumber() == ((Node)o).getNumber() && getCloud().equals(((Node)o).getCloud()); 689 } 690 691 692 public Parameters createParameters(String functionName) { 693 return getNodeFunction(functionName).createParameters(); 694 } 695 696 protected FieldValue createFunctionValue(final Object result) { 697 return new AbstractFieldValue(this, getCloud()) { 698 public Object get() { 699 return result; 700 } 701 }; 702 } 703 704 public FieldValue getFunctionValue(String functionName, List parameters) { 705 Function function = getFunction(functionName); 706 Parameters params = function.createParameters(); 707 params.setAll(parameters); 708 return createFunctionValue(function.getFunctionValue(params)); 709 } 710 711 protected Function getNodeFunction(String functionName) { 712 return null; 713 } 714 715 public final Function getFunction(String functionName) { 716 Function function = getNodeFunction(functionName); 717 if (function == null) { 718 throw new NotFoundException("Function with name " + functionName + " does not exist on node " + getNumber() + " of type " + getNodeManager().getName() + "(known are " + getFunctions() + ")"); 719 } 720 return new WrappedFunction(function) { 721 public final Object getFunctionValue(Parameters params) { 722 params.setIfDefined(Parameter.NODE, AbstractNode.this); 723 params.setIfDefined(Parameter.CLOUD, AbstractNode.this.getCloud()); 724 return AbstractNode.this.createFunctionValue(super.getFunctionValue(params)).get(); 725 } 726 }; 727 } 728 729 } 730 | Popular Tags |