* Allow _parent to consist of three elements, such as page.comments.blocked.

Fixes bug 563 - http://helma.org/bugs/show_bug.cgi?id=563
* Throw an exception when adding to a collection with accessname defined and the 
  collection already contains an object with the given name. Previously, the old object 
  was deleted from the database. 
  Fixes bug 561 - http://helma.org/bugs/show_bug.cgi?id=561
This commit is contained in:
hns 2007-10-11 12:21:40 +00:00
parent 3c059e8778
commit ae0536eb26
2 changed files with 32 additions and 26 deletions

View file

@ -789,12 +789,17 @@ public final class Node implements INode, Serializable {
if (pn2 == null) { if (pn2 == null) {
getApp().logError("Error: Can't retrieve parent node " + getApp().logError("Error: Can't retrieve parent node " +
pinfo + " for " + this); pinfo + " for " + this);
} else if (pinfo.collectionname != null) {
pn2 = (Node) pn2.getNode(pinfo.collectionname);
} else if (pn2.equals(this)) { } else if (pn2.equals(this)) {
// a special case we want to support: virtualname is actually
// a reference to this node, not a collection containint this node.
setParent(pn); setParent(pn);
name = pinfo.virtualname; name = pinfo.virtualname;
anonymous = false; anonymous = false;
return pn; return pn;
} }
pn = pn2; pn = pn2;
} }
@ -952,11 +957,11 @@ public final class Node implements INode, Serializable {
} }
// check if subnode accessname is set. If so, check if another node // check if subnode accessname is set. If so, check if another node
// uses the same access name and remove it // uses the same access name, throwing an exception if so.
if ((dbmap != null) && (node.dbmap != null)) { if (dbmap != null && node.dbmap != null) {
Relation prel = dbmap.getSubnodeRelation(); 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);
// if no relation from db column to prop name is found, // if no relation from db column to prop name is found,
@ -965,15 +970,14 @@ public final class Node implements INode, Serializable {
: localrel.propName; : 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 = (INode) getChildElement(prop); INode old = (INode) getChildElement(prop);
if ((old != null) && (old != node)) { if (old != null && old != node) {
// FIXME: we delete the existing node here, // A node with this name already exists. This is a
// but actually the app developer should prevent this from // programming error, throw an exception.
// happening, so it might be better to throw an exception. throw new RuntimeException("An object named \"" + prop +
old.remove(); "\" is already contained in the collection.");
this.removeNode(old);
} }
if (state != TRANSIENT) { if (state != TRANSIENT) {
@ -2714,7 +2718,7 @@ public final class Node implements INode, Serializable {
* @return the number of loaded nodes within this collection update * @return the number of loaded nodes within this collection update
*/ */
public int updateSubnodes () { public int updateSubnodes () {
// FIXME: what do we do if dbmap is null // TODO: what do we do if dbmap is null
if (dbmap == null) { if (dbmap == null) {
throw new RuntimeException (this + " doesn't have a DbMapping"); throw new RuntimeException (this + " doesn't have a DbMapping");
} }

View file

@ -16,6 +16,8 @@
package helma.objectmodel.db; package helma.objectmodel.db;
import helma.util.StringUtils;
/** /**
* This class describes a parent relation between releational nodes. * This class describes a parent relation between releational nodes.
@ -23,38 +25,38 @@ package helma.objectmodel.db;
public class ParentInfo { public class ParentInfo {
public final String propname; public final String propname;
public final String virtualname; public final String virtualname;
public final String collectionname;
public final boolean isroot; public final boolean isroot;
/** /**
* Creates a new ParentInfo object. * Creates a new ParentInfo object.
* *
* @param desc ... * @param desc a single parent info descriptor
*/ */
public ParentInfo(String desc) { public ParentInfo(String desc) {
// [named] isn't used anymore, we just want to keep the parsing compatible. // [named] isn't used anymore, we just want to keep the parsing compatible.
int n = desc.indexOf("[named]"); int n = desc.indexOf("[named]");
String d = n>-1 ? desc.substring(0, n) : desc; desc = n > -1 ? desc.substring(0, n) : desc;
int dot = d.indexOf("."); String[] parts = StringUtils.split(desc, ".");
if (dot > -1) { propname = parts.length > 0 ? parts[0].trim() : null;
propname = d.substring(0, dot).trim(); virtualname = parts.length > 1 ? parts[1].trim() : null;
virtualname = d.substring(dot + 1).trim(); collectionname = parts.length > 2 ? parts[2].trim() : null;
} else {
propname = d.trim();
virtualname = null;
}
isroot = "root".equalsIgnoreCase(propname); isroot = "root".equalsIgnoreCase(propname);
} }
/** /**
* * @return a string representation of the parent info
*
* @return ...
*/ */
public String toString() { public String toString() {
return "ParentInfo[" + propname + "," + virtualname + "]"; StringBuffer b = new StringBuffer("ParentInfo[").append(propname);
if (virtualname != null)
b.append(".").append(virtualname);
if (collectionname != null)
b.append(".").append(collectionname);
return b.append("]").toString();
} }
} }