diff --git a/src/helma/objectmodel/db/DbMapping.java b/src/helma/objectmodel/db/DbMapping.java index 10b84244..d2186c25 100644 --- a/src/helma/objectmodel/db/DbMapping.java +++ b/src/helma/objectmodel/db/DbMapping.java @@ -26,8 +26,6 @@ public final class DbMapping implements Updatable { // prototype name of this mapping String typename; - // int version; - // properties from where the mapping is read SystemProperties props; @@ -42,8 +40,8 @@ public final class DbMapping implements Updatable { ParentInfo[] parent; // Relations describing subnodes and properties. - Relation subnodesRel; - Relation propertiesRel; + Relation subRelation; + Relation propRelation; // if this defines a subnode mapping with groupby layer, we need a DbMapping for those groupby nodes DbMapping groupbyMapping; @@ -230,17 +228,19 @@ public final class DbMapping implements Updatable { if (subnodeMapping != null) { try { // check if subnode relation already exists. If so, reuse it - if (subnodesRel == null) - subnodesRel = new Relation (subnodeMapping, "_children", this, props); - subnodesRel.update (subnodeMapping, props); - if (subnodesRel.accessor != null) - propertiesRel = subnodesRel; + if (subRelation == null) + subRelation = new Relation (subnodeMapping, "_children", this, props); + subRelation.update (subnodeMapping, props); + // if subnodes are accessed via access name or group name, + // the subnode relation is also the property relation. + if (subRelation.accessor != null || subRelation.groupby != null) + propRelation = subRelation; } catch (Exception x) { app.logEvent ("Error reading _subnodes relation for "+typename+": "+x.getMessage ()); - // subnodesRel = null; + // subRelation = null; } } else { - subnodesRel = propertiesRel = null; + subRelation = propRelation = null; } if (groupbyMapping != null) { @@ -422,8 +422,8 @@ public final class DbMapping implements Updatable { public DbMapping getSubnodeMapping () { - if (subnodesRel != null) - return subnodesRel.otherType; + if (subRelation != null) + return subRelation.otherType; if (parentMapping != null) return parentMapping.getSubnodeMapping (); return null; @@ -452,7 +452,7 @@ public final class DbMapping implements Updatable { * db-mapping with the right relations to create the group-by nodes */ public synchronized DbMapping getGroupbyMapping () { - if (subnodesRel == null || subnodesRel.groupby == null) + if (subRelation == null || subRelation.groupby == null) return null; if (groupbyMapping == null) { initGroupbyMapping (); @@ -469,38 +469,31 @@ public final class DbMapping implements Updatable { groupbyMapping = new DbMapping (app); // If a mapping is defined, make the internal mapping inherit from // the defined named prototype. - if (subnodesRel.groupbyprototype != null) - groupbyMapping.parentMapping = app.getDbMapping (subnodesRel.groupbyprototype); - groupbyMapping.subnodesRel = subnodesRel.getGroupbySubnodeRelation (); - if (propertiesRel != null) - groupbyMapping.propertiesRel = propertiesRel.getGroupbyPropertyRelation (); + if (subRelation.groupbyPrototype != null) + groupbyMapping.parentMapping = app.getDbMapping (subRelation.groupbyPrototype); + groupbyMapping.subRelation = subRelation.getGroupbySubnodeRelation (); + if (propRelation != null) + groupbyMapping.propRelation = propRelation.getGroupbyPropertyRelation (); else - groupbyMapping.propertiesRel = subnodesRel.getGroupbyPropertyRelation (); - groupbyMapping.typename = subnodesRel.groupbyprototype; + groupbyMapping.propRelation = subRelation.getGroupbyPropertyRelation (); + groupbyMapping.typename = subRelation.groupbyPrototype; } - /* public void setPropertyMapping (DbMapping pm) { - properties = pm; - } */ - - /* public void setSubnodeRelation (Relation rel) { - subnodesRel = rel; - } */ - + public void setPropertyRelation (Relation rel) { - propertiesRel = rel; + propRelation = rel; } public Relation getSubnodeRelation () { - if (subnodesRel == null && parentMapping != null) + if (subRelation == null && parentMapping != null) return parentMapping.getSubnodeRelation (); - return subnodesRel; + return subRelation; } public Relation getPropertyRelation () { - if (propertiesRel == null && parentMapping != null) + if (propRelation == null && parentMapping != null) return parentMapping.getPropertyRelation (); - return propertiesRel; + return propRelation; } public Relation getPropertyRelation (String propname) { @@ -524,9 +517,9 @@ public final class DbMapping implements Updatable { } public String getSubnodeGroupby () { - if (subnodesRel == null && parentMapping != null) + if (subRelation == null && parentMapping != null) return parentMapping.getSubnodeGroupby (); - return subnodesRel == null ? null : subnodesRel.groupby; + return subRelation == null ? null : subRelation.groupby; } public String getIDgen () { diff --git a/src/helma/objectmodel/db/Node.java b/src/helma/objectmodel/db/Node.java index dba3415d..08a829f5 100644 --- a/src/helma/objectmodel/db/Node.java +++ b/src/helma/objectmodel/db/Node.java @@ -17,7 +17,6 @@ import helma.objectmodel.*; import helma.util.*; import helma.framework.IPathElement; import java.math.BigDecimal; -// import com.workingdogs.village.*; /** @@ -154,7 +153,7 @@ public final class Node implements INode, Serializable { transient String subnodeRelation = null; transient long lastSubnodeFetch = 0; transient long lastSubnodeChange = 0; - + transient long lastNameCheck = 0; transient long lastParentSet = 0; transient long lastSubnodeCount = 0; // these two are only used @@ -261,11 +260,6 @@ public final class Node implements INode, Serializable { name = nameField == null ? id : rs.getString (nameField); if (name == null || name.length() == 0) name = dbmap.getTypeName() + " " + id; - // set parent for user objects to internal userroot node - if ("user".equals (prototype)) { - parentHandle = new NodeHandle (new DbKey (null, "1")); - anonymous = false; - } created = lastmodified = System.currentTimeMillis (); @@ -281,25 +275,25 @@ public final class Node implements INode, Serializable { switch (rel.getColumnType()) { case Types.BIT: - newprop.setBooleanValue (rs.getBoolean(rel.getDbField())); + newprop.setBooleanValue (rs.getBoolean(columns[i])); break; case Types.TINYINT: case Types.BIGINT: case Types.SMALLINT: case Types.INTEGER: - newprop.setIntegerValue (rs.getLong(rel.getDbField())); + newprop.setIntegerValue (rs.getLong(columns[i])); break; case Types.REAL: case Types.FLOAT: case Types.DOUBLE: - newprop.setFloatValue (rs.getDouble(rel.getDbField())); + newprop.setFloatValue (rs.getDouble(columns[i])); break; case Types.DECIMAL: case Types.NUMERIC: - BigDecimal num = rs.getBigDecimal (rel.getDbField()); + BigDecimal num = rs.getBigDecimal (columns[i]); if (num == null) break; if (num.scale() > 0) @@ -311,20 +305,20 @@ public final class Node implements INode, Serializable { case Types.LONGVARBINARY: case Types.VARBINARY: case Types.BINARY: - newprop.setStringValue (rs.getString(rel.getDbField())); + newprop.setStringValue (rs.getString(columns[i])); break; case Types.LONGVARCHAR: case Types.CHAR: case Types.VARCHAR: case Types.OTHER: - newprop.setStringValue (rs.getString(rel.getDbField())); + newprop.setStringValue (rs.getString(columns[i])); break; case Types.DATE: case Types.TIME: case Types.TIMESTAMP: - newprop.setDateValue (rs.getTimestamp(rel.getDbField())); + newprop.setDateValue (rs.getTimestamp(columns[i])); break; case Types.NULL: @@ -333,7 +327,7 @@ public final class Node implements INode, Serializable { // continue; default: - newprop.setStringValue (rs.getString(rel.getDbField())); + newprop.setStringValue (rs.getString(columns[i])); break; } @@ -478,16 +472,13 @@ public final class Node implements INode, Serializable { } /** - * Get something to identify this node within a URL. This is the ID for anonymous nodes + * Get something to identify this node within a URL. This is the ID for anonymous nodes * and a property value for named properties. */ 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. - // Work around this for user objects to alsways return a URL like /users/username - if ("user".equalsIgnoreCase (prototype)) { - anonymous = false; - } else if (parentHandle != null) { + if (parentHandle != null && lastNameCheck < Math.max (dbmap.getLastTypeChange(), lastmodified)) { try { Node p = parentHandle.getNode (nmgr); DbMapping parentmap = p.getDbMapping (); @@ -508,8 +499,9 @@ public final class Node implements INode, Serializable { } catch (Exception ignore) { // just fall back to default method } + lastNameCheck = System.currentTimeMillis (); } - return anonymous || name == null || name.length() == 0 ? id : name; + return anonymous || name == null || name.length() == 0 ? id : name; } @@ -615,10 +607,13 @@ public final class Node implements INode, Serializable { * Register a node as parent of the present node. We can't refer to the node directly, so we use * the ID + DB map combo. */ - public void setParent (Node parent) { + protected void setParent (Node parent) { parentHandle = parent == null ? null : parent.getHandle (); } + /** + * Set the parent handle which can be used to get the actual parent node. + */ public void setParentHandle (NodeHandle parent) { parentHandle = parent; } @@ -679,10 +674,11 @@ public final class Node implements INode, Serializable { // check what's specified in the type.properties for this node. ParentInfo[] parentInfo = null; - if (isRelational () && (lastParentSet < dbmap.getLastTypeChange() || lastParentSet < lastmodified)) + if (isRelational () && lastParentSet < Math.max (dbmap.getLastTypeChange(), lastmodified)) parentInfo = dbmap.getParentInfo (); - // check if current parent candidate matches presciption, if not, try to get it + // check if current parent candidate matches presciption, + // if not, try to get one that does. if (parentInfo != null && state != TRANSIENT) { for (int i=0; i