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

View file

@ -17,18 +17,17 @@
package helma.objectmodel.db;
import helma.framework.IPathElement;
import helma.objectmodel.*;
import helma.util.*;
import java.io.*;
import java.math.BigDecimal;
import java.sql.*;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import helma.objectmodel.ConcurrencyException;
import helma.objectmodel.INode;
import helma.objectmodel.IProperty;
import helma.objectmodel.TransientNode;
import helma.util.EmptyEnumeration;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.*;
/**
* 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 = in.readShort();
String rawParentID = null;
if (version < 9) {
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() {
// if subnodes are also mounted as properties, try to get the "nice" prop value
// 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)) {
try {
Node p = parentHandle.getNode(nmgr);
DbMapping parentmap = p.getDbMapping();
Relation prel = parentmap.getPropertyRelation();
Relation prel = parentmap.getSubnodeRelation();
if ((prel != null) && prel.hasAccessName()) {
String propname = dbmap.columnNameToProperty(prel.accessName);
@ -672,7 +674,7 @@ public final class Node implements INode, Serializable {
if (parentmap != null) {
// 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) &&
(prel.accessName != null)) {
@ -880,7 +882,7 @@ public final class Node implements INode, Serializable {
// check if properties are subnodes (_properties.aresubnodes=true)
if ((dbmap != null) && (node.dbmap != null)) {
Relation prel = dbmap.getPropertyRelation();
Relation prel = dbmap.getSubnodeRelation();
if ((prel != null) && (prel.accessName != null)) {
Relation localrel = node.dbmap.columnNameToRelation(prel.accessName);
@ -1027,26 +1029,26 @@ public final class Node implements INode, Serializable {
Relation rel = dbmap.getExactPropertyRelation(name);
if (rel != null) {
return (IPathElement) getNode(name);
return getNode(name);
}
rel = dbmap.getSubnodeRelation();
if ((rel != null) && (rel.groupby == null) && (rel.accessName != null)) {
if ((rel.otherType != null) && rel.otherType.isRelational()) {
return (IPathElement) nmgr.getNode(this, name, rel);
return nmgr.getNode(this, name, rel);
} else {
return (IPathElement) getNode(name);
return getNode(name);
}
}
return (IPathElement) getSubnode(name);
return getSubnode(name);
} else {
// no dbmapping - just try child collection first, then named property.
IPathElement child = (IPathElement) getSubnode(name);
IPathElement child = getSubnode(name);
if (child == null) {
child = (IPathElement) getNode(name);
child = getNode(name);
}
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
if ((dbmap != null) && (node.dbmap != null)) {
Relation prel = dbmap.getPropertyRelation();
Relation prel = dbmap.getSubnodeRelation();
if ((prel != null) && (prel.accessName != null)) {
Relation localrel = node.dbmap.columnNameToRelation(prel.accessName);
@ -1552,7 +1554,7 @@ public final class Node implements INode, Serializable {
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) &&
prel.otherType.isRelational()) {
@ -1600,89 +1602,97 @@ public final class Node implements INode, Serializable {
getParent();
}
/**
*
*
* @param propname ...
*
* @return ...
*/
protected Property getProperty(String propname) {
// nmgr.logEvent ("GETTING PROPERTY: "+propname);
if (propname == 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
: (Property) propMap.get(propname.toLowerCase());
// See if this could be a relationally linked node which still doesn't know
// (i.e, still thinks it's just the key as a string)
DbMapping pmap = (dbmap == null) ? null : dbmap.getExactPropertyMapping(propname);
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 (n != null) {
if ((n.parentHandle == null) &&
!"root".equalsIgnoreCase(n.getPrototype())) {
n.setParent(this);
n.name = propname;
n.anonymous = false;
}
// if this is from relational database only fetch if this node
// 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 new Property(propname, this, n);
}
}
}
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.
// then set parent's property to this node for the new name value
DbMapping parentmap = parent.getDbMapping();
Relation propRel = parentmap.getPropertyRelation();
Relation propRel = parentmap.getSubnodeRelation();
String dbcolumn = dbmap.propertyToColumnName(propname);
if ((propRel != null) && (propRel.accessName != null) &&

View file

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

View file

@ -17,12 +17,13 @@
package helma.objectmodel.db;
import helma.framework.core.Application;
import helma.objectmodel.*;
import helma.objectmodel.INode;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
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
@ -119,7 +120,7 @@ public final class Relation {
/**
* 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.propName = propName;
otherType = null;
@ -423,6 +424,10 @@ public final class Relation {
* - complex reference nodes
*/
public boolean createOnDemand() {
if (otherType == null) {
return false;
}
return virtual ||
(otherType.isRelational() && accessName != null) ||
(groupby != null) || isComplexReference();

View file

@ -17,7 +17,6 @@
package helma.scripting.rhino;
import helma.scripting.ScriptingException;
import helma.framework.*;
import helma.framework.core.*;
import helma.objectmodel.*;
import helma.objectmodel.db.*;
@ -28,7 +27,6 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
@ -192,8 +190,8 @@ public class HopObject extends ScriptableObject implements Wrapper {
/**
* Render a skin to the response buffer.
*
* @param skin The skin object or name
* @param param An optional parameter object
* @param skinobj The skin object or name
* @param paramobj An optional parameter object
*
* @return ...
*/
@ -221,8 +219,8 @@ public class HopObject extends ScriptableObject implements Wrapper {
/**
* Render a skin and return its output as string.
*
* @param skin The skin object or name
* @param param An optional parameter object
* @param skinobj The skin object or name
* @param paramobj An optional parameter object
*
* @return ...
*/
@ -295,19 +293,8 @@ public class HopObject extends ScriptableObject implements Wrapper {
if (id instanceof Number) {
n = get(((Number) id).intValue(), this);
} else if (id instanceof String) {
// 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);
}
} else if (id != null) {
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
@ -350,7 +337,7 @@ public class HopObject extends ScriptableObject implements Wrapper {
*/
public boolean jsFunction_set(Object id, Object value) {
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)) {
return false;
@ -361,7 +348,7 @@ public class HopObject extends ScriptableObject implements Wrapper {
if (id instanceof Number) {
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());
@ -369,10 +356,8 @@ public class HopObject extends ScriptableObject implements Wrapper {
node.addNode(n, idx);
} else if (id instanceof String) {
} else if (id != null) {
put(id.toString(), this, value);
} else {
throw new RuntimeException("Invalid type for id argument in HopObject.set(): "+id);
}
return true;
@ -844,7 +829,7 @@ public class HopObject extends ScriptableObject implements Wrapper {
/**
*
*
* @param name ...
* @param idx ...
* @param start ...
*
* @return ...
@ -862,7 +847,7 @@ public class HopObject extends ScriptableObject implements Wrapper {
/**
*
*
* @param name ...
* @param idx ...
* @param start ...
*
* @return ...