From d2aa17041f26d47ec3843f789d00fedbb20abef0 Mon Sep 17 00:00:00 2001 From: hns Date: Wed, 5 Mar 2003 14:33:21 +0000 Subject: [PATCH] Several changes/fixes in DbMapping: * Relation mappings that are overwritten in sub-prototypes no longer override the parent prototype's Relation object but creates its own Relation * Generally enable all things to be overwritten in DbMappings that inherit from another relational DbMapping. That means it should now be possible to really change lots of things from a parent DbMapping and a child DbMapping. * Improved property enumeration which now merges properties defined in the DbMapping inherit chain * Cleaned up and improved variable naming. --- src/helma/objectmodel/db/DbMapping.java | 196 +++++++++++++--------- src/helma/objectmodel/db/Node.java | 51 +++--- src/helma/objectmodel/db/NodeManager.java | 10 +- src/helma/objectmodel/db/Property.java | 2 +- src/helma/objectmodel/db/Relation.java | 26 +-- 5 files changed, 158 insertions(+), 127 deletions(-) diff --git a/src/helma/objectmodel/db/DbMapping.java b/src/helma/objectmodel/db/DbMapping.java index 14d8af5d..f8995ee8 100644 --- a/src/helma/objectmodel/db/DbMapping.java +++ b/src/helma/objectmodel/db/DbMapping.java @@ -7,6 +7,7 @@ import helma.framework.core.Application; import helma.util.Updatable; import helma.util.SystemProperties; import java.util.HashMap; +import java.util.HashSet; import java.util.Enumeration; import java.util.Iterator; import java.util.StringTokenizer; @@ -28,15 +29,15 @@ public final class DbMapping implements Updatable { // properties from where the mapping is read SystemProperties props; - // name of data source to which this mapping writes - DbSource source; + // name of data dbSource to which this mapping writes + DbSource dbSource; // name of datasource - String sourceName; + String dbSourceName; // name of db table - String table; + String tableName; // list of properties to try for parent - ParentInfo[] parent; + ParentInfo[] parentInfo; // Relations describing subnodes and properties. Relation subRelation; @@ -101,7 +102,7 @@ public final class DbMapping implements Updatable { prop2db = new HashMap (); db2prop = new HashMap (); - parent = null; + parentInfo = null; idField = null; } @@ -123,7 +124,7 @@ public final class DbMapping implements Updatable { columnMap = new HashMap (); - parent = null; + parentInfo = null; idField = null; @@ -145,7 +146,7 @@ public final class DbMapping implements Updatable { */ public synchronized void update () { // read in properties - table = props.getProperty ("_table"); + tableName = props.getProperty ("_table"); idgen = props.getProperty ("_idgen"); // see if there is a field which specifies the prototype of objects, if different prototypes // can be stored in this table @@ -153,17 +154,17 @@ public final class DbMapping implements Updatable { // see if this prototype extends (inherits from) any other prototype extendsProto = props.getProperty ("_extends"); - sourceName = props.getProperty ("_db"); - if (sourceName != null) { - source = app.getDbSource (sourceName); - if (source == null) { - app.logEvent ("*** Data Source for prototype "+typename+" does not exist: "+sourceName); + dbSourceName = props.getProperty ("_db"); + if (dbSourceName != null) { + dbSource = app.getDbSource (dbSourceName); + if (dbSource == null) { + app.logEvent ("*** Data Source for prototype "+typename+" does not exist: "+dbSourceName); app.logEvent ("*** accessing or storing a "+typename+" object will cause an error."); - } else if (table == null) { + } else if (tableName == null) { app.logEvent ("*** No table name specified for prototype "+typename); app.logEvent ("*** accessing or storing a "+typename+" object will cause an error."); - // mark mapping as invalid by nulling the source field - source = null; + // mark mapping as invalid by nulling the dbSource field + dbSource = null; } } @@ -179,11 +180,11 @@ public final class DbMapping implements Updatable { if (parentSpec != null) { // comma-separated list of properties to be used as parent StringTokenizer st = new StringTokenizer (parentSpec, ",;"); - parent = new ParentInfo[st.countTokens()]; - for (int i=0; i 0) { setName (propvalue); @@ -664,9 +664,9 @@ 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 (); - if (prel != null && prel.otherType == dbmap && prel.accessor != null) { + if (prel != null && prel.otherType == dbmap && prel.accessName != null) { // reverse look up property used to access this via parent - Relation proprel = dbmap.columnNameToRelation (prel.accessor); + Relation proprel = dbmap.columnNameToRelation (prel.accessName); if (proprel != null && proprel.propName != null) newname = getString (proprel.propName); } @@ -773,17 +773,18 @@ public final class Node implements INode, Serializable { checkWriteLock (); node.checkWriteLock (); } - + // if subnodes are defined via realation, make sure its constraints are enforced. - if (dbmap != null && dbmap.getSubnodeRelation () != null) + if (dbmap != null && dbmap.getSubnodeRelation () != null) { dbmap.getSubnodeRelation ().setConstraints (this, node); - + } + // if the new node is marked as TRANSIENT and this node is not, mark new node as NEW if (state != TRANSIENT && node.state == TRANSIENT) node.makePersistentCapable (); String n = node.getName(); - + // if (n.indexOf('/') > -1) // throw new RuntimeException ("\"/\" found in Node name."); @@ -809,7 +810,7 @@ public final class Node implements INode, Serializable { if (groupbyNode == null) groupbyNode = getGroupbySubnode (groupbyValue, true); groupbyNode.addNode (node); - + return node; } catch (Exception x) { System.err.println ("Error adding groupby: "+x); @@ -836,10 +837,10 @@ 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(); - if (prel != null && prel.accessor != null) { - Relation localrel = node.dbmap.columnNameToRelation (prel.accessor); + if (prel != null && prel.accessName != null) { + Relation localrel = node.dbmap.columnNameToRelation (prel.accessName); // if no relation from db column to prop name is found, assume that both are equal - String propname = localrel == null ? prel.accessor : localrel.propName; + String propname = localrel == null ? prel.accessName : localrel.propName; String prop = node.getString (propname); if (prop != null && prop.length() > 0) { INode old = getNode (prop); @@ -932,7 +933,7 @@ public final class Node implements INode, Serializable { if (rel != null) return (IPathElement) getNode (name); rel = dbmap.getSubnodeRelation (); - if (rel != null && rel.groupby == null && rel.accessor != null) { + if (rel != null && rel.groupby == null && rel.accessName != null) { if (rel.otherType != null && rel.otherType.isRelational ()) return (IPathElement) nmgr.getNode (this, name, rel); else @@ -1112,10 +1113,10 @@ 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(); - if (prel != null && prel.accessor != null) { - Relation localrel = node.dbmap.columnNameToRelation (prel.accessor); + if (prel != null && prel.accessName != null) { + Relation localrel = node.dbmap.columnNameToRelation (prel.accessName); // if no relation from db column to prop name is found, assume that both are equal - String propname = localrel == null ? prel.accessor : localrel.propName; + String propname = localrel == null ? prel.accessName : localrel.propName; String prop = node.getString (propname); if (prop != null && getNode (prop) == node) unset (prop); @@ -1309,17 +1310,13 @@ public final class Node implements INode, Serializable { */ public Enumeration properties () { - if (dbmap != null && dbmap.isRelational() && dbmap.getProp2DB ().size() > 0) + if (dbmap != null && dbmap.isRelational()) // return the properties defined in type.properties, if there are any - return new Enumeration () { - Iterator i = dbmap.getProp2DB().keySet().iterator(); - public boolean hasMoreElements() {return i.hasNext();} - public Object nextElement () {return i.next();} - }; + return dbmap.getPropertyEnumeration(); Relation prel = dbmap == null ? null : dbmap.getPropertyRelation (); - if (prel != null && prel.accessor != null && !prel.subnodesAreProperties - && prel.otherType != null && prel.otherType.isRelational ()) + if (prel != null && prel.hasAccessName() + && prel.otherType != null && prel.otherType.isRelational ()) // return names of objects from a relational db table return nmgr.getPropertyNames (this, prel).elements (); else if (propMap != null) @@ -1493,7 +1490,7 @@ public final class Node implements INode, Serializable { propMap.put (p2, prop); } - // check if this may have an effect on the node's URL when using subnodesAreProperties + // check if this may have an effect on the node's URL when using accessname // but only do this if we already have a parent set, i.e. if we are already stored in the db Node parent = parentHandle == null ? null : (Node) getParent (); @@ -1504,7 +1501,7 @@ public final class Node implements INode, Serializable { Relation propRel = parentmap.getPropertyRelation (); String dbcolumn = dbmap.propertyToColumnName (propname); - if (propRel != null && propRel.accessor != null && propRel.accessor.equals (dbcolumn)) { + if (propRel != null && propRel.accessName != null && propRel.accessName.equals (dbcolumn)) { INode n = parent.getNode (value); if (n != null && n != this) { parent.unset (value); @@ -1748,7 +1745,7 @@ public final class Node implements INode, Serializable { // UPDATE: using n.getKey() instead of manually constructing key. HW 2002/09/13 tx.visitCleanNode (n.getKey(), n); // if the field is not the primary key of the property, also register it - if (rel != null && rel.accessor != null && state != TRANSIENT) { + if (rel != null && rel.accessName != null && state != TRANSIENT) { Key secKey = new SyntheticKey (getKey (), propname); nmgr.evictKey (secKey); tx.visitCleanNode (secKey, n); diff --git a/src/helma/objectmodel/db/NodeManager.java b/src/helma/objectmodel/db/NodeManager.java index e8c88b34..87134589 100644 --- a/src/helma/objectmodel/db/NodeManager.java +++ b/src/helma/objectmodel/db/NodeManager.java @@ -1027,8 +1027,8 @@ public final class NodeManager { } String accessProp = null; - if (rel.accessor != null && !rel.usesPrimaryKey ()) - accessProp = dbm.columnNameToProperty (rel.accessor); + if (rel.accessName != null && !rel.usesPrimaryKey ()) + accessProp = dbm.columnNameToProperty (rel.accessName); while (rs.next ()) { // create new Nodes. @@ -1048,7 +1048,7 @@ public final class NodeManager { sn.add (new NodeHandle (primKey)); } - // if relation doesn't use primary key as accessor, get accessor value + // if relation doesn't use primary key as accessName, get accessName value String accessName = null; if (accessProp != null) { accessName = node.getString (accessProp); @@ -1166,7 +1166,7 @@ public final class NodeManager { Vector retval = new Vector (); // if we do a groupby query (creating an intermediate layer of groupby nodes), // retrieve the value of that field instead of the primary key - String namefield = rel.accessor; + String namefield = rel.accessName; Connection con = rel.otherType.getConnection (); String table = rel.otherType.getTableName (); @@ -1296,7 +1296,7 @@ public final class NodeManager { if (home.getSubnodeRelation () != null) { // combine our key with the constraints in the manually set subnode relation q.append ("WHERE "); - q.append (rel.accessor); + q.append (rel.accessName); q.append (" = '"); q.append (escape(kstr)); q.append ("'"); diff --git a/src/helma/objectmodel/db/Property.java b/src/helma/objectmodel/db/Property.java index d933c5b2..beabe7fa 100644 --- a/src/helma/objectmodel/db/Property.java +++ b/src/helma/objectmodel/db/Property.java @@ -238,7 +238,7 @@ public final class Property implements IProperty, Serializable, Cloneable { // check if the property node is also a subnode // BUG: this doesn't work because properties for subnode/properties are never stored and therefore // never reused. - if (nvrel != null && nvrel.subnodesAreProperties) { + if (nvrel != null && nvrel.hasAccessName()) { node.removeNode (nvalue); } // only need to call unregisterPropLink if the value node is not stored in a relational db diff --git a/src/helma/objectmodel/db/Relation.java b/src/helma/objectmodel/db/Relation.java index c29a08c1..b744e588 100644 --- a/src/helma/objectmodel/db/Relation.java +++ b/src/helma/objectmodel/db/Relation.java @@ -52,10 +52,9 @@ public final class Relation { boolean readonly; boolean aggressiveLoading; boolean aggressiveCaching; - boolean subnodesAreProperties; boolean isPrivate; - String accessor; // db column used to access objects through this relation + String accessName; // db column used to access objects through this relation String order; String groupbyOrder; String groupby; @@ -76,9 +75,8 @@ public final class Relation { this.columnName = rel.columnName; this.reftype = rel.reftype; this.constraints = rel.constraints; - this.accessor = rel.accessor; + this.accessName = rel.accessName; this.maxSize = rel.maxSize; - this.subnodesAreProperties = rel.subnodesAreProperties; } /** @@ -199,10 +197,8 @@ public final class Relation { aggressiveLoading = aggressiveCaching = false; } // check if subnode condition should be applied for property relations - accessor = props.getProperty (propName+".accessname"); - if (accessor != null) - subnodesAreProperties = true; - // parse contstraints + accessName = props.getProperty (propName+".accessname"); + // parse contstraints String local = props.getProperty (propName+".local"); String foreign = props.getProperty (propName+".foreign"); if (local != null && foreign != null) { @@ -257,7 +253,7 @@ public final class Relation { * and never stored to a persistent storage. */ public boolean createPropertyOnDemand () { - return virtual || accessor != null || groupby != null; + return virtual || accessName != null || groupby != null; } /** @@ -321,13 +317,17 @@ public final class Relation { if (reftype == REFERENCE) return constraints.length == 1 && constraints[0].foreignKeyIsPrimary (); if (reftype == COLLECTION) - return accessor == null || accessor.equalsIgnoreCase (otherType.getIDField ()); + return accessName == null || accessName.equalsIgnoreCase (otherType.getIDField ()); } return false; } - public String getAccessor () { - return accessor; + public boolean hasAccessName () { + return accessName != null; + } + + public String getAccessName () { + return accessName; } public Relation getSubnodeRelation () { @@ -445,7 +445,7 @@ public final class Relation { String prefix = pre; if (kstr != null) { q.append (prefix); - String accessColumn = accessor == null ? otherType.getIDField () : accessor; + String accessColumn = accessName == null ? otherType.getIDField () : accessName; q.append (accessColumn); q.append (" = "); // check if column is string type and value needs to be quoted