DbMapping: Changed most fields visibility to private

DbMapping:   Change getPropertyRelation visibility to private, always use
             getSubnodeRelation from outside instead.
Node:        Rewrote getProperty(String) to be simpler and easier to understand.
             furthermore, getProperty(String) now also returns child objects (subnodes)
             making it unnecessary for calling code to also use getChildElement()
             or getSubnode()
Node:        Fixed NullPointerException in getElementName() for transient nodes
Node:        Use DbMapping.getSubnodeRelation() instead of DbMapping.getPropertyRelation()
NodeManager: Fixes in getNode() methods, which now invoke each other depending on
             key/query type
Relation:    Removed unused arguments from constructor
Relation:    Fixed NullPointerException in createOnDemand()
HopObject:   Do not use getChildElement() in jsFunction_get() (see change in
             Node.getProperty())
HopObject:   Handle case where jsFunction_get() and jsFunction_set() are called with
             non-strings that should be handled as string, e.g.
             org.mozilla.javascript.NativeString

cosmetic cleanup everywhere (imports, unneeded casts, unused fields etc.)
This commit is contained in:
hns 2003-10-23 12:00:35 +00:00
parent ccf197aeac
commit c0830be336
5 changed files with 168 additions and 173 deletions

View file

@ -20,13 +20,9 @@ import helma.framework.core.Application;
import helma.framework.core.Prototype; import helma.framework.core.Prototype;
import helma.util.SystemProperties; import helma.util.SystemProperties;
import helma.util.Updatable; import helma.util.Updatable;
import java.sql.*; import java.sql.*;
import java.util.Enumeration; import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
/** /**
* A DbMapping describes how a certain type of Nodes is to mapped to a * A DbMapping describes how a certain type of Nodes is to mapped to a
@ -35,76 +31,76 @@ import java.util.StringTokenizer;
*/ */
public final class DbMapping implements Updatable { public final class DbMapping implements Updatable {
// DbMappings belong to an application // DbMappings belong to an application
Application app; protected Application app;
// prototype name of this mapping // prototype name of this mapping
private String typename; private String typename;
// properties from where the mapping is read // properties from where the mapping is read
SystemProperties props; private SystemProperties props;
// name of data dbSource to which this mapping writes // name of data dbSource to which this mapping writes
DbSource dbSource; private DbSource dbSource;
// name of datasource // name of datasource
String dbSourceName; private String dbSourceName;
// name of db table // name of db table
String tableName; private String tableName;
// list of properties to try for parent // list of properties to try for parent
ParentInfo[] parentInfo; private ParentInfo[] parentInfo;
// Relations describing subnodes and properties. // Relations describing subnodes and properties.
Relation subRelation; protected Relation subRelation;
Relation propRelation; protected Relation propRelation;
// if this defines a subnode mapping with groupby layer, // if this defines a subnode mapping with groupby layer,
// we need a DbMapping for those groupby nodes // we need a DbMapping for those groupby nodes
DbMapping groupbyMapping; private DbMapping groupbyMapping;
// Map of property names to Relations objects // Map of property names to Relations objects
HashMap prop2db; private HashMap prop2db;
// Map of db columns to Relations objects. // Map of db columns to Relations objects.
// Case insensitive, keys are stored in upper case so // Case insensitive, keys are stored in upper case so
// lookups must do a toUpperCase(). // lookups must do a toUpperCase().
HashMap db2prop; private HashMap db2prop;
// list of columns to fetch from db // list of columns to fetch from db
DbColumn[] columns = null; private DbColumn[] columns = null;
// Map of db columns by name // Map of db columns by name
HashMap columnMap; private HashMap columnMap;
// Array of aggressively loaded references // Array of aggressively loaded references
Relation[] joins; private Relation[] joins;
// pre-rendered select statement // pre-rendered select statement
String selectString = null; private String selectString = null;
String insertString = null; private String insertString = null;
String updateString = null; private String updateString = null;
// db field used as primary key // db field used as primary key
private String idField; private String idField;
// db field used as object name // db field used as object name
String nameField; private String nameField;
// db field used to identify name of prototype to use for object instantiation // db field used to identify name of prototype to use for object instantiation
String protoField; private String protoField;
// name of parent prototype, if any // name of parent prototype, if any
String extendsProto; private String extendsProto;
// dbmapping of parent prototype, if any // dbmapping of parent prototype, if any
DbMapping parentMapping; private DbMapping parentMapping;
// descriptor for key generation method // descriptor for key generation method
private String idgen; private String idgen;
// remember last key generated for this table // remember last key generated for this table
long lastID; private long lastID;
// timestamp of last modification of the mapping (type.properties) // timestamp of last modification of the mapping (type.properties)
// init value is -1 so we know we have to run update once even if // init value is -1 so we know we have to run update once even if
@ -262,7 +258,7 @@ public final class DbMapping implements Updatable {
Relation rel = (Relation) prop2db.get(propName.toLowerCase()); Relation rel = (Relation) prop2db.get(propName.toLowerCase());
if (rel == null) { if (rel == null) {
rel = new Relation(dbField, propName, this, props); rel = new Relation(propName, this);
} }
rel.update(dbField, props); rel.update(dbField, props);
@ -312,7 +308,7 @@ public final class DbMapping implements Updatable {
try { try {
// check if subnode relation already exists. If so, reuse it // check if subnode relation already exists. If so, reuse it
if (subRelation == null) { if (subRelation == null) {
subRelation = new Relation(subnodeMapping, "_children", this, props); subRelation = new Relation("_children", this);
} }
subRelation.update(subnodeMapping, props); subRelation.update(subnodeMapping, props);
@ -695,7 +691,7 @@ public final class DbMapping implements Updatable {
* *
* @return ... * @return ...
*/ */
public Relation getPropertyRelation() { private Relation getPropertyRelation() {
if ((propRelation == null) && (parentMapping != null)) { if ((propRelation == null) && (parentMapping != null)) {
return parentMapping.getPropertyRelation(); return parentMapping.getPropertyRelation();
} }

View file

@ -17,18 +17,17 @@
package helma.objectmodel.db; package helma.objectmodel.db;
import helma.framework.IPathElement; import helma.framework.IPathElement;
import helma.objectmodel.*; import helma.objectmodel.ConcurrencyException;
import helma.util.*; import helma.objectmodel.INode;
import java.io.*; import helma.objectmodel.IProperty;
import java.math.BigDecimal; import helma.objectmodel.TransientNode;
import java.sql.*; import helma.util.EmptyEnumeration;
import java.util.Date;
import java.util.Enumeration; import java.io.IOException;
import java.util.Hashtable; import java.io.ObjectInputStream;
import java.util.Iterator; import java.io.ObjectOutputStream;
import java.util.List; import java.io.Serializable;
import java.util.StringTokenizer; import java.util.*;
import java.util.Vector;
/** /**
* An implementation of INode that can be stored in the internal database or * An implementation of INode that can be stored in the internal database or
@ -182,8 +181,6 @@ public final class Node implements INode, Serializable {
// version indicates the serialization version // version indicates the serialization version
version = in.readShort(); version = in.readShort();
String rawParentID = null;
if (version < 9) { if (version < 9) {
throw new IOException("Can't read pre 1.3.0 HopObject"); throw new IOException("Can't read pre 1.3.0 HopObject");
} }
@ -418,12 +415,17 @@ public final class Node implements INode, Serializable {
public String getElementName() { public String getElementName() {
// if subnodes are also mounted as properties, try to get the "nice" prop value // if subnodes are also mounted as properties, try to get the "nice" prop value
// instead of the id by turning the anonymous flag off. // instead of the id by turning the anonymous flag off.
long lastmod = Math.max(dbmap.getLastTypeChange(), lastmodified); long lastmod = lastmodified;
if (dbmap != null) {
lastmod = Math.max(lastmod, dbmap.getLastTypeChange());
}
if ((parentHandle != null) && (lastNameCheck < lastmod)) { if ((parentHandle != null) && (lastNameCheck < lastmod)) {
try { try {
Node p = parentHandle.getNode(nmgr); Node p = parentHandle.getNode(nmgr);
DbMapping parentmap = p.getDbMapping(); DbMapping parentmap = p.getDbMapping();
Relation prel = parentmap.getPropertyRelation(); Relation prel = parentmap.getSubnodeRelation();
if ((prel != null) && prel.hasAccessName()) { if ((prel != null) && prel.hasAccessName()) {
String propname = dbmap.columnNameToProperty(prel.accessName); String propname = dbmap.columnNameToProperty(prel.accessName);
@ -672,7 +674,7 @@ public final class Node implements INode, Serializable {
if (parentmap != null) { if (parentmap != null) {
// first try to retrieve name via generic property relation of parent // first try to retrieve name via generic property relation of parent
Relation prel = parentmap.getPropertyRelation(); Relation prel = parentmap.getSubnodeRelation();
if ((prel != null) && (prel.otherType == dbmap) && if ((prel != null) && (prel.otherType == dbmap) &&
(prel.accessName != null)) { (prel.accessName != null)) {
@ -880,7 +882,7 @@ public final class Node implements INode, Serializable {
// check if properties are subnodes (_properties.aresubnodes=true) // check if properties are subnodes (_properties.aresubnodes=true)
if ((dbmap != null) && (node.dbmap != null)) { if ((dbmap != null) && (node.dbmap != null)) {
Relation prel = dbmap.getPropertyRelation(); Relation prel = dbmap.getSubnodeRelation();
if ((prel != null) && (prel.accessName != null)) { if ((prel != null) && (prel.accessName != null)) {
Relation localrel = node.dbmap.columnNameToRelation(prel.accessName); Relation localrel = node.dbmap.columnNameToRelation(prel.accessName);
@ -1027,26 +1029,26 @@ public final class Node implements INode, Serializable {
Relation rel = dbmap.getExactPropertyRelation(name); Relation rel = dbmap.getExactPropertyRelation(name);
if (rel != null) { if (rel != null) {
return (IPathElement) getNode(name); return getNode(name);
} }
rel = dbmap.getSubnodeRelation(); rel = dbmap.getSubnodeRelation();
if ((rel != null) && (rel.groupby == null) && (rel.accessName != null)) { if ((rel != null) && (rel.groupby == null) && (rel.accessName != null)) {
if ((rel.otherType != null) && rel.otherType.isRelational()) { if ((rel.otherType != null) && rel.otherType.isRelational()) {
return (IPathElement) nmgr.getNode(this, name, rel); return nmgr.getNode(this, name, rel);
} else { } else {
return (IPathElement) getNode(name); return getNode(name);
} }
} }
return (IPathElement) getSubnode(name); return getSubnode(name);
} else { } else {
// no dbmapping - just try child collection first, then named property. // no dbmapping - just try child collection first, then named property.
IPathElement child = (IPathElement) getSubnode(name); IPathElement child = getSubnode(name);
if (child == null) { if (child == null) {
child = (IPathElement) getNode(name); child = getNode(name);
} }
return child; return child;
@ -1266,7 +1268,7 @@ public final class Node implements INode, Serializable {
// check if subnodes are also accessed as properties. If so, also unset the property // check if subnodes are also accessed as properties. If so, also unset the property
if ((dbmap != null) && (node.dbmap != null)) { if ((dbmap != null) && (node.dbmap != null)) {
Relation prel = dbmap.getPropertyRelation(); Relation prel = dbmap.getSubnodeRelation();
if ((prel != null) && (prel.accessName != null)) { if ((prel != null) && (prel.accessName != null)) {
Relation localrel = node.dbmap.columnNameToRelation(prel.accessName); Relation localrel = node.dbmap.columnNameToRelation(prel.accessName);
@ -1552,7 +1554,7 @@ public final class Node implements INode, Serializable {
return dbmap.getPropertyEnumeration(); return dbmap.getPropertyEnumeration();
} }
Relation prel = (dbmap == null) ? null : dbmap.getPropertyRelation(); Relation prel = (dbmap == null) ? null : dbmap.getSubnodeRelation();
if ((prel != null) && prel.hasAccessName() && (prel.otherType != null) && if ((prel != null) && prel.hasAccessName() && (prel.otherType != null) &&
prel.otherType.isRelational()) { prel.otherType.isRelational()) {
@ -1600,89 +1602,97 @@ public final class Node implements INode, Serializable {
getParent(); getParent();
} }
/**
*
*
* @param propname ...
*
* @return ...
*/
protected Property getProperty(String propname) { protected Property getProperty(String propname) {
// nmgr.logEvent ("GETTING PROPERTY: "+propname);
if (propname == null) { if (propname == null) {
return null; return null;
} }
Relation rel = dbmap == null ?
null :
dbmap.getExactPropertyRelation(propname);
// 1) check if this is a create-on-demand node property
if (rel != null && (rel.isCollection() || rel.isComplexReference())) {
if (state == TRANSIENT && rel.isCollection()) {
// When we get a collection from a transient node for the first time, or when
// we get a collection whose content objects are stored in the embedded
// XML data storage, we just want to create and set a generic node without
// consulting the NodeManager about it.
Node n = new Node(propname, rel.getPrototype(), nmgr);
n.setDbMapping(rel.getVirtualMapping());
n.setParent(this);
setNode(propname, n);
return (Property) propMap.get(propname.toLowerCase());
} else if (state != TRANSIENT) {
Node n = nmgr.getNode(this, propname, rel);
Property prop = (propMap == null) ? null if (n != null) {
: (Property) propMap.get(propname.toLowerCase()); if ((n.parentHandle == null) &&
!"root".equalsIgnoreCase(n.getPrototype())) {
// See if this could be a relationally linked node which still doesn't know n.setParent(this);
// (i.e, still thinks it's just the key as a string) n.name = propname;
DbMapping pmap = (dbmap == null) ? null : dbmap.getExactPropertyMapping(propname); n.anonymous = false;
if ((pmap != null) && (prop != null) && (prop.getType() != IProperty.NODE)) {
// this is a relational node stored by id but we still think it's just a string.
// Fix it.
prop.convertToNodeReference(pmap);
}
// the property does not exist in our propmap - see if we should create it on the fly,
// either because it is mapped to an object from relational database or defined as
// collection aka virtual node
if (dbmap != null) {
// the explicitly defined property mapping
Relation propRel = dbmap.getPropertyRelation(propname);
// property was not found in propmap
if (prop == null) {
// if no property relation is defined for this specific property name,
// use the generic property relation, if one is defined.
if (propRel == null) {
propRel = dbmap.getPropertyRelation();
}
// so if we have a property relation and it does in fact link to another object...
if ((propRel != null) && (propRel.isCollection() ||
propRel.isComplexReference())) {
// in some cases we just want to create and set a generic node without
// consulting the NodeManager if it exists: When we get a collection
// (aka virtual node) from a transient node for the first time, or when
// we get a collection whose content objects are stored in the embedded
// XML data storage.
if ((state == TRANSIENT) && propRel.virtual) {
Node pn = new Node(propname, propRel.getPrototype(), nmgr);
pn.setDbMapping(propRel.getVirtualMapping());
pn.setParent(this);
setNode(propname, pn);
prop = (Property) propMap.get(propname);
} }
// if this is from relational database only fetch if this node return new Property(propname, this, n);
// is itself persistent.
else if ((state != TRANSIENT) && propRel.createOnDemand()) {
// this may be a relational node stored by property name
Node pn = nmgr.getNode(this, propname, propRel);
if (pn != null) {
if ((pn.parentHandle == null) &&
!"root".equalsIgnoreCase(pn.getPrototype())) {
pn.setParent(this);
pn.name = propname;
pn.anonymous = false;
}
prop = new Property(propname, this, pn);
}
}
}
} else if (propRel != null && propRel.isVirtual()) {
// prop was found and explicit property relation is collection -
// this is a collection node containing objects stored in the embedded db
Node pn = (Node) prop.getNodeValue();
if (pn != null) {
// do set DbMapping for embedded db collection nodes
pn.setDbMapping(propRel.getVirtualMapping());
// also set node manager in case this is a mountpoint node
// that came in through replication
pn.nmgr = nmgr;
} }
} }
} }
return prop; // 2) check if the property is contained in the propMap
Property prop = propMap == null ? null :
(Property) propMap.get(propname.toLowerCase());
if (prop != null) {
if (rel != null) {
// Is a relational node stored by id but things it's a string or int. Fix it.
if (rel.otherType != null && prop.getType() != Property.NODE) {
prop.convertToNodeReference(rel.otherType);
}
if (rel.isCollection()) {
// property was found in propMap and is a collection - this is
// a collection holding non-relational objects. set DbMapping and
// NodeManager
Node n = (Node) prop.getNodeValue();
if (n != null) {
// do set DbMapping for embedded db collection nodes
n.setDbMapping(rel.getVirtualMapping());
// also set node manager in case this is a mountpoint node
// that came in through replication
n.nmgr = nmgr;
}
}
}
return prop;
}
// 3) try to get the property from the database via accessname, if defined
if (rel == null && dbmap != null && state != TRANSIENT) {
rel = dbmap.getSubnodeRelation();
if (rel != null && rel.otherType != null) {
Node n = nmgr.getNode(this, propname, rel);
if (n != null) {
if ((n.parentHandle == null) &&
!"root".equalsIgnoreCase(n.getPrototype())) {
n.setParent(this);
n.name = propname;
n.anonymous = false;
}
return new Property(propname, this, n);
}
}
}
// 4) nothing to be found - return null
return null;
} }
/** /**
@ -1896,7 +1906,7 @@ public final class Node implements INode, Serializable {
// check if this node is already registered with the old name; if so, remove it. // check if this node is already registered with the old name; if so, remove it.
// then set parent's property to this node for the new name value // then set parent's property to this node for the new name value
DbMapping parentmap = parent.getDbMapping(); DbMapping parentmap = parent.getDbMapping();
Relation propRel = parentmap.getPropertyRelation(); Relation propRel = parentmap.getSubnodeRelation();
String dbcolumn = dbmap.propertyToColumnName(propname); String dbcolumn = dbmap.propertyToColumnName(propname);
if ((propRel != null) && (propRel.accessName != null) && if ((propRel != null) && (propRel.accessName != null) &&

View file

@ -19,8 +19,11 @@ package helma.objectmodel.db;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.util.CacheMap; import helma.util.CacheMap;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.io.*;
import java.sql.*; import java.sql.*;
import java.util.*; import java.util.*;
@ -215,24 +218,21 @@ public final class NodeManager {
if ((node == null) || (node.getState() == Node.INVALID)) { if ((node == null) || (node.getState() == Node.INVALID)) {
// The requested node isn't in the shared cache. // The requested node isn't in the shared cache.
// Synchronize with key to make sure only one version is
// fetched from the database.
if (key instanceof SyntheticKey) { if (key instanceof SyntheticKey) {
Node parent = getNode(key.getParentKey()); Node parent = getNode(key.getParentKey());
Relation rel = parent.dbmap.getPropertyRelation(key.getID()); Relation rel = parent.dbmap.getPropertyRelation(key.getID());
if ((rel == null) || (rel.groupby != null)) { if (rel != null) {
node = parent.getGroupbySubnode(key.getID(), true); return getNode(parent, key.getID(), rel);
} else if (rel != null) {
node = getNode(parent, key.getID(), rel);
} else { } else {
node = null; node = null;
} }
} else { } else if (key instanceof DbKey) {
node = getNodeByKey(tx.txn, (DbKey) key); node = getNodeByKey(tx.txn, (DbKey) key);
} }
if (node != null) { if (node != null) {
// synchronize with cache
synchronized (cache) { synchronized (cache) {
Node oldnode = (Node) cache.put(node.getKey(), node); Node oldnode = (Node) cache.put(node.getKey(), node);
@ -241,8 +241,8 @@ public final class NodeManager {
cache.put(node.getKey(), oldnode); cache.put(node.getKey(), oldnode);
node = oldnode; node = oldnode;
} }
} }
// synchronized // end of cache-synchronized section
} }
} }
@ -279,10 +279,9 @@ public final class NodeManager {
// generated on the fly // generated on the fly
key = new SyntheticKey(home.getKey(), kstr); key = new SyntheticKey(home.getKey(), kstr);
} else { } else {
// if a key for a node from within the DB // refers to a node through its primary database key
// FIXME: This should never apply, since for every relation-based loading
// Synthetic Keys are used. Right?
key = new DbKey(rel.otherType, kstr); key = new DbKey(rel.otherType, kstr);
return getNode(key);
} }
// See if Transactor has already come across this node // See if Transactor has already come across this node

View file

@ -17,12 +17,13 @@
package helma.objectmodel.db; package helma.objectmodel.db;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.objectmodel.*; import helma.objectmodel.INode;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Vector; import java.util.Vector;
import java.util.Map;
import java.util.HashMap;
/** /**
* This describes how a property of a persistent Object is stored in a * This describes how a property of a persistent Object is stored in a
@ -119,7 +120,7 @@ public final class Relation {
/** /**
* Reads a relation entry from a line in a properties file. * Reads a relation entry from a line in a properties file.
*/ */
public Relation(String desc, String propName, DbMapping ownType, Properties props) { public Relation(String propName, DbMapping ownType) {
this.ownType = ownType; this.ownType = ownType;
this.propName = propName; this.propName = propName;
otherType = null; otherType = null;
@ -423,6 +424,10 @@ public final class Relation {
* - complex reference nodes * - complex reference nodes
*/ */
public boolean createOnDemand() { public boolean createOnDemand() {
if (otherType == null) {
return false;
}
return virtual || return virtual ||
(otherType.isRelational() && accessName != null) || (otherType.isRelational() && accessName != null) ||
(groupby != null) || isComplexReference(); (groupby != null) || isComplexReference();

View file

@ -17,7 +17,6 @@
package helma.scripting.rhino; package helma.scripting.rhino;
import helma.scripting.ScriptingException; import helma.scripting.ScriptingException;
import helma.framework.*;
import helma.framework.core.*; import helma.framework.core.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.*; import helma.objectmodel.db.*;
@ -28,7 +27,6 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
@ -192,8 +190,8 @@ public class HopObject extends ScriptableObject implements Wrapper {
/** /**
* Render a skin to the response buffer. * Render a skin to the response buffer.
* *
* @param skin The skin object or name * @param skinobj The skin object or name
* @param param An optional parameter object * @param paramobj An optional parameter object
* *
* @return ... * @return ...
*/ */
@ -221,8 +219,8 @@ public class HopObject extends ScriptableObject implements Wrapper {
/** /**
* Render a skin and return its output as string. * Render a skin and return its output as string.
* *
* @param skin The skin object or name * @param skinobj The skin object or name
* @param param An optional parameter object * @param paramobj An optional parameter object
* *
* @return ... * @return ...
*/ */
@ -295,19 +293,8 @@ public class HopObject extends ScriptableObject implements Wrapper {
if (id instanceof Number) { if (id instanceof Number) {
n = get(((Number) id).intValue(), this); n = get(((Number) id).intValue(), this);
} else if (id instanceof String) { } else if (id != null) {
// HopObject.get() is more often called for child elements than for
// ordinary properties, so try a getChildElement() first. This seems
// to have quite an impact on get() performance.
n = node.getChildElement(id.toString());
if (n != null) {
return Context.toObject(n, core.global);
}
n = getFromNode(id.toString()); n = getFromNode(id.toString());
} else {
throw new RuntimeException("Invalid type for id argument in HopObject.get(): "+id);
} }
// since we're calling Scriptable.get() methods, we'll get NOT_FOUND rather // since we're calling Scriptable.get() methods, we'll get NOT_FOUND rather
@ -350,7 +337,7 @@ public class HopObject extends ScriptableObject implements Wrapper {
*/ */
public boolean jsFunction_set(Object id, Object value) { public boolean jsFunction_set(Object id, Object value) {
if (id == Undefined.instance || value == Undefined.instance) { if (id == Undefined.instance || value == Undefined.instance) {
throw new RuntimeException("HopObject.set() called with wrong number of arguments"); throw new EvaluatorException("HopObject.set() called with wrong number of arguments");
} }
if ((node == null)) { if ((node == null)) {
return false; return false;
@ -361,7 +348,7 @@ public class HopObject extends ScriptableObject implements Wrapper {
if (id instanceof Number) { if (id instanceof Number) {
if (!(value instanceof HopObject)) { if (!(value instanceof HopObject)) {
throw new RuntimeException("Can only set HopObjects as child objects in HopObject.set()"); throw new EvaluatorException("Can only set HopObjects as child objects in HopObject.set()");
} }
int idx = (((Number) id).intValue()); int idx = (((Number) id).intValue());
@ -369,10 +356,8 @@ public class HopObject extends ScriptableObject implements Wrapper {
node.addNode(n, idx); node.addNode(n, idx);
} else if (id instanceof String) { } else if (id != null) {
put(id.toString(), this, value); put(id.toString(), this, value);
} else {
throw new RuntimeException("Invalid type for id argument in HopObject.set(): "+id);
} }
return true; return true;
@ -844,7 +829,7 @@ public class HopObject extends ScriptableObject implements Wrapper {
/** /**
* *
* *
* @param name ... * @param idx ...
* @param start ... * @param start ...
* *
* @return ... * @return ...
@ -862,7 +847,7 @@ public class HopObject extends ScriptableObject implements Wrapper {
/** /**
* *
* *
* @param name ... * @param idx ...
* @param start ... * @param start ...
* *
* @return ... * @return ...