Changed remove() method to remove node itself if no arguments are supplied.

Added getNodeProperty() method which will only return properties of the node but not the
underlying prototype, thus avoiding to return functions declared for the prototype. This is used
for the HopObjects get() function.

Added getDefaultValue() to return a string representation for HopObjects. Previously, concatenating
HopObjects to Strings threw an error.
This commit is contained in:
hns 2002-05-14 16:40:28 +00:00
parent 1cd27f8c1d
commit 9dcf718733

View file

@ -158,14 +158,20 @@ public class ESNode extends ObjectPrototype {
/** /**
* Remove one or more subnodes. * Remove node itself or one or more subnodes.
*/ */
public boolean remove (ESValue args[]) { public boolean remove (ESValue args[]) {
checkNode (); checkNode ();
for (int i=0; i<args.length; i++) { // semantics: if called without arguments, remove self.
if (args[i] instanceof ESNode) { // otherwise, remove given subnodes.
ESNode esn = (ESNode) args[i]; if (args.length == 0) {
node.removeNode (esn.getNode ()); return node.remove ();
} else {
for (int i=0; i<args.length; i++) {
if (args[i] instanceof ESNode) {
ESNode esn = (ESNode) args[i];
node.removeNode (esn.getNode ());
}
} }
} }
return true; return true;
@ -292,12 +298,29 @@ public class ESNode extends ObjectPrototype {
} }
/**
* Retrieve a property from the node object or the underlying EcmaScript prototype.
* Normally we would first check the node object and then the prototype, but since
* node properties are potentially expensive to look up because they require database
* queries, we do the prototype lookup first. This usually doesn't cause any confusion
* because generally things are divided cleanly between prototype and object - the
* first holds the functions, the latter the mapped data properties.
*/
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException { public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
checkNode (); checkNode ();
// eval.app.logEvent ("get property called: "+propertyName); // eval.app.logEvent ("get property called: "+propertyName);
ESValue retval = super.getProperty (propertyName, hash); ESValue retval = super.getProperty (propertyName, hash);
if (! (retval instanceof ESUndefined)) if (! (retval instanceof ESUndefined))
return retval; return retval;
return getNodeProperty (propertyName);
}
/**
* Retrieve a property only from the node itself, not the underlying EcmaScript prototype object.
* This is called directly when we call get(x) on a hopobject, since we don't want to return
* the prototype functions in that case.
*/
public ESValue getNodeProperty (String propertyName) throws EcmaScriptException {
// persistent or persistent capable nodes have a cache property that's a transient node. // persistent or persistent capable nodes have a cache property that's a transient node.
// it it hasn't requested before, initialize it now // it it hasn't requested before, initialize it now
@ -313,7 +336,7 @@ public class ESNode extends ObjectPrototype {
String rel = node.getSubnodeRelation (); String rel = node.getSubnodeRelation ();
return rel == null ? (ESValue) ESNull.theNull : new ESString (rel); return rel == null ? (ESValue) ESNull.theNull : new ESString (rel);
} }
if ("_id".equals (propertyName)) if ("_id".equals (propertyName))
return new ESString (node.getID ()); return new ESString (node.getID ());
if ("_parent".equals (propertyName)) { if ("_parent".equals (propertyName)) {
@ -323,7 +346,7 @@ public class ESNode extends ObjectPrototype {
else else
return ESNull.theNull; return ESNull.theNull;
} }
// this is not very nice, but as a hack we return the id of a node as node.__id__ // this is not very nice, but as a hack we return the id of a node as node.__id__
if (propertyName.startsWith ("__") && propertyName.endsWith ("__")) if (propertyName.startsWith ("__") && propertyName.endsWith ("__"))
return getInternalProperty (propertyName); return getInternalProperty (propertyName);
@ -340,7 +363,7 @@ public class ESNode extends ObjectPrototype {
} }
if (p.getType () == IProperty.BOOLEAN) if (p.getType () == IProperty.BOOLEAN)
return ESBoolean.makeBoolean (p.getBooleanValue ()); return ESBoolean.makeBoolean (p.getBooleanValue ());
if (p.getType () == IProperty.DATE) if (p.getType () == IProperty.DATE)
return new DatePrototype (evaluator, p.getDateValue ()); return new DatePrototype (evaluator, p.getDateValue ());
if (p.getType () == IProperty.INTEGER) if (p.getType () == IProperty.INTEGER)
return new ESNumber ((double) p.getIntegerValue ()); return new ESNumber ((double) p.getIntegerValue ());
@ -356,12 +379,6 @@ public class ESNode extends ObjectPrototype {
if (p.getType () == IProperty.JAVAOBJECT) if (p.getType () == IProperty.JAVAOBJECT)
return ESLoader.normalizeObject (p.getJavaObjectValue (), evaluator); return ESLoader.normalizeObject (p.getJavaObjectValue (), evaluator);
} }
// these are predefined
// if ("created".equalsIgnoreCase (propertyName))
// return new DatePrototype (evaluator, node.created ());
// if ("lastmodified".equalsIgnoreCase (propertyName))
// return new DatePrototype (evaluator, node.lastModified ());
// as last resort, try to get property as anonymous subnode // as last resort, try to get property as anonymous subnode
INode anon = node.getSubnode (propertyName); INode anon = node.getSubnode (propertyName);
@ -371,6 +388,10 @@ public class ESNode extends ObjectPrototype {
return ESNull.theNull; return ESNull.theNull;
} }
/**
* Some internal properties defined for every Node object. These are most commonly
* used for debugging Helma applications.
*/
private ESValue getInternalProperty (String propertyName) throws EcmaScriptException { private ESValue getInternalProperty (String propertyName) throws EcmaScriptException {
if ("__id__".equalsIgnoreCase (propertyName)) { if ("__id__".equalsIgnoreCase (propertyName)) {
return new ESString (node.getID ()); return new ESString (node.getID ());
@ -441,8 +462,8 @@ public class ESNode extends ObjectPrototype {
return getNode (); return getNode ();
} }
/** /**
* An ESNode equals another object if it is an ESNode that wraps the same INode * An ESNode equals another object if it is an ESNode that wraps the same INode
* or the wrapped INode itself. FIXME: doesen't check dbmapping/type! * or the wrapped INode itself. FIXME: doesen't check dbmapping/type!
*/ */
public boolean equals (Object what) { public boolean equals (Object what) {
@ -458,59 +479,13 @@ public class ESNode extends ObjectPrototype {
return (node == other.node); return (node == other.node);
} }
return false; return false;
} }
public ESValue getDefaultValue(int hint) throws EcmaScriptException {
return new ESString (this.toString());
}
} // class ESNode } // class ESNode