switched everything from the old id/mapping to the new
NodeHandle references. This breaks serialization compatibility with prior versions.
This commit is contained in:
parent
7bdcdcd65f
commit
a90c945bae
1 changed files with 238 additions and 248 deletions
|
@ -25,8 +25,8 @@ import com.workingdogs.village.*;
|
||||||
|
|
||||||
public class Node implements INode, Serializable {
|
public class Node implements INode, Serializable {
|
||||||
|
|
||||||
// The ID of this node's parent node
|
// The handle to the node's parent
|
||||||
protected String parentID;
|
protected NodeHandle parentHandle;
|
||||||
// Ordered list of subnodes of this node
|
// Ordered list of subnodes of this node
|
||||||
private List subnodes;
|
private List subnodes;
|
||||||
// Named subnodes (properties) of this node
|
// Named subnodes (properties) of this node
|
||||||
|
@ -52,7 +52,11 @@ public class Node implements INode, Serializable {
|
||||||
int version = in.readShort ();
|
int version = in.readShort ();
|
||||||
id = in.readUTF ();
|
id = in.readUTF ();
|
||||||
name = in.readUTF ();
|
name = in.readUTF ();
|
||||||
parentID = (String) in.readObject ();
|
if (version < 5)
|
||||||
|
throw new IOException ("Unsupported Data Format (pre 1.2)");
|
||||||
|
// parentHandle = new NodeHandle (new Key (null, (String) in.readObject ()));
|
||||||
|
else
|
||||||
|
parentHandle = (NodeHandle) in.readObject ();
|
||||||
created = in.readLong ();
|
created = in.readLong ();
|
||||||
lastmodified = in.readLong ();
|
lastmodified = in.readLong ();
|
||||||
if (version < 4) {
|
if (version < 4) {
|
||||||
|
@ -75,10 +79,10 @@ public class Node implements INode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeObject (ObjectOutputStream out) throws IOException {
|
private void writeObject (ObjectOutputStream out) throws IOException {
|
||||||
out.writeShort (4); // serialization version
|
out.writeShort (5); // serialization version
|
||||||
out.writeUTF (id);
|
out.writeUTF (id);
|
||||||
out.writeUTF (name);
|
out.writeUTF (name);
|
||||||
out.writeObject (parentID);
|
out.writeObject (parentHandle);
|
||||||
out.writeLong (created);
|
out.writeLong (created);
|
||||||
out.writeLong (lastmodified);
|
out.writeLong (lastmodified);
|
||||||
DbMapping smap = dbmap == null ? null : dbmap.getSubnodeMapping ();
|
DbMapping smap = dbmap == null ? null : dbmap.getSubnodeMapping ();
|
||||||
|
@ -93,12 +97,18 @@ public class Node implements INode, Serializable {
|
||||||
out.writeObject (prototype);
|
out.writeObject (prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
transient String prototype;
|
private transient String prototype;
|
||||||
transient INode cacheNode;
|
|
||||||
|
private transient NodeHandle handle;
|
||||||
|
|
||||||
|
private transient INode cacheNode;
|
||||||
|
|
||||||
transient WrappedNodeManager nmgr;
|
transient WrappedNodeManager nmgr;
|
||||||
|
|
||||||
transient DbMapping dbmap;
|
transient DbMapping dbmap;
|
||||||
|
|
||||||
transient Key primaryKey = null;
|
transient Key primaryKey = null;
|
||||||
transient DbMapping parentmap;
|
|
||||||
transient String subnodeRelation = null;
|
transient String subnodeRelation = null;
|
||||||
transient long lastSubnodeFetch = 0;
|
transient long lastSubnodeFetch = 0;
|
||||||
transient long lastSubnodeChange = 0;
|
transient long lastSubnodeChange = 0;
|
||||||
|
@ -117,12 +127,27 @@ public class Node implements INode, Serializable {
|
||||||
static final long serialVersionUID = -3740339688506633675L;
|
static final long serialVersionUID = -3740339688506633675L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor is only used for instances of the NullNode subclass. Do not use for ordinary Nodes!
|
* This constructor is only used for instances of the NullNode subclass. Do not use for ordinary Nodes!<
|
||||||
*/
|
*/
|
||||||
public Node () {
|
Node () {
|
||||||
created = lastmodified = System.currentTimeMillis ();
|
created = lastmodified = System.currentTimeMillis ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Node with the given name. Only used by NodeManager for "root nodes" and
|
||||||
|
* not in a Transaction context, which is why we can immediately mark it as CLEAN.
|
||||||
|
*/
|
||||||
|
protected Node (String name, String id, String prototype, WrappedNodeManager nmgr) {
|
||||||
|
this.nmgr = nmgr;
|
||||||
|
this.id = id;
|
||||||
|
this.name = name == null || "".equals (name) ? id : name;
|
||||||
|
if (prototype != null)
|
||||||
|
setPrototype (prototype);
|
||||||
|
created = lastmodified = System.currentTimeMillis ();
|
||||||
|
markAs (CLEAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor used for virtual nodes.
|
* Constructor used for virtual nodes.
|
||||||
*/
|
*/
|
||||||
|
@ -131,18 +156,38 @@ public class Node implements INode, Serializable {
|
||||||
setParent (home);
|
setParent (home);
|
||||||
// this.dbmap = null;
|
// this.dbmap = null;
|
||||||
// generate a key for the virtual node that can't be mistaken for a JDBC-URL
|
// generate a key for the virtual node that can't be mistaken for a JDBC-URL
|
||||||
this.id = Key.makeVirtualID (parentmap, parentID, propname);
|
primaryKey = new SyntheticKey (home.getKey (), propname);
|
||||||
|
this.id = primaryKey.getID ();
|
||||||
this.name = propname;
|
this.name = propname;
|
||||||
this.anonymous = false;
|
this.anonymous = false;
|
||||||
setPrototype (prototype);
|
setPrototype (prototype);
|
||||||
this.state = VIRTUAL;
|
this.state = VIRTUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Node with the given name. This is used for ordinary transient nodes.
|
||||||
|
*/
|
||||||
|
public Node (String n, String prototype, WrappedNodeManager nmgr) {
|
||||||
|
this.nmgr = nmgr;
|
||||||
|
this.prototype = prototype;
|
||||||
|
dbmap = nmgr.getDbMapping (prototype);
|
||||||
|
// the id is only generated when the node is actually checked into db.
|
||||||
|
// id = nmgr.generateID (dbmap);
|
||||||
|
// checkWriteLock ();
|
||||||
|
this.name = n == null ? "" : n;
|
||||||
|
created = lastmodified = System.currentTimeMillis ();
|
||||||
|
adoptName = true;
|
||||||
|
state = TRANSIENT;
|
||||||
|
// markAs (TRANSIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor used for nodes being stored in a relational database table.
|
* Constructor used for nodes being stored in a relational database table.
|
||||||
*/
|
*/
|
||||||
public Node (DbMapping dbmap, Record rec, WrappedNodeManager nmgr) throws DataSetException {
|
public Node (DbMapping dbmap, Record rec, WrappedNodeManager nmgr) throws DataSetException {
|
||||||
|
|
||||||
|
this.nmgr = nmgr;
|
||||||
// see what prototype/DbMapping this object should use
|
// see what prototype/DbMapping this object should use
|
||||||
DbMapping m = dbmap;
|
DbMapping m = dbmap;
|
||||||
String protoField= dbmap.getPrototypeField ();
|
String protoField= dbmap.getPrototypeField ();
|
||||||
|
@ -161,7 +206,6 @@ public class Node implements INode, Serializable {
|
||||||
setPrototype (m.getTypeName ());
|
setPrototype (m.getTypeName ());
|
||||||
this.dbmap = m;
|
this.dbmap = m;
|
||||||
|
|
||||||
this.nmgr = nmgr;
|
|
||||||
id = rec.getValue (dbmap.getIDField ()).asString ();
|
id = rec.getValue (dbmap.getIDField ()).asString ();
|
||||||
checkWriteLock ();
|
checkWriteLock ();
|
||||||
String nameField = dbmap.getNameField ();
|
String nameField = dbmap.getNameField ();
|
||||||
|
@ -170,8 +214,7 @@ public class Node implements INode, Serializable {
|
||||||
name = m.getTypeName() + " " + id;
|
name = m.getTypeName() + " " + id;
|
||||||
// set parent for user objects to internal userroot node
|
// set parent for user objects to internal userroot node
|
||||||
if ("user".equals (prototype)) {
|
if ("user".equals (prototype)) {
|
||||||
this.parentID = "1";
|
parentHandle = new NodeHandle (new DbKey (null, "1"));
|
||||||
this.parentmap = nmgr.getDbMapping("__userroot__");
|
|
||||||
anonymous = false;
|
anonymous = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +298,7 @@ public class Node implements INode, Serializable {
|
||||||
|
|
||||||
// if the property is a pointer to another node, change the property type to NODE
|
// if the property is a pointer to another node, change the property type to NODE
|
||||||
if (rel.direction == Relation.FORWARD) {
|
if (rel.direction == Relation.FORWARD) {
|
||||||
newprop.nvalueID = newprop.getStringValue ();
|
newprop.nhandle = new NodeHandle (new DbKey (rel.other, newprop.getStringValue ()));
|
||||||
newprop.type = IProperty.NODE;
|
newprop.type = IProperty.NODE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,93 +306,6 @@ public class Node implements INode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Node with the given name.
|
|
||||||
*/
|
|
||||||
public Node (String n, String prototype, WrappedNodeManager nmgr) {
|
|
||||||
this.nmgr = nmgr;
|
|
||||||
this.prototype = prototype;
|
|
||||||
dbmap = nmgr.getDbMapping (prototype);
|
|
||||||
id = nmgr.generateID (dbmap);
|
|
||||||
// checkWriteLock ();
|
|
||||||
this.name = n == null || "".equals (n) ? id : n;
|
|
||||||
created = lastmodified = System.currentTimeMillis ();
|
|
||||||
adoptName = true;
|
|
||||||
markAs (TRANSIENT);
|
|
||||||
// nmgr.registerNode (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Node with the given name. Only used by NodeManager for "root nodes" and
|
|
||||||
* not in a Transaction context, which is why we can immediately mark it as CLEAN.
|
|
||||||
*/
|
|
||||||
protected Node (String name, String id, String prototype, WrappedNodeManager nmgr) {
|
|
||||||
this.nmgr = nmgr;
|
|
||||||
this.id = id;
|
|
||||||
this.name = name == null || "".equals (name) ? id : name;
|
|
||||||
if (prototype != null)
|
|
||||||
setPrototype (prototype);
|
|
||||||
created = lastmodified = System.currentTimeMillis ();
|
|
||||||
markAs (CLEAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of Node, transforming from another implementation of
|
|
||||||
* interface INode. This Constructor is used when a transient
|
|
||||||
* node is converted into a persistent-capable one, hence the status is set to NEW.
|
|
||||||
*/
|
|
||||||
/* private Node (INode node, Hashtable ntable, boolean conversionRoot, WrappedNodeManager nmgr) {
|
|
||||||
this.nmgr = nmgr;
|
|
||||||
this.dbmap = node.getDbMapping ();
|
|
||||||
this.id = nmgr.generateID (dbmap);
|
|
||||||
checkWriteLock ();
|
|
||||||
this.name = node.getName ();
|
|
||||||
this.prototype = node.getPrototype ();
|
|
||||||
created = lastmodified = System.currentTimeMillis ();
|
|
||||||
ntable.put (node, this);
|
|
||||||
// only take over name from property if this is not the root of the current node conversion
|
|
||||||
adoptName = !conversionRoot;
|
|
||||||
for (Enumeration e = node.getSubnodes (); e.hasMoreElements (); ) {
|
|
||||||
INode next = (INode) e.nextElement ();
|
|
||||||
Node nextc = (next instanceof Node) ? (Node) next : (Node) ntable.get (next); // is this a Node already?
|
|
||||||
if (nextc == null)
|
|
||||||
nextc = new Node (next, ntable, true, nmgr);
|
|
||||||
if (nextc.state == INVALID)
|
|
||||||
nextc = nmgr.getNode (nextc.getID (), nextc.getDbMapping ());
|
|
||||||
addNode (nextc);
|
|
||||||
}
|
|
||||||
for (Enumeration e = node.properties (); e.hasMoreElements (); ) {
|
|
||||||
IProperty next = node.get ((String) e.nextElement (), false);
|
|
||||||
if (next == null)
|
|
||||||
continue;
|
|
||||||
int t = next.getType ();
|
|
||||||
if (t == IProperty.NODE) {
|
|
||||||
INode n = next.getNodeValue ();
|
|
||||||
Node nextc = (n instanceof Node) ? (Node) n : (Node) ntable.get (n); // is this a Node already?
|
|
||||||
if (nextc == null)
|
|
||||||
nextc = new Node (n, ntable, true, nmgr);
|
|
||||||
if (nextc.state == INVALID)
|
|
||||||
nextc = nmgr.getNode (nextc.getID (), nextc.getDbMapping ());
|
|
||||||
setNode (next.getName (), nextc);
|
|
||||||
} else if (t == IProperty.STRING) {
|
|
||||||
setString (next.getName (), next.getStringValue ());
|
|
||||||
} else if (t == IProperty.INTEGER) {
|
|
||||||
setInteger (next.getName (), next.getIntegerValue ());
|
|
||||||
} else if (t == IProperty.FLOAT) {
|
|
||||||
setFloat (next.getName (), next.getFloatValue ());
|
|
||||||
} else if (t == IProperty.BOOLEAN) {
|
|
||||||
setBoolean (next.getName (), next.getBooleanValue ());
|
|
||||||
} else if (t == IProperty.DATE) {
|
|
||||||
setDate (next.getName (), next.getDateValue ());
|
|
||||||
} else if (t == IProperty.JAVAOBJECT) {
|
|
||||||
setJavaObject (next.getName (), next.getJavaObjectValue ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adoptName = true; // switch back to normal name adoption behaviour
|
|
||||||
markAs (NEW);
|
|
||||||
// nmgr.registerNode (this);
|
|
||||||
} */
|
|
||||||
|
|
||||||
protected synchronized void checkWriteLock () {
|
protected synchronized void checkWriteLock () {
|
||||||
// System.err.println ("registering writelock for "+this.getName ()+" ("+lock+") to "+Thread.currentThread ());
|
// System.err.println ("registering writelock for "+this.getName ()+" ("+lock+") to "+Thread.currentThread ());
|
||||||
|
@ -422,6 +378,8 @@ public class Node implements INode, Serializable {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public String getID () {
|
public String getID () {
|
||||||
|
if (state == TRANSIENT)
|
||||||
|
throw new RuntimeException ("getID called on transient Node: "+this);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,12 +403,14 @@ public class Node implements INode, Serializable {
|
||||||
public String getNameOrID () {
|
public String getNameOrID () {
|
||||||
// if subnodes are also mounted as properties, try to get the "nice" prop value
|
// if subnodes are also mounted as properties, try to get the "nice" prop value
|
||||||
// instead of the id by turning the anonymous flag off.
|
// instead of the id by turning the anonymous flag off.
|
||||||
// HACK: work around this for user objects to alsways return a URL like /users/username
|
// Work around this for user objects to alsways return a URL like /users/username
|
||||||
if ("user".equalsIgnoreCase (prototype)) {
|
if ("user".equalsIgnoreCase (prototype)) {
|
||||||
anonymous = false;
|
anonymous = false;
|
||||||
} else if (parentmap != null) {
|
} else if (parentHandle != null) {
|
||||||
|
try {
|
||||||
|
DbMapping parentmap = parentHandle.getDbMapping (nmgr);
|
||||||
Relation prel = parentmap.getPropertyRelation();
|
Relation prel = parentmap.getPropertyRelation();
|
||||||
if (prel != null && prel.subnodesAreProperties && !prel.usesPrimaryKey ()) try {
|
if (prel != null && prel.subnodesAreProperties && !prel.usesPrimaryKey ()) {
|
||||||
Relation localrel = dbmap.columnNameToProperty (prel.getRemoteField ());
|
Relation localrel = dbmap.columnNameToProperty (prel.getRemoteField ());
|
||||||
String propvalue = getString (localrel.propname, false);
|
String propvalue = getString (localrel.propname, false);
|
||||||
if (propvalue != null && propvalue.length() > 0) {
|
if (propvalue != null && propvalue.length() > 0) {
|
||||||
|
@ -460,6 +420,7 @@ public class Node implements INode, Serializable {
|
||||||
} else {
|
} else {
|
||||||
anonymous = true;
|
anonymous = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
// just fall back to default method
|
// just fall back to default method
|
||||||
}
|
}
|
||||||
|
@ -533,10 +494,7 @@ public class Node implements INode, Serializable {
|
||||||
public void setDbMapping (DbMapping dbmap) {
|
public void setDbMapping (DbMapping dbmap) {
|
||||||
if (this.dbmap != dbmap) {
|
if (this.dbmap != dbmap) {
|
||||||
this.dbmap = dbmap;
|
this.dbmap = dbmap;
|
||||||
primaryKey = null;
|
// primaryKey = null;
|
||||||
try {
|
|
||||||
((Transactor) Thread.currentThread()).visitCleanNode (this);
|
|
||||||
} catch (ClassCastException ignore) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,13 +503,21 @@ public class Node implements INode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Key getKey () {
|
public Key getKey () {
|
||||||
|
if (state == TRANSIENT)
|
||||||
|
throw new RuntimeException ("getKey called on transient Node: "+this);
|
||||||
if (dbmap == null && prototype != null && nmgr != null)
|
if (dbmap == null && prototype != null && nmgr != null)
|
||||||
dbmap = nmgr.getDbMapping (prototype);
|
dbmap = nmgr.getDbMapping (prototype);
|
||||||
if (primaryKey == null)
|
if (primaryKey == null)
|
||||||
primaryKey = new Key (dbmap, id);
|
primaryKey = new DbKey (dbmap, id);
|
||||||
return primaryKey;
|
return primaryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NodeHandle getHandle () {
|
||||||
|
if (handle == null)
|
||||||
|
handle = new NodeHandle (this);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
public void setSubnodeRelation (String rel) {
|
public void setSubnodeRelation (String rel) {
|
||||||
if ((rel == null && this.subnodeRelation == null)
|
if ((rel == null && this.subnodeRelation == null)
|
||||||
|| (rel != null && rel.equalsIgnoreCase (this.subnodeRelation)))
|
|| (rel != null && rel.equalsIgnoreCase (this.subnodeRelation)))
|
||||||
|
@ -584,8 +550,7 @@ public class Node implements INode, Serializable {
|
||||||
* the ID + DB map combo.
|
* the ID + DB map combo.
|
||||||
*/
|
*/
|
||||||
public void setParent (Node parent) {
|
public void setParent (Node parent) {
|
||||||
this.parentID = parent == null ? null : parent.getID();
|
parentHandle = parent == null ? null : parent.getHandle ();
|
||||||
this.parentmap = parent == null ? null : parent.getDbMapping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -595,21 +560,21 @@ public class Node implements INode, Serializable {
|
||||||
*/
|
*/
|
||||||
public void setParent (Node parent, String propertyName) {
|
public void setParent (Node parent, String propertyName) {
|
||||||
// we only do that for relational nodes.
|
// we only do that for relational nodes.
|
||||||
if (dbmap == null || !dbmap.isRelational ())
|
if (!isRelational ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String oldParentID = parentID;
|
NodeHandle oldParentHandle = parentHandle;
|
||||||
parentID = parent == null ? null : parent.getID();
|
parentHandle = parent == null ? null : parent.getHandle ();
|
||||||
parentmap = parent == null ? null : parent.getDbMapping();
|
|
||||||
|
|
||||||
if (parentID == null || parentID.equals (oldParentID))
|
if (parentHandle == null || parentHandle.equals (oldParentHandle))
|
||||||
// nothing changed, no need to find access property
|
// nothing changed, no need to find access property
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (propertyName == null) {
|
if (parent != null && propertyName == null) {
|
||||||
// see if we can find out the propertyName by ourselfes by looking at the
|
// see if we can find out the propertyName by ourselfes by looking at the
|
||||||
// parent's property relation
|
// parent's property relation
|
||||||
String newname = null;
|
String newname = null;
|
||||||
|
DbMapping parentmap = parent.getDbMapping ();
|
||||||
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 ();
|
||||||
|
@ -645,8 +610,7 @@ public class Node implements INode, Serializable {
|
||||||
|
|
||||||
// check what's specified in the type.properties for this node.
|
// check what's specified in the type.properties for this node.
|
||||||
ParentInfo[] parentInfo = null;
|
ParentInfo[] parentInfo = null;
|
||||||
if (dbmap != null && dbmap.isRelational () &&
|
if (isRelational () && (lastParentSet < dbmap.getLastTypeChange() || lastParentSet < lastmodified))
|
||||||
(lastParentSet < dbmap.getLastTypeChange() || lastParentSet < lastmodified))
|
|
||||||
parentInfo = dbmap.getParentInfo ();
|
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 it
|
||||||
|
@ -679,10 +643,9 @@ public class Node implements INode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fall back to heuristic parent (the node that fetched this one from db)
|
// fall back to heuristic parent (the node that fetched this one from db)
|
||||||
if (parentID == null) {
|
if (parentHandle == null)
|
||||||
return null;
|
return null;
|
||||||
}
|
return parentHandle.getNode (nmgr);
|
||||||
return nmgr.getNode (parentID, parentmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -690,9 +653,9 @@ public class Node implements INode, Serializable {
|
||||||
* Get parent, using cached info if it exists.
|
* Get parent, using cached info if it exists.
|
||||||
*/
|
*/
|
||||||
public Node getCachedParent () {
|
public Node getCachedParent () {
|
||||||
if (parentID == null)
|
if (parentHandle == null)
|
||||||
return null;
|
return null;
|
||||||
return nmgr.getNode (parentID, parentmap);
|
return parentHandle.getNode (nmgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -758,22 +721,17 @@ public class Node implements INode, Serializable {
|
||||||
|
|
||||||
if (where < 0 || where > numberOfNodes ())
|
if (where < 0 || where > numberOfNodes ())
|
||||||
where = numberOfNodes ();
|
where = numberOfNodes ();
|
||||||
if (node.parentID != null) {
|
|
||||||
// this makes the job of addLink, which means that addLink and addNode
|
|
||||||
// are functionally equivalent now.
|
|
||||||
if (!node.parentID.equals (id) || !node.anonymous) {
|
|
||||||
node.registerLink (this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subnodes != null && subnodes.contains (node.getID ())) {
|
NodeHandle nhandle = node.getHandle ();
|
||||||
|
if (subnodes != null && subnodes.contains (nhandle)) {
|
||||||
// Node is already subnode of this - just move to new position
|
// Node is already subnode of this - just move to new position
|
||||||
subnodes.remove (node.getID ());
|
subnodes.remove (nhandle);
|
||||||
where = Math.min (where, numberOfNodes ());
|
where = Math.min (where, numberOfNodes ());
|
||||||
subnodes.add (where, node.getID ());
|
subnodes.add (where, nhandle);
|
||||||
} else {
|
} else {
|
||||||
if (subnodes == null) subnodes = new ExternalizableVector ();
|
if (subnodes == null)
|
||||||
subnodes.add (where, node.getID ());
|
subnodes = new ExternalizableVector ();
|
||||||
|
subnodes.add (where, nhandle);
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -795,9 +753,19 @@ public class Node implements INode, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.parentID == null && !"root".equalsIgnoreCase (node.getPrototype ())) {
|
if (!"root".equalsIgnoreCase (node.getPrototype ())) {
|
||||||
|
Node nparent = (Node) node.getParent ();
|
||||||
|
// if the node doesn't have a parent yet, or it has one but it's transient while we are
|
||||||
|
// persistent, make this the nodes new parent.
|
||||||
|
if (nparent == null || (state != TRANSIENT && nparent.getState () == TRANSIENT)) {
|
||||||
node.setParent (this);
|
node.setParent (this);
|
||||||
node.anonymous = true;
|
node.anonymous = true;
|
||||||
|
} else if (nparent != null && (nparent != this || !node.anonymous)) {
|
||||||
|
// this makes the additional job of addLink, registering that we have a link to a node in our
|
||||||
|
// subnodes that actually sits somewhere else. This means that addLink and addNode
|
||||||
|
// are actually the same now.
|
||||||
|
node.registerLinkFrom (this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,14 +824,18 @@ public class Node implements INode, Serializable {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* register a node that links to this node.
|
* register a node that links to this node so we can notify it when we cease to exist.
|
||||||
|
* this is only necessary if we are a non-relational node, since for relational nodes
|
||||||
|
* the referring object will notice that we've gone at runtime.
|
||||||
*/
|
*/
|
||||||
protected void registerLink (Node from) {
|
protected void registerLinkFrom (Node from) {
|
||||||
|
if (isRelational ())
|
||||||
|
return;
|
||||||
if (links == null)
|
if (links == null)
|
||||||
links = new ExternalizableVector ();
|
links = new ExternalizableVector ();
|
||||||
Object fromID = from.getID ();
|
Object fromHandle = from.getHandle ();
|
||||||
if (!links.contains (fromID))
|
if (!links.contains (fromHandle))
|
||||||
links.add (fromID);
|
links.add (fromHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public INode getSubnode (String path) {
|
public INode getSubnode (String path) {
|
||||||
|
@ -878,25 +850,28 @@ public class Node implements INode, Serializable {
|
||||||
retval = this;
|
retval = this;
|
||||||
} else {
|
} else {
|
||||||
runner.loadNodes ();
|
runner.loadNodes ();
|
||||||
boolean found = runner.subnodes == null ? false : runner.subnodes.contains (next);
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
retval = null;
|
|
||||||
else {
|
|
||||||
Relation srel = null;
|
Relation srel = null;
|
||||||
DbMapping smap = null;
|
DbMapping smap = null;
|
||||||
if (runner.dbmap != null) {
|
if (runner.dbmap != null) {
|
||||||
srel = runner.dbmap.getSubnodeRelation ();
|
srel = runner.dbmap.getSubnodeRelation ();
|
||||||
smap = runner.dbmap.getSubnodeMapping ();
|
smap = runner.dbmap.getSubnodeMapping ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if there is a group-by relation
|
// check if there is a group-by relation
|
||||||
|
NodeHandle nhandle = null;
|
||||||
if (srel != null && srel.groupby != null)
|
if (srel != null && srel.groupby != null)
|
||||||
retval = nmgr.getNode (this, next, srel);
|
nhandle = new NodeHandle (new SyntheticKey (runner.getKey (), next));
|
||||||
else
|
else
|
||||||
retval = nmgr.getNode (next, smap);
|
nhandle = new NodeHandle (new DbKey (smap, next));
|
||||||
|
boolean found = runner.subnodes == null ? false : runner.subnodes.contains (nhandle);
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
retval = null;
|
||||||
|
} else {
|
||||||
|
retval = nhandle.getNode (nmgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval != null && retval.parentID == null && !"root".equalsIgnoreCase (retval.getPrototype ())) {
|
if (retval != null && retval.parentHandle == null && !"root".equalsIgnoreCase (retval.getPrototype ())) {
|
||||||
retval.setParent (runner);
|
retval.setParent (runner);
|
||||||
retval.anonymous = true;
|
retval.anonymous = true;
|
||||||
}
|
}
|
||||||
|
@ -914,20 +889,16 @@ public class Node implements INode, Serializable {
|
||||||
if (subnodes == null)
|
if (subnodes == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Relation srel = null;
|
|
||||||
DbMapping smap = null;
|
DbMapping smap = null;
|
||||||
if (dbmap != null) {
|
if (dbmap != null)
|
||||||
srel = dbmap.getSubnodeRelation ();
|
|
||||||
smap = dbmap.getSubnodeMapping ();
|
smap = dbmap.getSubnodeMapping ();
|
||||||
}
|
|
||||||
Node retval = null;
|
Node retval = null;
|
||||||
if (subnodes.size () > index) {
|
if (subnodes.size () > index) {
|
||||||
// check if there is a group-by relation
|
// check if there is a group-by relation
|
||||||
if (srel != null && srel.groupby != null)
|
retval = ((NodeHandle) subnodes.get (index)).getNode (nmgr);
|
||||||
retval = nmgr.getNode (this, (String) subnodes.get (index), srel);
|
|
||||||
else
|
if (retval != null && retval.parentHandle == null && !"root".equalsIgnoreCase (retval.getPrototype ())) {
|
||||||
retval = nmgr.getNode ((String) subnodes.get (index), smap);
|
|
||||||
if (retval != null && retval.parentID == null && !"root".equalsIgnoreCase (retval.getPrototype ())) {
|
|
||||||
retval.setParent (this);
|
retval.setParent (this);
|
||||||
retval.anonymous = true;
|
retval.anonymous = true;
|
||||||
}
|
}
|
||||||
|
@ -940,7 +911,8 @@ public class Node implements INode, Serializable {
|
||||||
if (subnodes == null)
|
if (subnodes == null)
|
||||||
subnodes = new ExternalizableVector ();
|
subnodes = new ExternalizableVector ();
|
||||||
|
|
||||||
if (subnodes.contains (sid) || create) try {
|
NodeHandle ghandle = new NodeHandle (new SyntheticKey (getKey(), sid));
|
||||||
|
if (subnodes.contains (ghandle) || create) try {
|
||||||
Relation srel = dbmap.getSubnodeRelation ();
|
Relation srel = dbmap.getSubnodeRelation ();
|
||||||
Relation prel = dbmap.getPropertyRelation ();
|
Relation prel = dbmap.getPropertyRelation ();
|
||||||
boolean relational = srel.other != null && srel.other.isRelational ();
|
boolean relational = srel.other != null && srel.other.isRelational ();
|
||||||
|
@ -976,7 +948,7 @@ public class Node implements INode, Serializable {
|
||||||
node.setPrototype (gsrel.prototype);
|
node.setPrototype (gsrel.prototype);
|
||||||
} else {
|
} else {
|
||||||
setNode (sid, node);
|
setNode (sid, node);
|
||||||
subnodes.add (node.getID ());
|
subnodes.add (node.getHandle ());
|
||||||
}
|
}
|
||||||
nmgr.evictKey (node.getKey ());
|
nmgr.evictKey (node.getKey ());
|
||||||
return node;
|
return node;
|
||||||
|
@ -1014,7 +986,7 @@ public class Node implements INode, Serializable {
|
||||||
} else {
|
} else {
|
||||||
// removed just a link, not the main node.
|
// removed just a link, not the main node.
|
||||||
if (n.links != null) {
|
if (n.links != null) {
|
||||||
n.links.remove (this.id);
|
n.links.remove (getHandle ());
|
||||||
if (n.state == CLEAN) n.markAs (MODIFIED);
|
if (n.state == CLEAN) n.markAs (MODIFIED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1026,7 +998,7 @@ public class Node implements INode, Serializable {
|
||||||
*/
|
*/
|
||||||
protected void releaseNode (Node node) {
|
protected void releaseNode (Node node) {
|
||||||
if (subnodes != null)
|
if (subnodes != null)
|
||||||
subnodes.remove (node.getID ());
|
subnodes.remove (node.getHandle ());
|
||||||
|
|
||||||
lastSubnodeChange = System.currentTimeMillis ();
|
lastSubnodeChange = System.currentTimeMillis ();
|
||||||
|
|
||||||
|
@ -1041,7 +1013,7 @@ public class Node implements INode, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if subnodes are handled as virtual fs
|
// 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.subnodesAreProperties && !prel.usesPrimaryKey ()) {
|
if (prel != null && prel.subnodesAreProperties && !prel.usesPrimaryKey ()) {
|
||||||
|
@ -1072,22 +1044,22 @@ public class Node implements INode, Serializable {
|
||||||
*/
|
*/
|
||||||
protected void deepRemoveNode () {
|
protected void deepRemoveNode () {
|
||||||
|
|
||||||
// notify nodes that link to this node that it is being deleted.
|
// notify nodes that link to this node being deleted.
|
||||||
int l = links == null ? 0 : links.size ();
|
int l = links == null ? 0 : links.size ();
|
||||||
for (int i = 0; i < l; i++) {
|
for (int i = 0; i < l; i++) {
|
||||||
// TODO: solve dbmap problem
|
NodeHandle lhandle = (NodeHandle) links.get (i);
|
||||||
Node link = nmgr.getNode ((String) links.get (i), null);
|
Node link = lhandle.getNode (nmgr);
|
||||||
if (link != null) link.releaseNode (this);
|
if (link != null)
|
||||||
|
link.releaseNode (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up all nodes that use n as a property
|
// clean up all nodes that refer to this as a property
|
||||||
if (proplinks != null) {
|
if (proplinks != null) {
|
||||||
for (Iterator e1 = proplinks.iterator (); e1.hasNext (); ) try {
|
for (Iterator e1 = proplinks.iterator (); e1.hasNext (); ) try {
|
||||||
String pid = (String) e1.next ();
|
NodeHandle phandle = (NodeHandle) e1.next ();
|
||||||
Node pnode = nmgr.getNode (pid, null);
|
Node pnode = phandle.getNode (nmgr);
|
||||||
if (pnode != null) {
|
if (pnode != null)
|
||||||
nmgr.logEvent("Warning: Not unsetting node property of "+pnode.getFullName ());
|
nmgr.logEvent("Warning: Not unsetting node property of "+pnode.getName ());
|
||||||
}
|
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,7 +1085,7 @@ public class Node implements INode, Serializable {
|
||||||
// getParent() is heuristical/implicit for relational nodes, so we don't base
|
// getParent() is heuristical/implicit for relational nodes, so we don't base
|
||||||
// a cascading delete on that criterium for relational nodes.
|
// a cascading delete on that criterium for relational nodes.
|
||||||
Node n = (Node) v.get (i);
|
Node n = (Node) v.get (i);
|
||||||
if (n.dbmap == null || !n.dbmap.isRelational())
|
if (!n.isRelational())
|
||||||
removeNode (n);
|
removeNode (n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1130,14 +1102,18 @@ public class Node implements INode, Serializable {
|
||||||
if (subnodes == null)
|
if (subnodes == null)
|
||||||
return -1;
|
return -1;
|
||||||
// if the node contains relational groupby subnodes, the subnodes vector contains the names instead of ids.
|
// if the node contains relational groupby subnodes, the subnodes vector contains the names instead of ids.
|
||||||
Relation srel = dbmap == null ? null : dbmap.getSubnodeRelation ();
|
/* Relation srel = dbmap == null ? null : dbmap.getSubnodeRelation ();
|
||||||
if (srel != null && srel.groupby != null && srel.other != null && srel.other.isRelational ()) {
|
if (srel != null && srel.groupby != null && srel.other != null && srel.other.isRelational ()) {
|
||||||
if (n.getParent () != this)
|
if (n.getParent () != this)
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
return subnodes.indexOf (n.getName ());
|
return subnodes.indexOf (new SyntheticKey (getKey (), n.getID ());
|
||||||
} else
|
} else
|
||||||
return subnodes.indexOf (n.getID ());
|
return subnodes.indexOf (n.getKey ());*/
|
||||||
|
if (!(n instanceof Node))
|
||||||
|
return -1;
|
||||||
|
Node node = (Node) n;
|
||||||
|
return subnodes.indexOf (node.getHandle ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1251,7 +1227,7 @@ public class Node implements INode, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParentInfo () {
|
public String getParentInfo () {
|
||||||
return "anonymous:"+anonymous+",parentID:"+parentID+",parentmap:"+parentmap+",parent:"+getParent();
|
return "anonymous:"+anonymous+",parentHandle"+parentHandle+",parent:"+getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Property getProperty (String propname, boolean inherit) {
|
protected Property getProperty (String propname, boolean inherit) {
|
||||||
|
@ -1265,21 +1241,30 @@ public class Node implements INode, Serializable {
|
||||||
DbMapping pmap = dbmap == null ? null : dbmap.getExactPropertyMapping (propname);
|
DbMapping pmap = dbmap == null ? null : dbmap.getExactPropertyMapping (propname);
|
||||||
if (pmap != null && prop != null && prop.type != IProperty.NODE) {
|
if (pmap != null && prop != null && prop.type != IProperty.NODE) {
|
||||||
// this is a relational node stored by id but we still think it's just a string. fix it
|
// this is a relational node stored by id but we still think it's just a string. fix it
|
||||||
prop.nvalueID = prop.getStringValue ();
|
prop.nhandle = new NodeHandle (new DbKey (pmap, prop.getStringValue ()));
|
||||||
prop.type = IProperty.NODE;
|
prop.type = IProperty.NODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the property does not exist in our propmap - see if we can create it on the fly,
|
||||||
|
// either because it is mapped from a relational database or defined as virtual node
|
||||||
if (prop == null && dbmap != null) {
|
if (prop == null && dbmap != null) {
|
||||||
Relation prel = dbmap.getPropertyRelation (propname);
|
Relation prel = dbmap.getPropertyRelation (propname);
|
||||||
|
/* if (prel != null && prel.virtual && prel.other != null && !prel.other.isRelational ()) {
|
||||||
|
Node pn = (Node) createNode (propname);
|
||||||
|
if (prel.prototype != null) {
|
||||||
|
pn.setPrototype (prel.prototype);
|
||||||
|
}
|
||||||
|
prop = (Property) propMap.get (propname);
|
||||||
|
|
||||||
|
} else { */
|
||||||
if (prel == null)
|
if (prel == null)
|
||||||
prel = dbmap.getPropertyRelation ();
|
prel = dbmap.getPropertyRelation ();
|
||||||
if (prel != null && (prel.direction == Relation.DIRECT || prel.virtual)) {
|
if (prel != null && (prel.direction == Relation.DIRECT || prel.virtual)) {
|
||||||
// this *may* be a relational node stored by property name
|
// this may be a relational node stored by property name
|
||||||
try {
|
try {
|
||||||
Node pn = nmgr.getNode (this, propname, prel);
|
Node pn = nmgr.getNode (this, propname, prel);
|
||||||
if (pn != null) {
|
if (pn != null) {
|
||||||
if (pn.parentID == null && !"root".equalsIgnoreCase (pn.getPrototype ())) {
|
if (pn.parentHandle == null && !"root".equalsIgnoreCase (pn.getPrototype ())) {
|
||||||
pn.setParent (this);
|
pn.setParent (this);
|
||||||
pn.name = propname;
|
pn.name = propname;
|
||||||
pn.anonymous = false;
|
pn.anonymous = false;
|
||||||
|
@ -1290,6 +1275,7 @@ public class Node implements INode, Serializable {
|
||||||
// wasn't a node after all
|
// wasn't a node after all
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
if (prop == null && inherit && getParent () != null) {
|
if (prop == null && inherit && getParent () != null) {
|
||||||
prop = ((Node) getParent ()).getProperty (propname, inherit);
|
prop = ((Node) getParent ()).getProperty (propname, inherit);
|
||||||
|
@ -1393,12 +1379,12 @@ public class Node implements INode, Serializable {
|
||||||
|
|
||||||
// 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 subnodesAreProperties
|
||||||
// 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
|
||||||
INode parent = parentID == null ? null : getParent ();
|
INode parent = parentHandle == null ? null : getParent ();
|
||||||
|
|
||||||
if (parent != null && parent.getDbMapping() != null) {
|
if (parent != null && parent.getDbMapping() != null) {
|
||||||
// check if this node is already registered with the old name; if so, remove it.
|
// 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
|
// then set parent's property to this node for the new name value
|
||||||
parentmap = parent.getDbMapping ();
|
DbMapping parentmap = parent.getDbMapping ();
|
||||||
Relation prel = parentmap.getPropertyRelation ();
|
Relation prel = parentmap.getPropertyRelation ();
|
||||||
|
|
||||||
if (prel != null && prel.subnodesAreProperties && propname.equals (prel.getRemoteField())) {
|
if (prel != null && prel.subnodesAreProperties && propname.equals (prel.getRemoteField())) {
|
||||||
|
@ -1414,7 +1400,7 @@ public class Node implements INode, Serializable {
|
||||||
parent.unset (oldvalue);
|
parent.unset (oldvalue);
|
||||||
parent.addNode (this);
|
parent.addNode (this);
|
||||||
// let the node cache know this key's not for this node anymore.
|
// let the node cache know this key's not for this node anymore.
|
||||||
nmgr.evictKey (new Key (prel.other, prel.getKeyID (parent, oldvalue)));
|
nmgr.evictKey (new DbKey (prel.other, prel.getKeyID (parent, oldvalue)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parent.setNode (value, this);
|
parent.setNode (value, this);
|
||||||
|
@ -1573,7 +1559,7 @@ public class Node implements INode, Serializable {
|
||||||
|
|
||||||
// check if the main identity of this node is as a named property
|
// check if the main identity of this node is as a named property
|
||||||
// or as an anonymous node in a collection
|
// or as an anonymous node in a collection
|
||||||
if (n.parentID == null && n.adoptName && !"root".equalsIgnoreCase (n.getPrototype ())) {
|
if (n.parentHandle == null && n.adoptName && !"root".equalsIgnoreCase (n.getPrototype ())) {
|
||||||
n.setParent (this);
|
n.setParent (this);
|
||||||
n.name = propname;
|
n.name = propname;
|
||||||
n.anonymous = false;
|
n.anonymous = false;
|
||||||
|
@ -1587,7 +1573,7 @@ public class Node implements INode, Serializable {
|
||||||
|
|
||||||
Property prop = (Property) propMap.get (p2);
|
Property prop = (Property) propMap.get (p2);
|
||||||
if (prop != null) {
|
if (prop != null) {
|
||||||
if (prop.type == IProperty.NODE && n.getID ().equals (prop.nvalueID)) {
|
if (prop.type == IProperty.NODE && n.equals (prop.getNodeValue ())) {
|
||||||
// nothing to do, just clean up locks and return
|
// nothing to do, just clean up locks and return
|
||||||
if (state == CLEAN) clearWriteLock ();
|
if (state == CLEAN) clearWriteLock ();
|
||||||
if (n.state == CLEAN) n.clearWriteLock ();
|
if (n.state == CLEAN) n.clearWriteLock ();
|
||||||
|
@ -1608,10 +1594,10 @@ public class Node implements INode, Serializable {
|
||||||
|
|
||||||
// check node in with transactor cache
|
// check node in with transactor cache
|
||||||
Transactor tx = (Transactor) Thread.currentThread ();
|
Transactor tx = (Transactor) Thread.currentThread ();
|
||||||
tx.visitCleanNode (new Key (nmap, nID), n);
|
tx.visitCleanNode (new DbKey (nmap, nID), 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.direction == Relation.DIRECT && !rel.getKeyID(this, p2).equals (nID)) {
|
if (rel != null && rel.direction == Relation.DIRECT && !rel.getKeyID(this, p2).equals (nID)) {
|
||||||
Key secKey = new Key (rel.other, rel.getKeyID(this, p2));
|
Key secKey = new DbKey (rel.other, rel.getKeyID(this, p2));
|
||||||
nmgr.evictKey (secKey);
|
nmgr.evictKey (secKey);
|
||||||
tx.visitCleanNode (secKey, n);
|
tx.visitCleanNode (secKey, n);
|
||||||
}
|
}
|
||||||
|
@ -1644,21 +1630,21 @@ public class Node implements INode, Serializable {
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerPropLink (INode n) {
|
protected void registerPropLinkFrom (Node n) {
|
||||||
|
if (isRelational ())
|
||||||
|
return;
|
||||||
if (proplinks == null)
|
if (proplinks == null)
|
||||||
proplinks = new ExternalizableVector ();
|
proplinks = new ExternalizableVector ();
|
||||||
String plid = n.getID ();
|
Object fromHandle = n.getHandle ();
|
||||||
if (!proplinks.contains (plid))
|
if (!proplinks.contains (fromHandle))
|
||||||
proplinks.add (n.getID ());
|
proplinks.add (fromHandle);
|
||||||
if (state == CLEAN || state == DELETED)
|
if (state == CLEAN || state == DELETED)
|
||||||
markAs (MODIFIED);
|
markAs (MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void unregisterPropLink (INode n) {
|
protected void unregisterPropLinkFrom (Node n) {
|
||||||
if (proplinks != null)
|
if (proplinks != null)
|
||||||
proplinks.remove (n.getID ());
|
proplinks.remove (n.getHandle ());
|
||||||
// Server.throwNodeEvent (new NodeEvent (this, NodeEvent.NODE_REMOVED));
|
|
||||||
// Server.throwNodeEvent (new NodeEvent (n, NodeEvent.SUBNODE_REMOVED, this));
|
|
||||||
if (state == CLEAN)
|
if (state == CLEAN)
|
||||||
markAs (MODIFIED);
|
markAs (MODIFIED);
|
||||||
}
|
}
|
||||||
|
@ -1716,21 +1702,28 @@ public class Node implements INode, Serializable {
|
||||||
return "HopObject " + name;
|
return "HopObject " + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively convert other implementations of INode into helma.objectmodel.db.Node.
|
* Tell whether this node is stored inside a relational db. This doesn't mean
|
||||||
|
* it actually is stored in a relational db, just that it would be, if the node was
|
||||||
|
* persistent
|
||||||
*/
|
*/
|
||||||
/* protected Node convert (INode n) {
|
public boolean isRelational () {
|
||||||
Hashtable ntable = new Hashtable ();
|
return dbmap != null && dbmap.isRelational ();
|
||||||
Node converted = new Node (n, ntable, false, nmgr);
|
}
|
||||||
return converted;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively turn node status from TRANSIENT to NEW so that the Transactor will
|
* Recursively turn node status from TRANSIENT to NEW so that the Transactor will
|
||||||
* know it has to insert this node.
|
* know it has to insert this node.
|
||||||
*/
|
*/
|
||||||
protected void makePersistentCapable () {
|
protected void makePersistentCapable () {
|
||||||
|
if (state == TRANSIENT) {
|
||||||
|
state = NEW;
|
||||||
|
id = nmgr.generateID (dbmap);
|
||||||
|
Transactor current = (Transactor) Thread.currentThread ();
|
||||||
|
current.visitNode (this);
|
||||||
|
current.visitCleanNode (this);
|
||||||
|
}
|
||||||
for (Enumeration e = getSubnodes (); e.hasMoreElements (); ) {
|
for (Enumeration e = getSubnodes (); e.hasMoreElements (); ) {
|
||||||
Node n = (Node) e.nextElement ();
|
Node n = (Node) e.nextElement ();
|
||||||
if (n.state == TRANSIENT)
|
if (n.state == TRANSIENT)
|
||||||
|
@ -1744,12 +1737,6 @@ public class Node implements INode, Serializable {
|
||||||
n.makePersistentCapable ();
|
n.makePersistentCapable ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state == TRANSIENT) {
|
|
||||||
state = NEW;
|
|
||||||
Transactor current = (Transactor) Thread.currentThread ();
|
|
||||||
current.visitNode (this);
|
|
||||||
current.visitCleanNode (this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1775,8 +1762,11 @@ public class Node implements INode, Serializable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpSubnodes () {
|
public void dump () {
|
||||||
System.err.println (subnodes);
|
System.err.println ("subnodes: "+subnodes);
|
||||||
|
System.err.println ("properties: "+propMap);
|
||||||
|
System.err.println ("links: "+links);
|
||||||
|
System.err.println ("proplinks: "+proplinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue