001: /*
002: * Helma License Notice
003: *
004: * The contents of this file are subject to the Helma License
005: * Version 2.0 (the "License"). You may not use this file except in
006: * compliance with the License. A copy of the License is available at
007: * http://adele.helma.org/download/helma/license.txt
008: *
009: * Copyright 1998-2003 Helma Software. All Rights Reserved.
010: *
011: * $RCSfile$
012: * $Author: root $
013: * $Revision: 8604 $
014: * $Date: 2007-09-28 15:16:38 +0200 (Fre, 28 Sep 2007) $
015: */
016:
017: package helma.objectmodel.db;
018:
019: import helma.objectmodel.INodeState;
020:
021: import java.io.Serializable;
022:
023: /**
024: * This class is a handle or reference to a Node. This is to abstract from different
025: * methods of reference: Transient Nodes are referred to directly, while persistent
026: * nodes are referred to via key/node manager.
027: *
028: * A handle is used to refer to a node in a safe way over a longer period.
029: * While a direct reference may point to a node that has been evicted from the cache
030: * and reinstanciated since being set, NodeHandle will always return an up-to-date
031: * instance of its node.
032: */
033: public final class NodeHandle implements INodeState, Serializable {
034: static final long serialVersionUID = 3067763116576910931L;
035:
036: // direct reference to the node
037: private Node node;
038:
039: // the node's key
040: private Key key;
041:
042: /**
043: * Builds a handle for a node
044: */
045: public NodeHandle(Node node) {
046: int state = node.getState();
047:
048: if (state == TRANSIENT) {
049: this .node = node;
050: key = null;
051: } else {
052: this .node = null;
053: key = node.getKey();
054: }
055: }
056:
057: /**
058: * Builds a handle given a node's retrieval information. At the time this is called,
059: * the node is ususally not yet created. It will be fetched on demand when accessed by
060: * application code.
061: */
062: public NodeHandle(Key key) {
063: this .node = null;
064: this .key = key;
065: }
066:
067: /**
068: * Get the node described by this node handle
069: */
070: public Node getNode(WrappedNodeManager nodemgr) {
071: if (node != null) {
072: return node;
073: }
074:
075: return nodemgr.getNode(key);
076: }
077:
078: /**
079: * Get the key for the node described by this handle.
080: * This may only be called on persistent Nodes.
081: */
082: public Key getKey() {
083: if (key == null) {
084: throw new RuntimeException(
085: "getKey called on transient Node");
086: }
087:
088: return key;
089: }
090:
091: /**
092: * Get the ID for the node described by this handle.
093: * This may only be called on persistent Nodes.
094: */
095: public String getID() {
096: if (key == null) {
097: return node.getID();
098: }
099:
100: return key.getID();
101: }
102:
103: private Object getObject() {
104: if (node != null) {
105: return node;
106: } else {
107: return key;
108: }
109: }
110:
111: /**
112: *
113: *
114: * @param other ...
115: *
116: * @return ...
117: */
118: public boolean equals(Object other) {
119: try {
120: return getObject().equals(((NodeHandle) other).getObject());
121: } catch (Exception x) {
122: return false;
123: }
124: }
125:
126: /**
127: * This is to notify the handle that the underlying node is becoming
128: * persistent and we have to refer to it via the key from now on.
129: */
130: protected void becomePersistent() {
131: if (node != null) {
132: key = node.getKey();
133: node = null;
134: }
135: }
136:
137: /**
138: *
139: *
140: * @return ...
141: */
142: public String toString() {
143: if (node != null) {
144: return "NodeHandle[transient:" + node + "]";
145: } else {
146: return "NodeHandle[" + key + "]";
147: }
148: }
149: }
|