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.
This commit is contained in:
hns 2003-03-05 14:33:21 +00:00
parent 49f011ab87
commit d2aa17041f
5 changed files with 158 additions and 127 deletions

View file

@ -7,6 +7,7 @@ import helma.framework.core.Application;
import helma.util.Updatable; import helma.util.Updatable;
import helma.util.SystemProperties; import helma.util.SystemProperties;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Iterator; import java.util.Iterator;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -28,15 +29,15 @@ public final class DbMapping implements Updatable {
// properties from where the mapping is read // properties from where the mapping is read
SystemProperties props; SystemProperties props;
// name of data source to which this mapping writes // name of data dbSource to which this mapping writes
DbSource source; DbSource dbSource;
// name of datasource // name of datasource
String sourceName; String dbSourceName;
// name of db table // name of db table
String table; String tableName;
// list of properties to try for parent // list of properties to try for parent
ParentInfo[] parent; ParentInfo[] parentInfo;
// Relations describing subnodes and properties. // Relations describing subnodes and properties.
Relation subRelation; Relation subRelation;
@ -101,7 +102,7 @@ public final class DbMapping implements Updatable {
prop2db = new HashMap (); prop2db = new HashMap ();
db2prop = new HashMap (); db2prop = new HashMap ();
parent = null; parentInfo = null;
idField = null; idField = null;
} }
@ -123,7 +124,7 @@ public final class DbMapping implements Updatable {
columnMap = new HashMap (); columnMap = new HashMap ();
parent = null; parentInfo = null;
idField = null; idField = null;
@ -145,7 +146,7 @@ public final class DbMapping implements Updatable {
*/ */
public synchronized void update () { public synchronized void update () {
// read in properties // read in properties
table = props.getProperty ("_table"); tableName = props.getProperty ("_table");
idgen = props.getProperty ("_idgen"); idgen = props.getProperty ("_idgen");
// see if there is a field which specifies the prototype of objects, if different prototypes // see if there is a field which specifies the prototype of objects, if different prototypes
// can be stored in this table // 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 // see if this prototype extends (inherits from) any other prototype
extendsProto = props.getProperty ("_extends"); extendsProto = props.getProperty ("_extends");
sourceName = props.getProperty ("_db"); dbSourceName = props.getProperty ("_db");
if (sourceName != null) { if (dbSourceName != null) {
source = app.getDbSource (sourceName); dbSource = app.getDbSource (dbSourceName);
if (source == null) { if (dbSource == null) {
app.logEvent ("*** Data Source for prototype "+typename+" does not exist: "+sourceName); app.logEvent ("*** Data Source for prototype "+typename+" does not exist: "+dbSourceName);
app.logEvent ("*** accessing or storing a "+typename+" object will cause an error."); 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 ("*** No table name specified for prototype "+typename);
app.logEvent ("*** accessing or storing a "+typename+" object will cause an error."); app.logEvent ("*** accessing or storing a "+typename+" object will cause an error.");
// mark mapping as invalid by nulling the source field // mark mapping as invalid by nulling the dbSource field
source = null; dbSource = null;
} }
} }
@ -179,11 +180,11 @@ public final class DbMapping implements Updatable {
if (parentSpec != null) { if (parentSpec != null) {
// comma-separated list of properties to be used as parent // comma-separated list of properties to be used as parent
StringTokenizer st = new StringTokenizer (parentSpec, ",;"); StringTokenizer st = new StringTokenizer (parentSpec, ",;");
parent = new ParentInfo[st.countTokens()]; parentInfo = new ParentInfo[st.countTokens()];
for (int i=0; i<parent.length; i++) for (int i=0; i<parentInfo.length; i++)
parent[i] = new ParentInfo (st.nextToken().trim()); parentInfo[i] = new ParentInfo (st.nextToken().trim());
} else { } else {
parent = null; parentInfo = null;
} }
lastTypeChange = props.lastModified (); lastTypeChange = props.lastModified ();
@ -197,8 +198,8 @@ public final class DbMapping implements Updatable {
parentMapping = app.getDbMapping (extendsProto); parentMapping = app.getDbMapping (extendsProto);
} }
// if (table != null && source != null) { // if (tableName != null && dbSource != null) {
// app.logEvent ("set data source for "+typename+" to "+source); // app.logEvent ("set data dbSource for "+typename+" to "+dbSource);
HashMap p2d = new HashMap (); HashMap p2d = new HashMap ();
HashMap d2p = new HashMap (); HashMap d2p = new HashMap ();
@ -210,10 +211,13 @@ public final class DbMapping implements Updatable {
if (!propName.startsWith ("_") && propName.indexOf (".") < 0) { if (!propName.startsWith ("_") && propName.indexOf (".") < 0) {
String dbField = props.getProperty (propName); String dbField = props.getProperty (propName);
// check if a relation for this propery already exists. If so, reuse it // check if a relation for this propery already exists. If so, reuse it
Relation rel = propertyToRelation (propName); Relation rel = (Relation) prop2db.get (propName.toLowerCase());
if (rel == null) if (rel == null)
rel = new Relation (dbField, propName, this, props); rel = new Relation (dbField, propName, this, props);
rel.update (dbField, props); rel.update (dbField, props);
// key enumerations from SystemProperties are all lower case, which is why
// even though we don't do a toLowerCase() here,
// we have to when we lookup things in p2d later.
p2d.put (propName, rel); p2d.put (propName, rel);
if (rel.columnName != null && if (rel.columnName != null &&
(rel.reftype == Relation.PRIMITIVE || (rel.reftype == Relation.PRIMITIVE ||
@ -238,7 +242,7 @@ public final class DbMapping implements Updatable {
subRelation.update (subnodeMapping, props); subRelation.update (subnodeMapping, props);
// if subnodes are accessed via access name or group name, // if subnodes are accessed via access name or group name,
// the subnode relation is also the property relation. // the subnode relation is also the property relation.
if (subRelation.accessor != null || subRelation.groupby != null) if (subRelation.accessName != null || subRelation.groupby != null)
propRelation = subRelation; propRelation = subRelation;
} catch (Exception x) { } catch (Exception x) {
app.logEvent ("Error reading _subnodes relation for "+typename+": "+x.getMessage ()); app.logEvent ("Error reading _subnodes relation for "+typename+": "+x.getMessage ());
@ -266,18 +270,23 @@ public final class DbMapping implements Updatable {
* Get a JDBC connection for this DbMapping. * Get a JDBC connection for this DbMapping.
*/ */
public Connection getConnection () throws ClassNotFoundException, SQLException { public Connection getConnection () throws ClassNotFoundException, SQLException {
// if source was previously not available, check again if (dbSourceName == null) {
if (source == null && sourceName != null) if (parentMapping != null)
source = app.getDbSource (sourceName); return parentMapping.getConnection ();
if (sourceName == null && parentMapping != null)
return parentMapping.getConnection ();
if (source == null) {
if (sourceName == null)
throw new SQLException ("Tried to get Connection from non-relational embedded data source.");
else else
throw new SQLException ("Datasource is not defined: "+sourceName+"."); throw new SQLException ("Tried to get Connection from non-relational embedded data source.");
} }
return source.getConnection (); if (tableName == null) {
throw new SQLException ("Invalid DbMapping, _table not specified: "+this);
}
// if dbSource was previously not available, check again
if (dbSource == null) {
dbSource = app.getDbSource (dbSourceName);
}
if (dbSource == null) {
throw new SQLException ("Datasource is not defined: "+dbSourceName+".");
}
return dbSource.getConnection ();
} }
/** /**
@ -285,27 +294,23 @@ public final class DbMapping implements Updatable {
* data source including URL, JDBC driver, username and password. * data source including URL, JDBC driver, username and password.
*/ */
public DbSource getDbSource () { public DbSource getDbSource () {
if (source == null && parentMapping != null) if (dbSource == null) {
return parentMapping.getDbSource (); if (tableName != null && dbSourceName != null)
return source; dbSource = app.getDbSource (dbSourceName);
else if (parentMapping != null)
return parentMapping.getDbSource ();
}
return dbSource;
} }
/**
* Get the URL of the data source used for this mapping.
*/
public String getSourceID () {
if (source == null && parentMapping != null)
return parentMapping.getSourceID ();
return source == null ? "" : source.url;
}
/** /**
* Get the table name used for this type mapping. * Get the table name used for this type mapping.
*/ */
public String getTableName () { public String getTableName () {
if (source == null && parentMapping != null) if (tableName == null && parentMapping != null)
return parentMapping.getTableName (); return parentMapping.getTableName ();
return table; return tableName;
} }
/** /**
@ -349,7 +354,7 @@ public final class DbMapping implements Updatable {
* Get the column used for (internal) names of objects of this type. * Get the column used for (internal) names of objects of this type.
*/ */
public String getNameField () { public String getNameField () {
if (nameField == null && parentMapping != null) if (nameField == null && parentMapping != null)
return parentMapping.getNameField (); return parentMapping.getNameField ();
return nameField; return nameField;
} }
@ -358,7 +363,7 @@ public final class DbMapping implements Updatable {
* Get the column used for names of prototype. * Get the column used for names of prototype.
*/ */
public String getPrototypeField () { public String getPrototypeField () {
if (protoField == null && parentMapping != null) if (protoField == null && parentMapping != null)
return parentMapping.getPrototypeField (); return parentMapping.getPrototypeField ();
return protoField; return protoField;
} }
@ -370,9 +375,13 @@ public final class DbMapping implements Updatable {
public String columnNameToProperty (String columnName) { public String columnNameToProperty (String columnName) {
if (columnName == null) if (columnName == null)
return null; return null;
if (table == null && parentMapping != null) return _columnNameToProperty (columnName.toUpperCase());
return parentMapping.columnNameToProperty (columnName); }
Relation rel = (Relation) db2prop.get (columnName.toUpperCase ());
private String _columnNameToProperty (final String columnName) {
Relation rel = (Relation) db2prop.get (columnName);
if (rel == null && parentMapping != null)
return parentMapping._columnNameToProperty (columnName);
if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE)) if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE))
return rel.propName; return rel.propName;
return null; return null;
@ -384,11 +393,15 @@ public final class DbMapping implements Updatable {
public String propertyToColumnName (String propName) { public String propertyToColumnName (String propName) {
if (propName == null) if (propName == null)
return null; return null;
if (table == null && parentMapping != null)
return parentMapping.propertyToColumnName (propName);
// FIXME: prop2db stores keys in lower case, because it gets them // FIXME: prop2db stores keys in lower case, because it gets them
// from a SystemProperties object which converts keys to lower case. // from a SystemProperties object which converts keys to lower case.
Relation rel = (Relation) prop2db.get (propName.toLowerCase()); return _propertyToColumnName (propName.toLowerCase ());
}
private String _propertyToColumnName (final String propName) {
Relation rel = (Relation) prop2db.get (propName);
if (rel == null && parentMapping != null)
return parentMapping._propertyToColumnName (propName);
if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE)) if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE))
return rel.columnName; return rel.columnName;
return null; return null;
@ -400,9 +413,14 @@ public final class DbMapping implements Updatable {
public Relation columnNameToRelation (String columnName) { public Relation columnNameToRelation (String columnName) {
if (columnName == null) if (columnName == null)
return null; return null;
if (table == null && parentMapping != null) return _columnNameToRelation (columnName.toUpperCase());
return parentMapping.columnNameToRelation (columnName); }
return (Relation) db2prop.get (columnName.toUpperCase ());
private Relation _columnNameToRelation (final String columnName) {
Relation rel = (Relation) db2prop.get (columnName);
if (rel == null && parentMapping != null)
return parentMapping._columnNameToRelation (columnName);
return rel;
} }
/** /**
@ -411,11 +429,16 @@ public final class DbMapping implements Updatable {
public Relation propertyToRelation (String propName) { public Relation propertyToRelation (String propName) {
if (propName == null) if (propName == null)
return null; return null;
if (table == null && parentMapping != null)
return parentMapping.propertyToRelation (propName);
// FIXME: prop2db stores keys in lower case, because it gets them // FIXME: prop2db stores keys in lower case, because it gets them
// from a SystemProperties object which converts keys to lower case. // from a SystemProperties object which converts keys to lower case.
return (Relation) prop2db.get (propName.toLowerCase()); return _propertyToRelation (propName.toLowerCase());
}
private Relation _propertyToRelation (String propName) {
Relation rel = (Relation) prop2db.get (propName);
if (rel == null && parentMapping != null)
return parentMapping._propertyToRelation (propName);
return rel;
} }
@ -424,17 +447,17 @@ public final class DbMapping implements Updatable {
* determine its parent object. * determine its parent object.
*/ */
public synchronized ParentInfo[] getParentInfo () { public synchronized ParentInfo[] getParentInfo () {
if (parent == null && parentMapping != null) if (parentInfo == null && parentMapping != null)
return parentMapping.getParentInfo (); return parentMapping.getParentInfo ();
return parent; return parentInfo;
} }
public DbMapping getSubnodeMapping () { public DbMapping getSubnodeMapping () {
if (subRelation != null) if (subRelation != null)
return subRelation.otherType; return subRelation.otherType;
if (parentMapping != null) if (parentMapping != null)
return parentMapping.getSubnodeMapping (); return parentMapping.getSubnodeMapping ();
return null; return null;
} }
@ -551,7 +574,7 @@ public final class DbMapping implements Updatable {
* not what we want. * not what we want.
*/ */
public boolean isRelational () { public boolean isRelational () {
if (sourceName != null) if (dbSourceName != null)
return true; return true;
if (parentMapping != null) if (parentMapping != null)
return parentMapping.isRelational (); return parentMapping.isRelational ();
@ -565,7 +588,7 @@ public final class DbMapping implements Updatable {
public synchronized DbColumn[] getColumns() throws ClassNotFoundException, SQLException { public synchronized DbColumn[] getColumns() throws ClassNotFoundException, SQLException {
if (!isRelational ()) if (!isRelational ())
throw new SQLException ("Can't get columns for non-relational data mapping "+this); throw new SQLException ("Can't get columns for non-relational data mapping "+this);
if (source == null && parentMapping != null) if (dbSource == null && parentMapping != null)
return parentMapping.getColumns (); return parentMapping.getColumns ();
// Use local variable cols to avoid synchronization (schema may be nulled elsewhere) // Use local variable cols to avoid synchronization (schema may be nulled elsewhere)
if (columns == null) { if (columns == null) {
@ -656,7 +679,7 @@ public final class DbMapping implements Updatable {
* to be quoted in SQL queries. * to be quoted in SQL queries.
*/ */
public boolean needsQuotes (String columnName) throws SQLException { public boolean needsQuotes (String columnName) throws SQLException {
if (table == null && parentMapping != null) if (tableName == null && parentMapping != null)
return parentMapping.needsQuotes (columnName); return parentMapping.needsQuotes (columnName);
try { try {
DbColumn col = getColumn (columnName); DbColumn col = getColumn (columnName);
@ -698,27 +721,38 @@ public final class DbMapping implements Updatable {
public void notifyDataChange () { public void notifyDataChange () {
lastDataChange = System.currentTimeMillis (); lastDataChange = System.currentTimeMillis ();
if (parentMapping != null && source == null) if (parentMapping != null && dbSource == null)
parentMapping.notifyDataChange (); parentMapping.notifyDataChange ();
} }
public synchronized long getNewID (long dbmax) { public synchronized long getNewID (long dbmax) {
if (parentMapping != null && source == null) if (parentMapping != null && dbSource == null)
return parentMapping.getNewID (dbmax); return parentMapping.getNewID (dbmax);
lastID = Math.max (dbmax+1, lastID+1); lastID = Math.max (dbmax+1, lastID+1);
return lastID; return lastID;
} }
public HashMap getProp2DB () {
if (table == null && parentMapping != null) public Enumeration getPropertyEnumeration () {
return parentMapping.getProp2DB (); HashSet set = new HashSet ();
return prop2db; collectPropertyNames (set);
final Iterator it = set.iterator();
return new Enumeration () {
public boolean hasMoreElements() {
return it.hasNext();
}
public Object nextElement() {
return it.next();
}
};
} }
public Iterator getDBPropertyIterator () { private void collectPropertyNames (HashSet basket) {
if (table == null && parentMapping != null) // fetch propnames from parent mapping first, than add our own.
return parentMapping.getDBPropertyIterator (); if (parentMapping != null)
return db2prop.values ().iterator (); parentMapping.collectPropertyNames (basket);
if (!prop2db.isEmpty())
basket.addAll (prop2db.keySet());
} }
/** /**
@ -727,9 +761,9 @@ public final class DbMapping implements Updatable {
* db. * db.
*/ */
public String getStorageTypeName () { public String getStorageTypeName () {
if (table == null && parentMapping != null) if (tableName == null && parentMapping != null)
return parentMapping.getStorageTypeName (); return parentMapping.getStorageTypeName ();
return sourceName == null ? null : typename; return dbSourceName == null ? null : typename;
} }
/** /**

View file

@ -502,8 +502,8 @@ public final class Node implements INode, Serializable {
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.getPropertyRelation();
if (prel != null && prel.subnodesAreProperties && prel.accessor != null) { if (prel != null && prel.hasAccessName()) {
String propname = dbmap.columnNameToProperty (prel.accessor); String propname = dbmap.columnNameToProperty (prel.accessName);
String propvalue = getString (propname); String propvalue = getString (propname);
if (propvalue != null && propvalue.length() > 0) { if (propvalue != null && propvalue.length() > 0) {
setName (propvalue); setName (propvalue);
@ -664,9 +664,9 @@ 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.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 // 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) if (proprel != null && proprel.propName != null)
newname = getString (proprel.propName); newname = getString (proprel.propName);
} }
@ -773,17 +773,18 @@ public final class Node implements INode, Serializable {
checkWriteLock (); checkWriteLock ();
node.checkWriteLock (); node.checkWriteLock ();
} }
// if subnodes are defined via realation, make sure its constraints are enforced. // 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); dbmap.getSubnodeRelation ().setConstraints (this, node);
}
// if the new node is marked as TRANSIENT and this node is not, mark new node as NEW // if the new node is marked as TRANSIENT and this node is not, mark new node as NEW
if (state != TRANSIENT && node.state == TRANSIENT) if (state != TRANSIENT && node.state == TRANSIENT)
node.makePersistentCapable (); node.makePersistentCapable ();
String n = node.getName(); String n = node.getName();
// if (n.indexOf('/') > -1) // if (n.indexOf('/') > -1)
// throw new RuntimeException ("\"/\" found in Node name."); // throw new RuntimeException ("\"/\" found in Node name.");
@ -809,7 +810,7 @@ public final class Node implements INode, Serializable {
if (groupbyNode == null) if (groupbyNode == null)
groupbyNode = getGroupbySubnode (groupbyValue, true); groupbyNode = getGroupbySubnode (groupbyValue, true);
groupbyNode.addNode (node); groupbyNode.addNode (node);
return node; return node;
} catch (Exception x) { } catch (Exception x) {
System.err.println ("Error adding groupby: "+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) // 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.getPropertyRelation();
if (prel != null && prel.accessor != null) { if (prel != null && prel.accessName != null) {
Relation localrel = node.dbmap.columnNameToRelation (prel.accessor); Relation localrel = node.dbmap.columnNameToRelation (prel.accessName);
// if no relation from db column to prop name is found, assume that both are equal // 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); String prop = node.getString (propname);
if (prop != null && prop.length() > 0) { if (prop != null && prop.length() > 0) {
INode old = getNode (prop); INode old = getNode (prop);
@ -932,7 +933,7 @@ public final class Node implements INode, Serializable {
if (rel != null) if (rel != null)
return (IPathElement) getNode (name); return (IPathElement) getNode (name);
rel = dbmap.getSubnodeRelation (); 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 ()) if (rel.otherType != null && rel.otherType.isRelational ())
return (IPathElement) nmgr.getNode (this, name, rel); return (IPathElement) nmgr.getNode (this, name, rel);
else 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 // 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.getPropertyRelation();
if (prel != null && prel.accessor != null) { if (prel != null && prel.accessName != null) {
Relation localrel = node.dbmap.columnNameToRelation (prel.accessor); Relation localrel = node.dbmap.columnNameToRelation (prel.accessName);
// if no relation from db column to prop name is found, assume that both are equal // 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); String prop = node.getString (propname);
if (prop != null && getNode (prop) == node) if (prop != null && getNode (prop) == node)
unset (prop); unset (prop);
@ -1309,17 +1310,13 @@ public final class Node implements INode, Serializable {
*/ */
public Enumeration properties () { 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 the properties defined in type.properties, if there are any
return new Enumeration () { return dbmap.getPropertyEnumeration();
Iterator i = dbmap.getProp2DB().keySet().iterator();
public boolean hasMoreElements() {return i.hasNext();}
public Object nextElement () {return i.next();}
};
Relation prel = dbmap == null ? null : dbmap.getPropertyRelation (); Relation prel = dbmap == null ? null : dbmap.getPropertyRelation ();
if (prel != null && prel.accessor != null && !prel.subnodesAreProperties if (prel != null && prel.hasAccessName()
&& prel.otherType != null && prel.otherType.isRelational ()) && prel.otherType != null && prel.otherType.isRelational ())
// return names of objects from a relational db table // return names of objects from a relational db table
return nmgr.getPropertyNames (this, prel).elements (); return nmgr.getPropertyNames (this, prel).elements ();
else if (propMap != null) else if (propMap != null)
@ -1493,7 +1490,7 @@ public final class Node implements INode, Serializable {
propMap.put (p2, prop); 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 // 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 (); Node parent = parentHandle == null ? null : (Node) getParent ();
@ -1504,7 +1501,7 @@ public final class Node implements INode, Serializable {
Relation propRel = parentmap.getPropertyRelation (); Relation propRel = parentmap.getPropertyRelation ();
String dbcolumn = dbmap.propertyToColumnName (propname); 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); INode n = parent.getNode (value);
if (n != null && n != this) { if (n != null && n != this) {
parent.unset (value); 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 // UPDATE: using n.getKey() instead of manually constructing key. HW 2002/09/13
tx.visitCleanNode (n.getKey(), n); tx.visitCleanNode (n.getKey(), n);
// if the field is not the primary key of the property, also register it // 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); Key secKey = new SyntheticKey (getKey (), propname);
nmgr.evictKey (secKey); nmgr.evictKey (secKey);
tx.visitCleanNode (secKey, n); tx.visitCleanNode (secKey, n);

View file

@ -1027,8 +1027,8 @@ public final class NodeManager {
} }
String accessProp = null; String accessProp = null;
if (rel.accessor != null && !rel.usesPrimaryKey ()) if (rel.accessName != null && !rel.usesPrimaryKey ())
accessProp = dbm.columnNameToProperty (rel.accessor); accessProp = dbm.columnNameToProperty (rel.accessName);
while (rs.next ()) { while (rs.next ()) {
// create new Nodes. // create new Nodes.
@ -1048,7 +1048,7 @@ public final class NodeManager {
sn.add (new NodeHandle (primKey)); 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; String accessName = null;
if (accessProp != null) { if (accessProp != null) {
accessName = node.getString (accessProp); accessName = node.getString (accessProp);
@ -1166,7 +1166,7 @@ public final class NodeManager {
Vector retval = new Vector (); Vector retval = new Vector ();
// if we do a groupby query (creating an intermediate layer of groupby nodes), // if we do a groupby query (creating an intermediate layer of groupby nodes),
// retrieve the value of that field instead of the primary key // retrieve the value of that field instead of the primary key
String namefield = rel.accessor; String namefield = rel.accessName;
Connection con = rel.otherType.getConnection (); Connection con = rel.otherType.getConnection ();
String table = rel.otherType.getTableName (); String table = rel.otherType.getTableName ();
@ -1296,7 +1296,7 @@ public final class NodeManager {
if (home.getSubnodeRelation () != null) { if (home.getSubnodeRelation () != null) {
// combine our key with the constraints in the manually set subnode relation // combine our key with the constraints in the manually set subnode relation
q.append ("WHERE "); q.append ("WHERE ");
q.append (rel.accessor); q.append (rel.accessName);
q.append (" = '"); q.append (" = '");
q.append (escape(kstr)); q.append (escape(kstr));
q.append ("'"); q.append ("'");

View file

@ -238,7 +238,7 @@ public final class Property implements IProperty, Serializable, Cloneable {
// check if the property node is also a subnode // check if the property node is also a subnode
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore // BUG: this doesn't work because properties for subnode/properties are never stored and therefore
// never reused. // never reused.
if (nvrel != null && nvrel.subnodesAreProperties) { if (nvrel != null && nvrel.hasAccessName()) {
node.removeNode (nvalue); node.removeNode (nvalue);
} }
// only need to call unregisterPropLink if the value node is not stored in a relational db // only need to call unregisterPropLink if the value node is not stored in a relational db

View file

@ -52,10 +52,9 @@ public final class Relation {
boolean readonly; boolean readonly;
boolean aggressiveLoading; boolean aggressiveLoading;
boolean aggressiveCaching; boolean aggressiveCaching;
boolean subnodesAreProperties;
boolean isPrivate; 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 order;
String groupbyOrder; String groupbyOrder;
String groupby; String groupby;
@ -76,9 +75,8 @@ public final class Relation {
this.columnName = rel.columnName; this.columnName = rel.columnName;
this.reftype = rel.reftype; this.reftype = rel.reftype;
this.constraints = rel.constraints; this.constraints = rel.constraints;
this.accessor = rel.accessor; this.accessName = rel.accessName;
this.maxSize = rel.maxSize; this.maxSize = rel.maxSize;
this.subnodesAreProperties = rel.subnodesAreProperties;
} }
/** /**
@ -199,10 +197,8 @@ public final class Relation {
aggressiveLoading = aggressiveCaching = false; aggressiveLoading = aggressiveCaching = false;
} }
// check if subnode condition should be applied for property relations // check if subnode condition should be applied for property relations
accessor = props.getProperty (propName+".accessname"); accessName = props.getProperty (propName+".accessname");
if (accessor != null) // parse contstraints
subnodesAreProperties = true;
// parse contstraints
String local = props.getProperty (propName+".local"); String local = props.getProperty (propName+".local");
String foreign = props.getProperty (propName+".foreign"); String foreign = props.getProperty (propName+".foreign");
if (local != null && foreign != null) { if (local != null && foreign != null) {
@ -257,7 +253,7 @@ public final class Relation {
* and never stored to a persistent storage. * and never stored to a persistent storage.
*/ */
public boolean createPropertyOnDemand () { 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) if (reftype == REFERENCE)
return constraints.length == 1 && constraints[0].foreignKeyIsPrimary (); return constraints.length == 1 && constraints[0].foreignKeyIsPrimary ();
if (reftype == COLLECTION) if (reftype == COLLECTION)
return accessor == null || accessor.equalsIgnoreCase (otherType.getIDField ()); return accessName == null || accessName.equalsIgnoreCase (otherType.getIDField ());
} }
return false; return false;
} }
public String getAccessor () { public boolean hasAccessName () {
return accessor; return accessName != null;
}
public String getAccessName () {
return accessName;
} }
public Relation getSubnodeRelation () { public Relation getSubnodeRelation () {
@ -445,7 +445,7 @@ public final class Relation {
String prefix = pre; String prefix = pre;
if (kstr != null) { if (kstr != null) {
q.append (prefix); q.append (prefix);
String accessColumn = accessor == null ? otherType.getIDField () : accessor; String accessColumn = accessName == null ? otherType.getIDField () : accessName;
q.append (accessColumn); q.append (accessColumn);
q.append (" = "); q.append (" = ");
// check if column is string type and value needs to be quoted // check if column is string type and value needs to be quoted