You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2004/12/20 11:29:47 UTC
svn commit: r122838 - in incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: . nodetype version version/persistence virtual
Author: tripod
Date: Mon Dec 20 02:29:45 2004
New Revision: 122838
URL: http://svn.apache.org/viewcvs?view=rev&rev=122838
Log:
- improved versioning
Added:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFreezeImpl.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java (contents, props changed)
Removed:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentNode.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentProperty.java
Modified:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java Mon Dec 20 02:29:45 2004
@@ -20,6 +20,10 @@
import org.apache.jackrabbit.core.nodetype.PropDefId;
import org.apache.jackrabbit.core.nodetype.NodeDefId;
import org.apache.jackrabbit.core.state.*;
+import org.apache.jackrabbit.core.version.InternalVersionHistory;
+import org.apache.jackrabbit.core.version.VersionHistoryImpl;
+import org.apache.jackrabbit.core.version.InternalVersion;
+import org.apache.jackrabbit.core.version.VersionImpl;
import org.apache.log4j.Logger;
import javax.jcr.*;
@@ -586,9 +590,13 @@
// check special nodes
if (state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION)) {
- return session.versionMgr.createVersionInstance(session, state, def, this, listeners);
+ InternalVersion version = session.versionMgr.getVersion(state.getUUID());
+ return new VersionImpl(this, session, id, state, def, listeners, version);
+
} else if (state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION_HISTORY)) {
- return session.versionMgr.createVersionHistoryInstance(session, state, def, this, listeners);
+ InternalVersionHistory history = session.versionMgr.getVersionHistory(state.getUUID());
+ return new VersionHistoryImpl(this, session, id, state, def, listeners, history);
+
} else {
// create node object
return new NodeImpl(this, session, id, state, def, listeners);
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java Mon Dec 20 02:29:45 2004
@@ -2795,10 +2795,10 @@
}
// copy frozen properties
- PersistentProperty[] props = freeze.getFrozenProperties();
+ PropertyState[] props = freeze.getFrozenProperties();
HashSet propNames = new HashSet();
for (int i = 0; i < props.length; i++) {
- PersistentProperty prop = props[i];
+ PropertyState prop = props[i];
propNames.add(prop.getName());
if (prop.getValues().length == 1) {
try {
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java Mon Dec 20 02:29:45 2004
@@ -31,6 +31,9 @@
import org.apache.jackrabbit.core.state.tx.XASessionImpl;
import org.apache.jackrabbit.core.util.uuid.UUID;
import org.apache.jackrabbit.core.version.PersistentVersionManager;
+import org.apache.jackrabbit.core.version.VersionManager;
+import org.apache.jackrabbit.core.version.VersionManagerImpl;
+import org.apache.jackrabbit.core.version.persistence.NativePVM;
import org.apache.log4j.Logger;
import javax.jcr.*;
@@ -83,7 +86,8 @@
private final NamespaceRegistryImpl nsReg;
private final NodeTypeRegistry ntReg;
- private final PersistentVersionManager vMgr;
+ private final PersistentVersionManager pvMgr;
+ private final VersionManager vMgr;
private final TransactionManager txMgr;
// configuration of the repository
@@ -282,7 +286,8 @@
// init version manager
// todo: as soon as dynamic workspaces are available, base on system ws
SessionImpl verSession = getSystemSession(repConfig.getDefaultWorkspaceName());
- vMgr = new PersistentVersionManager(verSession);
+ pvMgr = new NativePVM(verSession);
+ vMgr = new VersionManagerImpl(pvMgr);
// load repository properties
repProps = new Properties();
@@ -362,7 +367,7 @@
return ntReg;
}
- PersistentVersionManager getPersistentVersionManager() {
+ VersionManager getVersionManager() {
// check state
if (disposed) {
throw new IllegalStateException("repository instance has been shut down");
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java Mon Dec 20 02:29:45 2004
@@ -22,6 +22,7 @@
import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.state.PersistentItemStateProvider;
import org.apache.jackrabbit.core.state.SessionItemStateManager;
+import org.apache.jackrabbit.core.version.VersionManagerImpl;
import org.apache.jackrabbit.core.version.VersionManager;
import org.apache.jackrabbit.core.xml.ImportHandler;
import org.apache.log4j.Logger;
@@ -158,7 +159,7 @@
hierMgr = itemStateMgr.getHierarchyMgr();
itemMgr = createItemManager(itemStateMgr, hierMgr);
accessMgr = createAccessManager(credentials, hierMgr);
- versionMgr = rep.getPersistentVersionManager() == null ? null : rep.getPersistentVersionManager().getVersionManager(wsp);
+ versionMgr = rep.getVersionManager();
// add virtual item managers only for normal sessions
if (!(this instanceof SystemSession)) {
@@ -190,7 +191,7 @@
itemStateMgr = new SessionItemStateManager(rep.getRootNodeUUID(), wsp.getPersistentStateManager(), getNamespaceResolver());
hierMgr = itemStateMgr.getHierarchyMgr();
itemMgr = createItemManager(itemStateMgr, hierMgr);
- versionMgr = rep.getPersistentVersionManager() == null ? null : rep.getPersistentVersionManager().getVersionManager(wsp);
+ versionMgr = rep.getVersionManager();
// add virtual item managers only for normal sessions
if (!(this instanceof SystemSession)) {
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml Mon Dec 20 02:29:45 2004
@@ -104,7 +104,7 @@
</supertypes>
<propertyDef name="jcr:encoding" type="String" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:mimeType" type="String" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
- <propertyDef name="jcr:data" type="Binary" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="true" multiple="false"/>
+ <propertyDef name="jcr:data" type="Binary" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" primaryItem="true" multiple="false"/>
<propertyDef name="jcr:lastModified" type="Date" autoCreate="true" mandatory="true" onParentVersion="COMPUTE" protected="false" primaryItem="false" multiple="false"/>
</nodeType>
<nodeType name="nt:folder" mixin="false" orderableChildNodes="false">
@@ -295,6 +295,22 @@
<requiredPrimaryType>nt:base</requiredPrimaryType>
</requiredPrimaryTypes>
</childNodeDef>
+ </nodeType>
+ <!-- internal nodetypes for persistent version manager -->
+ <nodeType name="rep:versionHistory" mixin="false" orderableChildNodes="false">
+ <supertypes>
+ <supertype>nt:unstructured</supertype>
+ </supertypes>
+ </nodeType>
+ <nodeType name="rep:version" mixin="false" orderableChildNodes="false">
+ <supertypes>
+ <supertype>nt:unstructured</supertype>
+ </supertypes>
+ </nodeType>
+ <nodeType name="rep:frozen" mixin="false" orderableChildNodes="true">
+ <supertypes>
+ <supertype>nt:unstructured</supertype>
+ </supertypes>
</nodeType>
</nodeTypes>
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/HistoryRootNodeState.java Mon Dec 20 02:29:45 2004
@@ -17,41 +17,73 @@
import org.apache.jackrabbit.core.NamespaceRegistryImpl;
import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.version.VersionManager;
+import org.apache.jackrabbit.core.version.InternalVersionHistory;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.jackrabbit.core.virtual.VirtualNodeState;
import javax.jcr.RepositoryException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
+import java.util.Iterator;
/**
- * This Class implements...
+ * The history root node state represents the root node of all version histories.
+ * the version histories are dynamically exposed. since there could be very many,
+ * it does not return all the child nodes by the {@link #getChildNodeEntries()}}
+ * method. this implies, that the version storage is not browsable, but the
+ * nodes are nevertheless correctly exposed (this behaviour can be changed, by
+ * modifying the compile-time constant {@link #LIST_ALL_HISTORIES}.
*/
public class HistoryRootNodeState extends VirtualNodeState {
- private VersionManager vm;
-
- public HistoryRootNodeState(VersionItemStateProvider vm, String uuid, String parentUUID) {
- super(vm, uuid, NodeTypeRegistry.NT_UNSTRUCTURED, parentUUID);
- this.vm = vm.getVersionManager();
-
- setDefinitionId(vm.getNodeDefId(VersionManager.NODENAME_HISTORY_ROOT));
- }
-
+ /**
+ * flag for listing all histories
+ */
+ private static final boolean LIST_ALL_HISTORIES = true;
+
+ /**
+ * the version manager
+ */
+ private final VersionManager vm;
+
+ /**
+ * creates a new history root state
+ * @param stateMgr
+ * @param parentUUID
+ * @param uuid
+ * @throws RepositoryException
+ */
+ protected HistoryRootNodeState(VersionItemStateProvider stateMgr,
+ VersionManager vm,
+ String parentUUID,
+ String uuid) throws RepositoryException {
+ super(stateMgr, parentUUID, uuid, NodeTypeRegistry.NT_UNSTRUCTURED, new QName[0]);
+ this.vm = vm;
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#hasChildNodeEntry(org.apache.jackrabbit.core.QName)
+ */
public synchronized boolean hasChildNodeEntry(QName name) {
- return vm.hasVersionHistory(name);
+ return vm.hasVersionHistory(name.getLocalName());
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#hasChildNodeEntry(org.apache.jackrabbit.core.QName, int)
+ */
public synchronized boolean hasChildNodeEntry(QName name, int index) {
- return index <= 1 ? vm.hasVersionHistory(name) : false;
+ return index <= 1 ? vm.hasVersionHistory(name.getLocalName()) : false;
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#getChildNodeEntry(org.apache.jackrabbit.core.QName, int)
+ */
public synchronized ChildNodeEntry getChildNodeEntry(QName nodeName, int index) {
try {
if (index <= 1) {
- InternalVersionHistory hist = vm.getVersionHistory(nodeName);
+ InternalVersionHistory hist = vm.getVersionHistory(nodeName.getLocalName());
return new ChildNodeEntry(nodeName, hist.getId(), 1);
}
} catch (RepositoryException e) {
@@ -60,22 +92,30 @@
return null;
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#getChildNodeEntries()
+ */
public synchronized List getChildNodeEntries() {
- try {
- ArrayList list = new ArrayList(vm.getNumVersionHistories());
- Iterator iter = vm.getVersionHistories();
- while (iter.hasNext()) {
- InternalVersionHistory vh = (InternalVersionHistory) iter.next();
- QName name = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, vh.getId());
- list.add(new ChildNodeEntry(name, vh.getId(), 1));
+ if (LIST_ALL_HISTORIES) {
+ try {
+ ArrayList list = new ArrayList(vm.getNumVersionHistories());
+ Iterator iter = vm.getVersionHistoryIds();
+ while (iter.hasNext()) {
+ String id = (String) iter.next();
+ QName name = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, id);
+ list.add(new ChildNodeEntry(name, id, 1));
+ }
+ return list;
+ } catch (RepositoryException e) {
+ // ignore
}
- return list;
- } catch (RepositoryException e) {
- // ignore
}
return Collections.EMPTY_LIST;
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#getChildNodeEntries(String)
+ */
public synchronized List getChildNodeEntries(String uuid) {
// todo: do nicer
try {
@@ -91,6 +131,9 @@
return Collections.EMPTY_LIST;
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#getChildNodeEntries(org.apache.jackrabbit.core.QName)
+ */
public synchronized List getChildNodeEntries(QName nodeName) {
// todo: do nicer
try {
@@ -105,6 +148,4 @@
}
return Collections.EMPTY_LIST;
}
-
-
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java Mon Dec 20 02:29:45 2004
@@ -18,42 +18,15 @@
import org.apache.jackrabbit.core.QName;
/**
- * Abstract class that represents either a frozen child or a frozen versionable
- * node.
+ * the base interface for nodes that were versioned and turned either into
+ * InternalFrozenNode or InteralFrozenVersionHistory.
*/
-public abstract class InternalFreeze {
+public interface InternalFreeze extends InternalVersionItem {
/**
- * the parent 'freeze'
+ * returns the name of the node.
+ * @return the name of the node.
*/
- private final InternalFreeze parent;
+ public QName getName();
- /**
- * Creates a new 'Freeze'
- *
- * @param parent
- */
- protected InternalFreeze(InternalFreeze parent) {
- this.parent = parent;
- }
-
- /**
- * Returns the name of the frozen node
- *
- * @return
- */
- public abstract QName getName();
-
- /**
- * returns the version manager
- *
- * @return
- */
- public PersistentVersionManager getVersionManager() {
- return parent == null ? null : parent.getVersionManager();
- }
-
- public InternalFreeze getParent() {
- return parent;
- }
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java Mon Dec 20 02:29:45 2004
@@ -16,321 +16,51 @@
package org.apache.jackrabbit.core.version;
import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
-import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.util.uuid.UUID;
-
-import javax.jcr.NodeIterator;
-import javax.jcr.PropertyIterator;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.version.OnParentVersionAction;
-import java.util.ArrayList;
-import java.util.List;
+import org.apache.jackrabbit.core.state.PropertyState;
+import javax.jcr.version.VersionException;
/**
- * The InternalFrozenNode class presents the frozen node that was generated
+ * The InternalFrozenNode interface represents the frozen node that was generated
* during a {@link javax.jcr.Node#checkin()}. It holds the set of frozen
* properties, the frozen child nodes and the frozen version history
* references of the original node.
*/
-public class InternalFrozenNode extends InternalFreeze {
-
- private static final boolean FREEZEMODE_CLONE = true;
-
- /**
- * the underlaying persistance node
- */
- private PersistentNode node;
-
- /**
- * the list of frozen child nodes
- */
- private InternalFreeze[] frozenChildNodes;
-
- /**
- * the list of frozen properties
- */
- private PersistentProperty[] frozenProperties;
-
- /**
- * the frozen uuid of the original node
- */
- private String frozenUUID = null;
-
- /**
- * the frozen primary type of the orginal node
- */
- private QName frozenPrimaryType = null;
-
- /**
- * the frozen list of mixin types of the original node
- */
- private QName[] frozenMixinTypes = null;
-
- /**
- * uuid of this node
- */
- private String uuid;
-
- /**
- * Creates a new frozen node based on the given persistance node.
- *
- * @param node
- * @throws RepositoryException
- */
- protected InternalFrozenNode(InternalFreeze parent, PersistentNode node) throws RepositoryException {
- super(parent);
- this.node = node;
-
- // init the frozen properties
- PersistentProperty[] props = node.getProperties();
- List propList = new ArrayList();
-
- for (int i = 0; i < props.length; i++) {
- PersistentProperty prop = props[i];
- if (FREEZEMODE_CLONE) {
- if (prop.getName().equals(ItemImpl.PROPNAME_PRIMARYTYPE)) {
- frozenPrimaryType = (QName) node.getPropertyValue(prop.getName()).internalValue();
- } else if (prop.getName().equals(ItemImpl.PROPNAME_UUID)) {
- frozenUUID = node.getPropertyValue(prop.getName()).toString();
- } else if (prop.getName().equals(ItemImpl.PROPNAME_MIXINTYPES)) {
- InternalValue[] values = node.getPropertyValues(prop.getName());
- if (values == null) {
- frozenMixinTypes = new QName[0];
- } else {
- frozenMixinTypes = new QName[values.length];
- for (int j = 0; j < values.length; j++) {
- frozenMixinTypes[j] = (QName) values[j].internalValue();
- }
- }
- } else {
- propList.add(prop);
- }
-
- } else {
- if (prop.getName().equals(VersionManager.PROPNAME_FROZEN_UUID)) {
- // special property
- frozenUUID = node.getPropertyValue(VersionManager.PROPNAME_FROZEN_UUID).internalValue().toString();
- } else if (prop.getName().equals(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE)) {
- // special property
- frozenPrimaryType = (QName) node.getPropertyValue(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE).internalValue();
- } else if (prop.getName().equals(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES)) {
- // special property
- InternalValue[] values = node.getPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES);
- if (values == null) {
- frozenMixinTypes = new QName[0];
- } else {
- frozenMixinTypes = new QName[values.length];
- for (int j = 0; j < values.length; j++) {
- frozenMixinTypes[j] = (QName) values[j].internalValue();
- }
- }
- } else if (prop.getName().equals(ItemImpl.PROPNAME_PRIMARYTYPE)) {
- // ignore
- } else if (prop.getName().equals(ItemImpl.PROPNAME_UUID)) {
- // ignore
- } else {
- propList.add(prop);
- }
- }
- }
- frozenProperties = (PersistentProperty[]) propList.toArray(new PersistentProperty[propList.size()]);
-
- // do some checks
- if (frozenMixinTypes == null) {
- frozenMixinTypes = new QName[0];
- }
- if (frozenPrimaryType == null) {
- throw new RepositoryException("Illegal frozen node. Must have 'frozenPrimaryType'");
- }
- // init the frozen child nodes
- PersistentNode[] childNodes = node.getChildNodes();
- frozenChildNodes = new InternalFreeze[childNodes.length];
- for (int i = 0; i < childNodes.length; i++) {
- if (childNodes[i].hasProperty(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE)) {
- frozenChildNodes[i] = new InternalFrozenNode(this, childNodes[i]);
- } else if (childNodes[i].hasProperty(VersionManager.PROPNAME_VERSION_HISTORY)) {
- frozenChildNodes[i] = new InternalFrozenVersionHistory(this, childNodes[i]);
- } else {
- // unkown ?
- }
- }
-
- }
-
- public String getInternalUUID() {
- return node.getUUID();
- }
-
- /**
- * Returns the name of this frozen node
- *
- * @return
- */
- public QName getName() {
- return node.getName();
- }
-
- /**
- * Returns the UUID of this frozen node
- *
- * @return
- */
- public String getUUID() {
- return node.getUUID();
- }
+public interface InternalFrozenNode extends InternalFreeze {
/**
* Returns the list of frozen child nodes
*
- * @return
+ * @return an array of internal freezes
+ * @throws VersionException if the freezes cannot be retrieved
*/
- public InternalFreeze[] getFrozenChildNodes() {
- return frozenChildNodes;
- }
+ public InternalFreeze[] getFrozenChildNodes() throws VersionException;
/**
- * Returns the list of frozen properties
+ * Returns the list of frozen properties.
*
- * @return
+ * @return an array of property states
*/
- public PersistentProperty[] getFrozenProperties() {
- return frozenProperties;
- }
+ public PropertyState[] getFrozenProperties();
/**
- * Returns the frozen UUID
+ * Returns the frozen UUID.
*
- * @return
+ * @return the frozen uuid.
*/
- public String getFrozenUUID() {
- return frozenUUID;
- }
+ public String getFrozenUUID();
/**
- * Returns the frozen primary type
+ * Returns the name of frozen primary type.
*
- * @return
+ * @return the name of the frozen primary type.
*/
- public QName getFrozenPrimaryType() {
- return frozenPrimaryType;
- }
+ public QName getFrozenPrimaryType();
/**
- * Returns the list of the frozen mixin types
+ * Returns the list of names of the frozen mixin types.
*
- * @return
+ * @return the list of names of the frozen mixin types.
*/
- public QName[] getFrozenMixinTypes() {
- return frozenMixinTypes;
- }
-
- /**
- * Checks-in a <code>src</code> node. It creates a new child node of
- * <code>parent</code> with the given <code>name</code> and adds the
- * source nodes properties according to their OPV value to the
- * list of frozen properties. It creates frozen child nodes for each child
- * node of <code>src</code> according to its OPV value.
- *
- * @param parent
- * @param name
- * @param src
- * @return
- * @throws RepositoryException
- */
- protected static PersistentNode checkin(PersistentNode parent, QName name, NodeImpl src, boolean initOnly, boolean forceCopy)
- throws RepositoryException {
-
- PersistentNode node;
- if (FREEZEMODE_CLONE) {
- // identiycopy
- // create new node
- NodeType[] mixins = src.getMixinNodeTypes();
- QName[] mixinNames = new QName[mixins.length];
- for (int i = 0; i < mixins.length; i++) {
- mixinNames[i] = ((NodeTypeImpl) mixins[i]).getQName();
- }
- node = parent.addNode(name, ((NodeTypeImpl) src.getPrimaryNodeType()).getQName());
- node.setMixinNodeTypes(mixinNames);
-
- } else {
- // emulated
- // create new node
- node = parent.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
-
- // initialize the internal properties
- if (src.isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
- node.setPropertyValue(VersionManager.PROPNAME_FROZEN_UUID, InternalValue.create(src.getUUID()));
- }
-
- node.setPropertyValue(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE,
- InternalValue.create(((NodeTypeImpl) src.getPrimaryNodeType()).getQName()));
-
- if (src.hasProperty(NodeImpl.PROPNAME_MIXINTYPES)) {
- NodeType[] mixins = src.getMixinNodeTypes();
- InternalValue[] ivalues = new InternalValue[mixins.length];
- for (int i = 0; i < mixins.length; i++) {
- ivalues[i] = InternalValue.create(((NodeTypeImpl) mixins[i]).getQName());
- }
- node.setPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, PropertyType.NAME, ivalues);
- }
- }
-
- if (!initOnly) {
- // add the properties
- PropertyIterator piter = src.getProperties();
- while (piter.hasNext()) {
- PropertyImpl prop = (PropertyImpl) piter.nextProperty();
- int opv = forceCopy ? OnParentVersionAction.COPY : prop.getDefinition().getOnParentVersion();
- switch (opv) {
- case OnParentVersionAction.ABORT:
- parent.reload();
- throw new RepositoryException("Checkin aborted due to OPV in " + prop.safeGetJCRPath());
- case OnParentVersionAction.COMPUTE:
- case OnParentVersionAction.IGNORE:
- case OnParentVersionAction.INITIALIZE:
- break;
- case OnParentVersionAction.VERSION:
- case OnParentVersionAction.COPY:
- node.copyFrom(prop);
- break;
- }
- }
-
-
- // add the frozen children and vistories
- NodeIterator niter = src.getNodes();
- while (niter.hasNext()) {
- NodeImpl child = (NodeImpl) niter.nextNode();
- int opv = forceCopy ? OnParentVersionAction.COPY : child.getDefinition().getOnParentVersion();
- switch (opv) {
- case OnParentVersionAction.ABORT:
- throw new RepositoryException("Checkin aborted due to OPV in " + child.safeGetJCRPath());
- case OnParentVersionAction.COMPUTE:
- case OnParentVersionAction.IGNORE:
- case OnParentVersionAction.INITIALIZE:
- break;
- case OnParentVersionAction.VERSION:
- if (child.isNodeType(NodeTypeRegistry.MIX_VERSIONABLE)) {
- // create frozen versionable child
- PersistentNode newChild = node.addNode(child.getQName(), NodeTypeRegistry.NT_FROZEN_VERSIONABLE_CHILD);
- newChild.setPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY,
- InternalValue.create(UUID.fromString(child.getVersionHistory().getUUID())));
- newChild.setPropertyValue(VersionManager.PROPNAME_BASE_VERSION,
- InternalValue.create(UUID.fromString(child.getBaseVersion().getUUID())));
- break;
- }
- // else copy
- case OnParentVersionAction.COPY:
- checkin(node, child.getQName(), child, false, true);
- break;
- }
- }
- }
- parent.store();
- return node;
- }
+ public QName[] getFrozenMixinTypes();
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java Mon Dec 20 02:29:45 2004
@@ -15,68 +15,46 @@
*/
package org.apache.jackrabbit.core.version;
-import org.apache.jackrabbit.core.QName;
-
-import javax.jcr.RepositoryException;
+import javax.jcr.version.VersionException;
/**
- * This Class represents a frozen versionable child node, that was created
+ * This interface defines a frozen versionable child node, that was created
* during a {@link javax.jcr.Node#checkin()} with a OPV==Version node.
*/
-public class InternalFrozenVersionHistory extends InternalFreeze {
-
- /**
- * the underlaying persistence node
- */
- private PersistentNode node;
+public interface InternalFrozenVersionHistory extends InternalFreeze {
/**
- * Creates a new frozen version history.
+ * Returns the id of the version history that was assigned to the node at
+ * the time it was versioned.
*
- * @param node
+ * @return the id of the version history
*/
- protected InternalFrozenVersionHistory(InternalFreeze parent, PersistentNode node) {
- super(parent);
- this.node = node;
- }
+ public String getVersionHistoryId();
/**
- * Returns the name of this frozen version history
+ * Returns the version history that was assigned to the node at
+ * the time it was versioned.
*
- * @return
+ * @return the internal version history.
+ * @throws VersionException if the history cannot be retrieved.
*/
- public QName getName() {
- return node.getName();
- }
+ public InternalVersionHistory getVersionHistory()
+ throws VersionException;
/**
- * Returns the version history that was versioned with this node.
+ * Returns the id of the base version that was assigned to the node at
+ * the time it was versioned.
*
- * @return
- * @throws RepositoryException
+ * @return the id of the base version
*/
- public String getVersionHistoryId()
- throws RepositoryException {
- return (String) node.getPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY).internalValue();
- }
+ public String getBaseVersionId();
/**
- * Returns the version history that was versioned with this node.
+ * Returns the base version that was assigned to the node at
+ * the time it was versioned.
*
- * @return
- * @throws RepositoryException
+ * @return the inernal base version
+ * @throws VersionException if the version could not be retrieved
*/
- public InternalVersionHistory getVersionHistory()
- throws RepositoryException {
- return getVersionManager().getVersionHistory(getVersionHistoryId());
- }
-
- public String getBaseVersionId() throws RepositoryException {
- return (String) node.getPropertyValue(VersionManager.PROPNAME_BASE_VERSION).internalValue();
- }
-
- public InternalVersion getBaseVesion()
- throws RepositoryException {
- return getVersionManager().getVersion(getVersionHistoryId(), getBaseVersionId());
- }
+ public InternalVersion getBaseVesion() throws VersionException;
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java Mon Dec 20 02:29:45 2004
@@ -15,229 +15,47 @@
*/
package org.apache.jackrabbit.core.version;
-import org.apache.jackrabbit.core.InternalValue;
import org.apache.jackrabbit.core.QName;
-import org.apache.jackrabbit.core.util.uuid.UUID;
-
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
import javax.jcr.version.Version;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Calendar;
-import java.util.HashSet;
/**
- * This Class implements the Version representation of the node.
+ * This interface defines the internal version.
*/
-public final class InternalVersion extends InternalFreeze {
-
- /**
- * the list/cache of predecessors (values == InternalVersion)
- */
- private ArrayList predecessors = new ArrayList();
-
- /**
- * the list of successors (values == InternalVersion)
- */
- private ArrayList successors = new ArrayList();
-
- /**
- * the internal version history that this version is contained in
- */
- private InternalVersionHistory versionHistory;
-
- /**
- * the underlaying persistance node of this history
- */
- private PersistentNode node;
-
- /**
- * the date when this version was created
- */
- private Calendar created;
-
- /**
- * the set of version labes of this history (values == String)
- */
- private HashSet labelCache = null;
-
- /**
- * the id of this version
- */
- private String versionId;
-
- /**
- * specifies if this is the root version
- */
- private final boolean isRoot;
-
- /**
- * Creates a new internal version with the given version history and
- * persistance node
- *
- * @param vh
- * @param node
- */
- InternalVersion(InternalVersionHistory vh, PersistentNode node) {
- super(null);
- this.versionHistory = vh;
- this.node = node;
-
- // check name
- isRoot = node.getName().equals(VersionManager.NODENAME_ROOTVERSION);
-
- // get id
- versionId = (String) node.getPropertyValue(PersistentVersionManager.PROPNAME_VERSION_ID).internalValue();
-
- // init internal values
- InternalValue[] values = node.getPropertyValues(VersionManager.PROPNAME_CREATED);
- if (values != null) {
- created = (Calendar) values[0].internalValue();
- }
- }
-
- /**
- * Returns the uuid of this version
- *
- * @return
- */
- public String getId() {
- return versionId;
- }
-
- /**
- * Returns the name of this version
- *
- * @return
- */
- public QName getName() {
- return node.getName();
- }
+public interface InternalVersion extends InternalVersionItem {
/**
- * returns the version manager
+ * Returns the name of this version.
*
- * @return
+ * @return the name of this version.
*/
- public PersistentVersionManager getVersionManager() {
- return versionHistory.getVersionManager();
- }
+ public QName getName();
/**
- * Returns the frozen node
+ * Returns the frozen node of this version or <code>null</code> if this is
+ * the root version.
*
- * @return
+ * @return the frozen node.
*/
- public InternalFrozenNode getFrozenNode() {
- // get frozen node
- try {
- PersistentNode pNode = node.getNode(PersistentVersionManager.NODENAME_FROZEN, 1);
- return pNode == null ? null : new InternalFrozenNode(this, pNode);
- } catch (RepositoryException e) {
- // ignore
- }
- return null;
- }
-
- /**
- * adds a successor version to the internal cache
- *
- * @param successor
- */
- private void addSuccessor(InternalVersion successor) {
- successors.add(successor);
- }
-
- /**
- * resolves the predecessors property and indirectly adds it self to their
- * successor list.
- */
- void resolvePredecessors() {
- InternalValue[] values = node.getPropertyValues(VersionManager.PROPNAME_PREDECESSORS);
- if (values != null) {
- for (int i = 0; i < values.length; i++) {
- InternalVersion v = versionHistory.getVersion(values[i].internalValue().toString());
- predecessors.add(v);
- v.addSuccessor(this);
- }
- }
- }
+ public InternalFrozenNode getFrozenNode();
/**
+ * Aequivalent to {@link javax.jcr.version.Version#getCreated()}
* @see Version#getCreated()
*/
- public Calendar getCreated() {
- return created;
- }
+ public Calendar getCreated();
/**
+ * Aequivalent to {@link javax.jcr.version.Version#getSuccessors()}}
* @see Version#getSuccessors()
*/
- public InternalVersion[] getSuccessors() {
- return (InternalVersion[]) successors.toArray(new InternalVersion[successors.size()]);
- }
+ public InternalVersion[] getSuccessors();
/**
- * @see Version#getSuccessors()
+ * Aequivalent to {@link javax.jcr.version.Version#getPredecessors()}}
+ * @see javax.jcr.version.Version#getPredecessors()
*/
- public InternalVersion[] getPredecessors() {
- return (InternalVersion[]) predecessors.toArray(new InternalVersion[predecessors.size()]);
- }
-
- /**
- * stores the internal predecessor cache to the persistance node
- *
- * @throws RepositoryException
- */
- private void storePredecessors() throws RepositoryException {
- InternalValue[] values = new InternalValue[predecessors.size()];
- for (int i = 0; i < values.length; i++) {
- values[i] = InternalValue.create(new UUID(((InternalVersion) predecessors.get(i)).getId()));
- }
- node.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.STRING, values);
- }
-
- /**
- * Detaches itself from the version graph.
- *
- * @throws RepositoryException
- */
- void internalDetach() throws RepositoryException {
- // detach this from all successors
- InternalVersion[] succ = (InternalVersion[]) getSuccessors();
- for (int i = 0; i < succ.length; i++) {
- succ[i].internalDetachPredecessor(this);
- }
-
- // clear properties
- successors.clear();
- predecessors.clear();
- labelCache = null;
- storePredecessors();
- }
-
- /**
- * Removes the predecessor V of this predecessor list and adds all of Vs
- * predecessors to it.
- * <p/>
- * please note, that this operation might corrupt the version graph
- *
- * @param v the successor to detach
- */
- private void internalDetachPredecessor(InternalVersion v) throws RepositoryException {
- // remove 'v' from predecessor list
- for (int i = 0; i < predecessors.size(); i++) {
- if (predecessors.get(i).equals(v)) {
- predecessors.remove(i);
- break;
- }
- }
- // attach v's successors
- predecessors.clear();
- predecessors.addAll(Arrays.asList(v.getPredecessors()));
- storePredecessors();
- }
+ public InternalVersion[] getPredecessors();
/**
* Checks if this version is more recent than the given version <code>v</code>.
@@ -248,78 +66,34 @@
* @return <code>true</code> if the version is more recent;
* <code>false</code> otherwise.
*/
- public boolean isMoreRecent(InternalVersion v) {
- for (int i = 0; i < predecessors.size(); i++) {
- InternalVersion pred = (InternalVersion) predecessors.get(i);
- if (pred.equals(this) || pred.isMoreRecent(v)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * returns the internal version history of this version
- *
- * @return
- */
- protected InternalVersionHistory getVersionHistory() {
- return versionHistory;
- }
-
- /**
- * adds a label to the label cache. does not affect storage
- *
- * @param label
- * @return
- */
- protected boolean internalAddLabel(String label) {
- if (labelCache == null) {
- labelCache = new HashSet();
- }
- return labelCache.add(label);
- }
+ public boolean isMoreRecent(InternalVersion v);
/**
- * removes a label from the label cache. does not affect storage
+ * returns the internal version history in wich this version lifes in.
*
- * @param label
- * @return
+ * @return the version history for this version.
*/
- protected boolean internalRemoveLabel(String label) {
- if (labelCache == null) {
- return false;
- } else {
- return labelCache.remove(label);
- }
- }
+ public InternalVersionHistory getVersionHistory();
/**
- * checks, if a label is in the label cache
+ * checks if this is the root version.
*
- * @param label
- * @return
+ * @return <code>true</code> if this version is the root version;
+ * <code>false</code> otherwise.
*/
- protected boolean internalHasLabel(String label) {
- return labelCache == null ? false : labelCache.contains(label);
- }
+ public boolean isRootVersion();
/**
- * returns the array of the cached labels
- *
- * @return
+ * Checks, if this version has the given label assosiated
+ * @param label the label to check.
+ * @return <code>true</code> if the label is assigned to this version;
+ * <code>false</code> otherwise.
*/
- protected String[] internalGetLabels() {
- return labelCache == null ? new String[0] : (String[]) labelCache.toArray(new String[labelCache.size()]);
- }
+ public boolean hasLabel(String label);
/**
- * checks if this is the root version.
- *
- * @return <code>true</code> if this version is the root version;
- * <code>false</code> otherwise.
+ * returns the labels that are assigned to this version
+ * @return a string array of labels.
*/
- public boolean isRootVersion() {
- return isRoot;
- }
+ public String[] getLabels();
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java Mon Dec 20 02:29:45 2004
@@ -15,209 +15,63 @@
*/
package org.apache.jackrabbit.core.version;
-import org.apache.jackrabbit.core.InternalValue;
-import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.QName;
-import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.util.Text;
-import org.apache.jackrabbit.core.util.uuid.UUID;
-import org.apache.log4j.Logger;
-
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
+
import javax.jcr.version.VersionException;
import javax.jcr.version.VersionHistory;
-import java.util.Calendar;
-import java.util.HashMap;
import java.util.Iterator;
/**
- * This Class implements a version history.
+ * This interface defines the internal version history.
*/
-public class InternalVersionHistory {
+public interface InternalVersionHistory extends InternalVersionItem {
/**
- * default logger
- */
- private static Logger log = Logger.getLogger(InternalVersionHistory.class);
-
- /**
- * the cache of the version labels
- * key = version label (String)
- * value = version
- */
- private HashMap labelCache = new HashMap();
-
- /**
- * the root version of this history
- */
- private InternalVersion rootVersion;
-
- /**
- * the hashmap of all versions
- * key = versionId (String)
- * value = version
- */
- private HashMap versionCache = new HashMap();
-
- /**
- * The nodes state of this version history
- */
- private PersistentNode node;
-
- /**
- * the node that holds the label nodes
- */
- private PersistentNode labelNode;
-
- /**
- * the id of this history
- */
- private String historyId;
-
- /**
- * the version manager
- */
- private final PersistentVersionManager vMgr;
-
- /**
- * Creates a new VersionHistory object for the given node state.
+ * Aequivalalent to {@link VersionHistory#getRootVersion()}.
+ * @see VersionHistory#getRootVersion()
*/
- InternalVersionHistory(PersistentVersionManager vMgr, PersistentNode node) throws RepositoryException {
- this.vMgr = vMgr;
- this.node = node;
- init();
- }
+ public InternalVersion getRootVersion();
/**
- * Initialies the history and loads all internal caches
- *
- * @throws RepositoryException
+ * Aequivalent to {@link VersionHistory#getVersion(java.lang.String)}.
+ * @see VersionHistory#getVersion(java.lang.String)
*/
- private void init() throws RepositoryException {
- versionCache.clear();
- labelCache.clear();
-
- // get id
- historyId = (String) node.getPropertyValue(PersistentVersionManager.PROPNAME_HISTORY_ID).internalValue();
-
- // get entries
- PersistentNode[] children = node.getChildNodes();
- for (int i = 0; i < children.length; i++) {
- PersistentNode child = children[i];
- if (child.getName().equals(PersistentVersionManager.NODENAME_VERSION_LABELS)) {
- labelNode = child;
- continue;
- }
- InternalVersion v = new InternalVersion(this, child);
- versionCache.put(v.getId(), v);
- if (v.isRootVersion()) {
- rootVersion = v;
- }
- }
-
- // resolve successors and predecessors
- Iterator iter = versionCache.values().iterator();
- while (iter.hasNext()) {
- InternalVersion v = (InternalVersion) iter.next();
- v.resolvePredecessors();
- }
-
- // init label cache
- PersistentNode labels[] = labelNode.getChildNodes();
- for (int i = 0; i < labels.length; i++) {
- PersistentNode lNode = labels[i];
- String name = (String) lNode.getPropertyValue(PersistentVersionManager.PROPNAME_NAME).internalValue();
- String ref = (String) lNode.getPropertyValue(PersistentVersionManager.PROPNAME_VERSION).internalValue();
- InternalVersion v = getVersion(ref);
- labelCache.put(name, v);
- v.internalAddLabel(name);
- }
- }
+ public InternalVersion getVersion(QName versionName) throws VersionException;
/**
- * returns the version manager
+ * Checks if the version with the given name exists in this version history.
*
- * @return
+ * @param versionName the name of the version
+ * @return <code>true</code> if the version exists;
+ * <code>false</code> otherwise.
*/
- public PersistentVersionManager getVersionManager() {
- return vMgr;
- }
+ public boolean hasVersion(QName versionName);
/**
- * Returns the id of this version history
+ * Checks if the version for the given uuid exists in this history.
*
- * @return
- */
- public String getId() {
- return historyId;
- }
-
- /**
- * @see VersionHistory#getRootVersion()
+ * @param uuid the uuid of the version
+ * @return <code>true</code> if the version exists;
+ * <code>false</code> otherwise.
*/
- public InternalVersion getRootVersion() throws RepositoryException {
- return rootVersion;
- }
-
- /**
- * @see VersionHistory#getVersion(java.lang.String)
- */
- public InternalVersion getVersion(QName versionName) throws RepositoryException {
- // maybe add cache by name?
- Iterator iter = versionCache.values().iterator();
- while (iter.hasNext()) {
- InternalVersion v = (InternalVersion) iter.next();
- if (v.getName().equals(versionName)) {
- return v;
- }
- }
- throw new VersionException("Version " + versionName + " does not exist.");
- }
-
- /**
- * @see VersionHistory#hasVersion(String)
- */
- public boolean hasVersion(QName versionName) {
- // maybe add cache?
- Iterator iter = versionCache.values().iterator();
- while (iter.hasNext()) {
- InternalVersion v = (InternalVersion) iter.next();
- if (v.getName().equals(versionName)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks if the version for the given uuid exists
- *
- * @param uuid
- * @return
- */
- public boolean hasVersion(String uuid) {
- return versionCache.containsKey(uuid);
- }
+ public boolean hasVersion(String uuid);
/**
* Returns the version with the given uuid or <code>null</code> if the
* respective version does not exist.
*
- * @param uuid
- * @return
+ * @param uuid the uuid of the version
+ * @return the internal version ot <code>null</code>
*/
- public InternalVersion getVersion(String uuid) {
- return (InternalVersion) versionCache.get(uuid);
- }
+ public InternalVersion getVersion(String uuid);
/**
+ * Aequivalent to {@link VersionHistory#getVersionByLabel(java.lang.String)}
+ * but returns <code>null</code> if the version does not exists.
+ *
* @see VersionHistory#getVersionByLabel(java.lang.String)
*/
- public InternalVersion getVersionByLabel(String label) throws RepositoryException {
- return (InternalVersion) labelCache.get(label);
- }
+ public InternalVersion getVersionByLabel(String label);
/**
* Removes the indicated version from this VersionHistory. If the specified
@@ -228,209 +82,50 @@
* predecessors of the removed version and vice versa. then, the entire
* version node and all its subnodes are removed.
*
- * @param versionName
- * @throws RepositoryException
- */
- public void removeVersion(QName versionName) throws RepositoryException {
- InternalVersion v = (InternalVersion) getVersion(versionName);
- if (v.equals(rootVersion)) {
- String msg = "Removal of " + versionName + " not allowed.";
- log.error(msg);
- throw new VersionException(msg);
- }
-
- // remove from persistance state
- node.removeNode(versionName);
-
- // unregister from labels
- String[] labels = v.internalGetLabels();
- for (int i = 0; i < labels.length; i++) {
- v.internalRemoveLabel(labels[i]);
- QName name = new QName("", Text.md5(labels[i]));
- labelNode.removeNode(name);
- }
-
- // detach from the version graph
- v.internalDetach();
-
- // and remove from history
- versionCache.remove(v.getId());
- store();
-
- }
-
- /**
- * Adds a label to a version
- *
- * @param version
- * @param label
- * @throws RepositoryException
- */
- public void addVersionLabel(InternalVersion version, String label, boolean move)
- throws VersionException, RepositoryException {
- InternalVersion prev = (InternalVersion) labelCache.get(label);
- if (version.equals(prev)) {
- // ignore
- return;
- } else if (prev != null && !move) {
- // already defined elsewhere, throw
- throw new VersionException("Version label " + label + " already defined for version " + prev.getName());
- } else if (prev != null) {
- // if already defined, but move, remove old label first
- removeVersionLabel(label);
- }
- labelCache.put(label, version);
- version.internalAddLabel(label);
- QName name = new QName("", Text.md5(label));
- PersistentNode lNode = labelNode.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
- lNode.setPropertyValue(PersistentVersionManager.PROPNAME_NAME, InternalValue.create(label));
- lNode.setPropertyValue(PersistentVersionManager.PROPNAME_VERSION, InternalValue.create(version.getId()));
- labelNode.store();
-
- // inform manager
- vMgr.onVersionModified(version);
- }
-
- /**
- * Removes the label from the respective version
- *
- * @param label
- * @throws RepositoryException if the label does not exist
+ * @param versionName the name of the version to be removed
+ * @throws VersionException if an error occurrs.
*/
- public void removeVersionLabel(String label) throws RepositoryException {
- InternalVersion v = (InternalVersion) labelCache.remove(label);
- if (v == null) {
- throw new RepositoryException("Version label " + label + " is not in version history.");
- }
- v.internalRemoveLabel(label);
- QName name = new QName("", Text.md5(label));
- labelNode.removeNode(name);
- labelNode.store();
-
- // inform manager
- vMgr.onVersionModified(v);
- }
+ public void removeVersion(QName versionName) throws VersionException;
/**
- * Checks in a node. It creates a new version with the given name and freezes
- * the state of the given node.
+ * Adds a label to a version. If the given label is already assigned to
+ * another version in this version history, a VersionException is thrown,
+ * unless <code>move</code> is set to <code>true</code>. in this case, the
+ * label is removed from the previously assigned version and added to the
+ * specified one.
*
- * @param name
- * @param src
- * @return
- * @throws RepositoryException
+ * @param name the name of the version
+ * @param label the label to assgign
+ * @param move flag what to do by collisions
+ * @return the version that was previously assigned by this label or <code>null</code>.
+ * @throws VersionException
*/
- protected InternalVersion checkin(QName name, NodeImpl src)
- throws RepositoryException {
-
- // copy predecessors from src node
- Value[] preds = src.getProperty(VersionManager.PROPNAME_PREDECESSORS).getValues();
- InternalValue[] predecessors = new InternalValue[preds.length];
- for (int i = 0; i < preds.length; i++) {
- String predId = preds[i].getString();
- // check if version exist
- if (!versionCache.containsKey(predId)) {
- throw new RepositoryException("invalid predecessor in source node");
- }
- predecessors[i] = InternalValue.create(predId);
- }
-
- PersistentNode vNode = node.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
- String versionId = UUID.randomUUID().toString();
- vNode.setPropertyValue(PersistentVersionManager.PROPNAME_VERSION_ID, InternalValue.create(versionId));
-
- // initialize 'created' and 'predecessors'
- vNode.setPropertyValue(VersionManager.PROPNAME_CREATED, InternalValue.create(Calendar.getInstance()));
- vNode.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.STRING, predecessors);
-
- // checkin source node
- InternalFrozenNode.checkin(vNode, PersistentVersionManager.NODENAME_FROZEN, src, false, false);
-
- // and store
- store();
-
- // update version graph
- InternalVersion version = new InternalVersion(this, vNode);
- version.resolvePredecessors();
-
- // update cache
- versionCache.put(version.getId(), version);
-
- return version;
- }
-
+ public InternalVersion addVersionLabel(QName name, String label, boolean move)
+ throws VersionException;
/**
- * Stores the changes made to this version history
+ * Removes the label from the respective version.
*
- * @throws RepositoryException
+ * @param label the label to be removed
+ * @return the version that had the label assigned
+ * @throws VersionException if the label does not exist
*/
- protected void store() throws RepositoryException {
- node.store();
- }
+ public InternalVersion removeVersionLabel(String label) throws VersionException;
/**
- * discards the changes made to this version history
+ * Returns an iterator over all versions (not ordered yet), including the
+ * root version.
*
- * @throws RepositoryException
+ * @return an iterator over {@link InternalVersion} objects.
*/
- protected void reload() throws RepositoryException {
- node.reload();
- init();
- }
+ public Iterator getVersions();
/**
- * Returns an iterator over all versions (not ordered yet)
+ * Returns the number of versions in this version history.
*
- * @return
+ * @return the number of versions, including the root version.
*/
- protected Iterator getVersions() {
- return versionCache.values().iterator();
- }
+ public int getNumVersions();
- /**
- * Returns the number of versions
- *
- * @return
- */
- protected int getNumVersions() {
- return versionCache.size();
- }
- /**
- * Creates a new <code>InternalVersionHistory</code> below the given parent
- * node and with the given name.
- *
- * @param parent
- * @param name
- * @return
- * @throws RepositoryException
- */
- protected static InternalVersionHistory create(PersistentVersionManager vMgr, PersistentNode parent, String historyId, QName name, NodeImpl src)
- throws RepositoryException {
-
- // create history node
- PersistentNode pNode = parent.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
- pNode.setPropertyValue(PersistentVersionManager.PROPNAME_HISTORY_ID, InternalValue.create(historyId));
-
- // create label node
- pNode.addNode(PersistentVersionManager.NODENAME_VERSION_LABELS, NodeTypeRegistry.NT_UNSTRUCTURED);
-
- // create root version
- String versionId = UUID.randomUUID().toString();
- PersistentNode vNode = pNode.addNode(VersionManager.NODENAME_ROOTVERSION, NodeTypeRegistry.NT_UNSTRUCTURED);
- vNode.setPropertyValue(PersistentVersionManager.PROPNAME_VERSION_ID, InternalValue.create(versionId));
-
- // initialize 'created' and 'predecessors'
- vNode.setPropertyValue(VersionManager.PROPNAME_CREATED, InternalValue.create(Calendar.getInstance()));
- vNode.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.REFERENCE, new InternalValue[0]);
-
- // add also an empty frozen node to the root version
- InternalFrozenNode.checkin(vNode, PersistentVersionManager.NODENAME_FROZEN, src, true, false);
-
- parent.store();
- return new InternalVersionHistory(vMgr, pNode);
- }
}
-
-
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionItem.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version;
+
+/**
+ * This interface defines the base for all internal versioning items. Internal
+ * versioning items are decoupled from their external form as exposed to the
+ * repository or in form of the node extensions {@link javax.jcr.version.Version}
+ * or {@link javax.jcr.version.VersionHistory}.
+ */
+public interface InternalVersionItem {
+
+ /**
+ * Returns the external id of this item
+ * @return
+ */
+ public String getId();
+
+ /**
+ * returns the parent version item or null
+ * @return
+ */
+ public InternalVersionItem getParent();
+}
Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentNode.java?view=auto&rev=122837
==============================================================================
Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentProperty.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentProperty.java?view=auto&rev=122837
==============================================================================
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java Mon Dec 20 02:29:45 2004
@@ -15,150 +15,18 @@
*/
package org.apache.jackrabbit.core.version;
-import org.apache.commons.collections.ReferenceMap;
import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.nodetype.NodeDefId;
-import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
-import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.PersistentItemStateProvider;
-import org.apache.jackrabbit.core.state.PersistentNodeState;
-import org.apache.jackrabbit.core.util.uuid.UUID;
-import org.apache.log4j.Logger;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.Workspace;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.*;
/**
- * This Class provides implements the persistent part of the versionin. the
- * current implementation uses the 'normal' repository content as storage.
+ * This interface defines the access to the persistence layer of the
+ * versioning. The way how the versions are stored may totaly differ from
+ * the way they are exposed to the client.
*/
-public class PersistentVersionManager {
-
-
- /**
- * the logger
- */
- private static Logger log = Logger.getLogger(PersistentVersionManager.class);
-
- /**
- * root path for version storage
- */
- public static final QName VERSION_HISTORY_ROOT_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "persistentVersionStorage");
-
- /**
- * name of the 'jcr:historyId' property
- */
- public static final QName PROPNAME_HISTORY_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "historyId");
- /**
- * name of the 'jcr:versionId' property
- */
- public static final QName PROPNAME_VERSION_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionId");
- /**
- * name of the 'jcr:versionLabels' node
- */
- public static final QName NODENAME_VERSION_LABELS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionLabels");
- /**
- * name of the 'jcr:frozen' property
- */
- public static final QName NODENAME_FROZEN = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozen");
- /**
- * name of the 'jcr:name' property
- */
- public static final QName PROPNAME_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "name");
- /**
- * name of the 'jcr:version' property
- */
- public static final QName PROPNAME_VERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "version");
-
- /**
- * the id of the persisten root node
- */
- private static final NodeId PERSISTENT_ROOT_ID = new NodeId("faceface-ab3b-48a9-b31b-e7d0a9c1c3b1");
-
- /**
- * the persistent root node of the version histories
- */
- private final PersistentNode historyRoot;
-
- /**
- * the state manager for the version storage
- */
- private PersistentItemStateProvider stateMgr;
-
- /**
- * the nodetype manager for the version storage
- */
- private NodeTypeManagerImpl ntMgr;
-
- /**
- * The representation version managers (per workspace)
- */
- private HashMap versionManagers = new HashMap();
-
- /**
- * the version histories. key=uuid, value=version history
- */
- private Map histories = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
-
- /**
- * Creates a new PersistentVersionManager.
- *
- * @param session
- * @throws RepositoryException
- */
- public PersistentVersionManager(SessionImpl session) throws RepositoryException {
- this.stateMgr = ((WorkspaceImpl) session.getWorkspace()).getPersistentStateManager();
- this.ntMgr = session.getNodeTypeManager();
-
- try {
- NodeImpl systemRoot = ((RepositoryImpl) session.getRepository()).getSystemRootNode(session);
- // enable this to make the persistence storage visible
- if (true) {
- // check for versionhistory root
- if (!systemRoot.hasNode(VERSION_HISTORY_ROOT_NAME)) {
- // if not exist, create
- systemRoot.addNode(VERSION_HISTORY_ROOT_NAME, NodeTypeRegistry.NT_UNSTRUCTURED);
- systemRoot.save();
- }
- PersistentNodeState nodeState = (PersistentNodeState) stateMgr.getItemState(new NodeId(systemRoot.getNode(VERSION_HISTORY_ROOT_NAME).internalGetUUID()));
- historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
- } else {
- if (!stateMgr.hasItemState(PERSISTENT_ROOT_ID)) {
- PersistentNodeState nodeState = stateMgr.createNodeState(PERSISTENT_ROOT_ID.getUUID(), NodeTypeRegistry.NT_UNSTRUCTURED, null);
- nodeState.setDefinitionId(new NodeDefId(ntMgr.getRootNodeDefinition().unwrap()));
- nodeState.store();
- historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
- } else {
- PersistentNodeState nodeState = (PersistentNodeState) stateMgr.getItemState(PERSISTENT_ROOT_ID);
- historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
- }
- }
- } catch (ItemStateException e) {
- throw new RepositoryException("Unable to initialize PersistentVersionManager: " + e.toString());
- }
- }
-
- /**
- * returns the version manager
- *
- * @return
- */
- public synchronized VersionManager getVersionManager(Workspace wsp) {
- VersionManager vm = (VersionManager) versionManagers.get(wsp.getName());
- if (vm == null) {
- vm = new VersionManager(this);
- versionManagers.put(wsp.getName(), vm);
- }
- return vm;
- }
-
+public interface PersistentVersionManager {
/**
* Creates a new Version History.
@@ -167,25 +35,8 @@
* @return the newly created version history.
* @throws RepositoryException
*/
- synchronized InternalVersionHistory createVersionHistory(NodeImpl node)
- throws RepositoryException {
-
- // create deep path
- String uuid = UUID.randomUUID().toString();
- QName historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid);
- if (historyRoot.hasNode(historyNodeName)) {
- historyRoot.removeNode(historyNodeName);
- historyRoot.store();
- }
-
- // create new history node in the persistent state
- InternalVersionHistory hist = InternalVersionHistory.create(this, historyRoot, uuid, historyNodeName, node);
- histories.put(hist.getId(), hist);
-
- // notify version managers
- onVersionHistoryModified(hist);
- return hist;
- }
+ public InternalVersionHistory createVersionHistory(NodeImpl node)
+ throws RepositoryException;
/**
* returns the internal version history for the id
@@ -194,21 +45,8 @@
* @return
* @throws RepositoryException
*/
- synchronized InternalVersionHistory getVersionHistory(String histId)
- throws RepositoryException {
-
- InternalVersionHistory hist = (InternalVersionHistory) histories.get(histId);
- if (hist == null) {
- // we cannot used the uuid, since the persistent state do not share the same ids
- QName historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, histId);
- PersistentNode hNode = historyRoot.getNode(historyNodeName, 1);
- if (hNode != null) {
- hist = new InternalVersionHistory(this, hNode);
- histories.put(histId, hist);
- }
- }
- return hist;
- }
+ public InternalVersionHistory getVersionHistory(String histId)
+ throws RepositoryException;
/**
* Checks if the versionhistory for the given id exists
@@ -216,28 +54,15 @@
* @param histId
* @return
*/
- synchronized boolean hasVersionHistory(String histId) {
- if (histories.containsKey(histId)) {
- return true;
- } else {
- return historyRoot.hasNode(new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, histId));
- }
- }
+ public boolean hasVersionHistory(String histId);
/**
- * returns an iterator over all existing version histories
+ * returns an iterator over the external ids of the version histories
*
* @return
* @throws RepositoryException
*/
- synchronized Iterator getVersionHistories() throws RepositoryException {
- PersistentNode[] ph = historyRoot.getChildNodes();
- ArrayList list = new ArrayList(ph.length);
- for (int i = 0; i < ph.length; i++) {
- list.add(getVersionHistory(ph[i].getName().getLocalName()));
- }
- return list.iterator();
- }
+ public Iterator getVersionHistoryIds() throws RepositoryException;
/**
* returns the number of version histories
@@ -245,9 +70,7 @@
* @return
* @throws RepositoryException
*/
- synchronized int getNumVersionHistories() throws RepositoryException {
- return historyRoot.getChildNodes().length;
- }
+ public int getNumVersionHistories() throws RepositoryException;
/**
* returns the internal version for the id
@@ -256,11 +79,8 @@
* @return
* @throws RepositoryException
*/
- synchronized InternalVersion getVersion(String histId, String versionId)
- throws RepositoryException {
- InternalVersionHistory history = getVersionHistory(histId);
- return history.getVersion(versionId);
- }
+ public InternalVersion getVersion(String histId, String versionId)
+ throws RepositoryException;
/**
* returns the version with the given id
@@ -269,20 +89,8 @@
* @return
* @throws RepositoryException
*/
- synchronized InternalVersion getVersion(String versionId)
- throws RepositoryException {
-
- // todo: implement better
- PersistentNode[] ph = historyRoot.getChildNodes();
- for (int i = 0; i < ph.length; i++) {
- InternalVersionHistory vh = getVersionHistory(ph[i].getName().getLocalName());
- InternalVersion v = vh.getVersion(versionId);
- if (v != null) {
- return v;
- }
- }
- return null;
- }
+ public InternalVersion getVersion(String versionId)
+ throws RepositoryException;
/**
* Checks if the version with the given id exists
@@ -290,47 +98,32 @@
* @param versionId
* @return
*/
- synchronized boolean hasVersion(String versionId) {
- // todo: implement better
- try {
- PersistentNode[] ph = historyRoot.getChildNodes();
- for (int i = 0; i < ph.length; i++) {
- InternalVersionHistory vh = getVersionHistory(ph[i].getName().getLocalName());
- if (vh.hasVersion(versionId)) {
- return true;
- }
- }
- } catch (RepositoryException e) {
- // ignore
- }
- return false;
- }
+ public boolean hasVersion(String versionId);
/**
- * is informed by the versions if they were modified
- *
- * @param version
+ * checks, if the item with the given external id exists
+ * @param externalId
+ * @return
*/
- void onVersionModified(InternalVersion version) throws RepositoryException {
- // check if version manager already generated item states
- Iterator iter = versionManagers.values().iterator();
- while (iter.hasNext()) {
- ((VersionManager) iter.next()).onVersionModified(version);
- }
- }
+ public boolean hasItem(String externalId);
/**
- * is informed by the versions if they were modified
- *
- * @param vh
+ * returns the item referred by the external id
+ * @param externalId
+ * @return
+ * @throws RepositoryException
*/
- void onVersionHistoryModified(InternalVersionHistory vh) throws RepositoryException {
- // check if version manager already generated item states
- Iterator iter = versionManagers.values().iterator();
- while (iter.hasNext()) {
- ((VersionManager) iter.next()).onVersionHistoryModified(vh);
- }
- }
+ public InternalVersionItem getItemByExternal(String externalId)
+ throws RepositoryException;
+
+ /**
+ * returns the item referred by the internal id
+ * @param internalId
+ * @return
+ * @throws RepositoryException
+ */
+ public InternalVersionItem getItemByInternal(String internalId)
+ throws RepositoryException;
/**
* Checks in a node
@@ -340,50 +133,6 @@
* @throws RepositoryException
* @see Node#checkin()
*/
- synchronized InternalVersion checkin(NodeImpl node) throws RepositoryException {
- // assuming node is versionable and checkout (check in nodeimpl)
- // To create a new version of a versionable node N, the client calls N.checkin.
- // This causes the following series of events:
- String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
- InternalVersionHistory history = getVersionHistory(histUUID);
-
- // 0. resolve the predecessors
- Value[] values = node.getProperty(VersionManager.PROPNAME_PREDECESSORS).getValues();
- InternalVersion[] preds = new InternalVersion[values.length];
- for (int i = 0; i < values.length; i++) {
- preds[i] = history.getVersion(values[i].getString());
- }
-
- // 0.1 search a predecessor, suitable for generating the new name
- String versionName = null;
- int maxDots = Integer.MAX_VALUE;
- for (int i = 0; i < preds.length; i++) {
- // take the first pred. without a successor
- if (preds[i].getSuccessors().length == 0) {
- versionName = preds[i].getName().getLocalName(); //assuming no namespaces in version names
- // need to count the dots
- int pos = -1;
- int numDots = 0;
- while (versionName.indexOf('.', pos + 1) >= 0) {
- pos = versionName.indexOf('.', pos + 1);
- numDots++;
- }
- if (numDots < maxDots) {
- maxDots = numDots;
- versionName = pos < 0 ? "1.0" : versionName.substring(0, pos + 1) + (Integer.parseInt(versionName.substring(pos + 1)) + 1);
- }
- break;
- }
- }
- // if no empty found, generate new name
- if (versionName == null) {
- versionName = preds[0].getName().getLocalName();
- do {
- versionName += ".1";
- } while (history.hasVersion(new QName("", versionName)));
- }
-
- return history.checkin(new QName("", versionName), node);
- }
+ public InternalVersion checkin(NodeImpl node) throws RepositoryException;
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java Mon Dec 20 02:29:45 2004
@@ -49,7 +49,7 @@
* @param history
* @throws RepositoryException
*/
- protected VersionHistoryImpl(ItemManager itemMgr, SessionImpl session, NodeId id,
+ public VersionHistoryImpl(ItemManager itemMgr, SessionImpl session, NodeId id,
NodeState state, NodeDef definition,
ItemLifeCycleListener[] listeners,
InternalVersionHistory history) throws RepositoryException {
@@ -108,11 +108,7 @@
throws VersionException, RepositoryException {
try {
QName name = QName.fromJCRName(version, session.getNamespaceResolver());
- InternalVersion v = history.getVersion(name);
- if (v == null) {
- throw new VersionException("Version " + version + " does not exist in this version history.");
- }
- history.addVersionLabel(v, label, move);
+ history.addVersionLabel(name, label, move);
} catch (IllegalNameException e) {
throw new RepositoryException(e);
} catch (UnknownPrefixException e) {
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryNodeState.java Mon Dec 20 02:29:45 2004
@@ -16,6 +16,8 @@
package org.apache.jackrabbit.core.version;
import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.version.InternalVersionHistory;
+import org.apache.jackrabbit.core.version.InternalVersion;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.jackrabbit.core.virtual.VirtualNodeState;
@@ -25,30 +27,48 @@
import java.util.List;
/**
- * This Class implements...
+ * This Class implements the virtual node state for a version history.
*/
public class VersionHistoryNodeState extends VirtualNodeState {
+ /**
+ * the rerpesenting version history
+ */
private final InternalVersionHistory vh;
- public VersionHistoryNodeState(VersionItemStateProvider vm, InternalVersionHistory vh, String parentUUID) {
- super(vm, vh.getId(), NodeTypeRegistry.NT_VERSION_HISTORY, parentUUID);
+ /**
+ * Creates a new versiom history node state
+ * @param vm
+ * @param vh
+ * @param parentUUID
+ * @throws RepositoryException
+ */
+ protected VersionHistoryNodeState(VersionItemStateProvider vm,
+ InternalVersionHistory vh,
+ String parentUUID)
+ throws RepositoryException {
+ super(vm, parentUUID, vh.getId(), NodeTypeRegistry.NT_VERSION_HISTORY, new QName[0]);
this.vh = vh;
-
- setDefinitionId(vm.getNodeDefId(NodeTypeRegistry.NT_VERSION_HISTORY));
- // we do not initialize the childnode entry array, but rather
- // generate it every time.
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#hasChildNodeEntry(org.apache.jackrabbit.core.QName)
+ */
public synchronized boolean hasChildNodeEntry(QName name) {
return vh.hasVersion(name);
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#hasChildNodeEntry(org.apache.jackrabbit.core.QName, int)
+ */
public synchronized boolean hasChildNodeEntry(QName name, int index) {
// no same name siblings
return index <= 1 ? vh.hasVersion(name) : false;
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#getChildNodeEntry(org.apache.jackrabbit.core.QName, int)
+ */
public synchronized ChildNodeEntry getChildNodeEntry(QName nodeName, int index) {
try {
if (index <= 1) {
@@ -61,6 +81,9 @@
return null;
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#getChildNodeEntries()
+ */
public synchronized List getChildNodeEntries() {
Iterator iter = vh.getVersions();
ArrayList list = new ArrayList(vh.getNumVersions());
@@ -71,6 +94,9 @@
return list;
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#getChildNodeEntries(String)
+ */
public synchronized List getChildNodeEntries(String uuid) {
ArrayList list = new ArrayList(1);
InternalVersion v = vh.getVersion(uuid);
@@ -78,6 +104,9 @@
return list;
}
+ /**
+ * @see org.apache.jackrabbit.core.state.NodeState#getChildNodeEntries(org.apache.jackrabbit.core.QName)
+ */
public synchronized List getChildNodeEntries(QName nodeName) {
ArrayList list = new ArrayList(1);
try {
@@ -88,5 +117,4 @@
}
return list;
}
-
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java Mon Dec 20 02:29:45 2004
@@ -47,7 +47,7 @@
* @param version
* @throws RepositoryException
*/
- protected VersionImpl(ItemManager itemMgr, SessionImpl session, NodeId id,
+ public VersionImpl(ItemManager itemMgr, SessionImpl session, NodeId id,
NodeState state, NodeDef definition,
ItemLifeCycleListener[] listeners, InternalVersion version)
throws RepositoryException {
@@ -66,14 +66,14 @@
* @see Version#getVersionLabels()
*/
public String[] getVersionLabels() throws RepositoryException {
- return version.internalGetLabels();
+ return version.getLabels();
}
/**
* @see Version#hasVersionLabel
*/
public boolean hasVersionLabel(String label) {
- return version.internalHasLabel(label);
+ return version.hasLabel(label);
}
/**
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionItemStateProvider.java Mon Dec 20 02:29:45 2004
@@ -15,58 +15,97 @@
*/
package org.apache.jackrabbit.core.version;
-import org.apache.jackrabbit.core.ItemId;
-import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.QName;
-import org.apache.jackrabbit.core.nodetype.NodeDefId;
-import org.apache.jackrabbit.core.nodetype.PropDefId;
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.version.*;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.nodetype.*;
import org.apache.jackrabbit.core.state.*;
-import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
-import org.apache.jackrabbit.core.virtual.VirtualNodeState;
+import org.apache.jackrabbit.core.virtual.*;
import org.apache.log4j.Logger;
import org.apache.commons.collections.ReferenceMap;
import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
+import javax.jcr.nodetype.ConstraintViolationException;
import java.util.Map;
+import java.util.HashSet;
/**
- * This Class implements...
+ * This Class implements a virtual item state provider, in order to expose the
+ * versions to the version storage.
*/
public class VersionItemStateProvider implements VirtualItemStateProvider {
-
/**
* the default logger
*/
private static Logger log = Logger.getLogger(VersionItemStateProvider.class);
-
+ /**
+ * the root node
+ */
private final HistoryRootNodeState root;
-
+ /**
+ * the version manager
+ */
private final VersionManager vMgr;
-
+ /**
+ * the node type manager
+ */
+ private final NodeTypeManagerImpl ntMgr;
/**
* the version histories. key=ItemId, value=ItemState
*/
private Map items = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
+ /**
+ * node def id for a unstructured node state
+ */
+ private NodeDefId NDEF_UNSTRUCTURED;
+ /**
+ * node def id for a version node state
+ */
+ private NodeDefId NDEF_VERSION;
+ /**
+ * node def id ofr a version history node state
+ */
+ private NodeDefId NDEF_VERSION_HISTORY;
-
- public VersionItemStateProvider(VersionManager vMgr, String rootId, String parentId) {
+ /**
+ * creates a new version item state provide
+ * @param vMgr
+ * @param rootId
+ * @param parentId
+ * @throws RepositoryException
+ */
+ public VersionItemStateProvider(VersionManager vMgr, NodeTypeManagerImpl ntMgr, String rootId, String parentId) throws RepositoryException {
this.vMgr = vMgr;
- this.root = new HistoryRootNodeState(this, rootId, parentId);
- }
+ this.ntMgr = ntMgr;
+ NDEF_UNSTRUCTURED = new NodeDefId(getNodeTypeManager().getNodeType(NodeTypeRegistry.NT_UNSTRUCTURED).getApplicableChildNodeDef(VersionManager.NODENAME_ROOTVERSION, NodeTypeRegistry.NT_UNSTRUCTURED).unwrap());
+ NDEF_VERSION = new NodeDefId(getNodeTypeManager().getNodeType(NodeTypeRegistry.NT_VERSION_HISTORY).getApplicableChildNodeDef(VersionManager.NODENAME_ROOTVERSION, NodeTypeRegistry.NT_VERSION).unwrap());
+ NDEF_VERSION_HISTORY = new NodeDefId(getNodeTypeManager().getNodeType(NodeTypeRegistry.NT_UNSTRUCTURED).getApplicableChildNodeDef(VersionManager.NODENAME_ROOTVERSION, NodeTypeRegistry.NT_VERSION_HISTORY).unwrap());
- public VersionManager getVersionManager() {
- return vMgr;
+ this.root = new HistoryRootNodeState(this, vMgr, parentId, rootId);
+ this.root.setDefinitionId(NDEF_UNSTRUCTURED);
}
- public boolean isVirtualRoot(ItemId id) {
- return id.equals(root.getId());
- }
+ //--------------------------------------------------< ItemStateProvider >---
- public NodeId getVirtualRootId() {
- return (NodeId) root.getId();
+ /**
+ * @see ItemStateProvider#hasItemState(org.apache.jackrabbit.core.ItemId)
+ */
+ public boolean hasItemState(ItemId id) {
+
+ // check cache
+ if (items.containsKey(id)) {
+ return true;
+ } else if (id instanceof NodeId) {
+ return hasNodeState((NodeId) id);
+ } else {
+ return hasPropertyState((PropertyId) id);
+ }
}
+ /**
+ * @see ItemStateProvider#getItemState(org.apache.jackrabbit.core.ItemId)
+ */
public ItemState getItemState(ItemId id)
throws NoSuchItemStateException, ItemStateException {
@@ -79,28 +118,61 @@
}
// add state to cache
items.put(id, state);
+ log.info("item added to cache. size=" + items.size());
}
return state;
}
+ /**
+ * virtual item state provider do not have attics.
+ *
+ * @throws NoSuchItemStateException always
+ */
+ public ItemState getItemStateInAttic(ItemId id) throws NoSuchItemStateException {
+ // never has states in attic
+ throw new NoSuchItemStateException(id.toString());
+ }
+
+ /**
+ * virtual item state provider do not have attics.
+ *
+ * @return <code>false</code>
+ */
+ public boolean hasItemStateInAttic(ItemId id) {
+ // never has states in attic
+ return false;
+ }
+
+ //-------------------------------------------< VirtualItemStateProvider >---
+
+ /**
+ * @see VirtualItemStateProvider#isVirtualRoot(org.apache.jackrabbit.core.ItemId)
+ */
+ public boolean isVirtualRoot(ItemId id) {
+ return id.equals(root.getId());
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.virtual.VirtualItemStateProvider#getVirtualRootId()
+ */
+ public NodeId getVirtualRootId() {
+ return (NodeId) root.getId();
+ }
+
+ /**
+ * @see VirtualItemStateProvider#hasNodeState(NodeId)
+ */
public boolean hasNodeState(NodeId id) {
if (id.equals(root.getId())) {
return true;
}
-
- // check version history
- if (vMgr.hasVersionHistory(id.getUUID())) {
- return true;
- }
- // check verion
- if (vMgr.hasVersion(id.getUUID())) {
- return true;
- }
-
- return false;
+ return vMgr.hasItem(id.getUUID());
}
- public NodeState getNodeState(NodeId id)
+ /**
+ * @see VirtualItemStateProvider#getNodeState(org.apache.jackrabbit.core.NodeId)
+ */
+ public VirtualNodeState getNodeState(NodeId id)
throws NoSuchItemStateException, ItemStateException {
// check if root
@@ -108,33 +180,80 @@
return root;
}
- // check version history
try {
- InternalVersionHistory vh = vMgr.getVersionHistory(id.getUUID());
- if (vh != null) {
- return new VersionHistoryNodeState(this, vh, root.getUUID());
+ InternalVersionItem vi = vMgr.getItem(id.getUUID());
+ if (vi instanceof InternalVersionHistory) {
+ VersionHistoryNodeState ns = new VersionHistoryNodeState(this, (InternalVersionHistory) vi, root.getUUID());
+ ns.setDefinitionId(NDEF_VERSION_HISTORY);
+ return ns;
+
+ } else if (vi instanceof InternalVersion) {
+ InternalVersion v = (InternalVersion) vi;
+ VersionNodeState ns = new VersionNodeState(this, v, vi.getParent().getId());
+ ns.setDefinitionId(NDEF_VERSION);
+ ns.setPropertyValue(VersionManager.PROPNAME_CREATED, InternalValue.create(v.getCreated()));
+ ns.setPropertyValue(VersionManager.PROPNAME_FROZEN_UUID, InternalValue.create(v.getFrozenNode().getFrozenUUID()));
+ ns.setPropertyValue(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE, InternalValue.create(v.getFrozenNode().getFrozenPrimaryType()));
+ ns.setPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, PropertyType.NAME, InternalValue.create(v.getFrozenNode().getFrozenMixinTypes()));
+ ns.setPropertyValues(VersionManager.PROPNAME_VERSION_LABELS, PropertyType.STRING, InternalValue.create(v.getLabels()));
+ ns.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.REFERENCE, new InternalValue[0]);
+ ns.setPropertyValues(VersionManager.PROPNAME_SUCCESSORS, PropertyType.REFERENCE, new InternalValue[0]);
+ return ns;
+
+ } else if (vi instanceof InternalFrozenNode) {
+ InternalFrozenNode fn = (InternalFrozenNode) vi;
+ VirtualNodeState parent = getNodeState(new NodeId(fn.getParent().getId()));
+ VirtualNodeState state = createNodeState(
+ parent,
+ VersionManager.NODENAME_FROZEN,
+ id.getUUID(),
+ fn.getFrozenPrimaryType());
+ mapFrozenNode(state, fn);
+ return state;
+
+ } else if (vi instanceof InternalFrozenVersionHistory) {
+ InternalFrozenVersionHistory fn = (InternalFrozenVersionHistory) vi;
+ VirtualNodeState parent = getNodeState(new NodeId(fn.getParent().getId()));
+ VirtualNodeState state = createNodeState(
+ parent,
+ VersionManager.NODENAME_FROZEN,
+ id.getUUID(),
+ NodeTypeRegistry.NT_FROZEN_VERSIONABLE_CHILD);
+ mapFrozenNode(state, fn);
+ return state;
}
} catch (RepositoryException e) {
- log.error("Unable to check for version history:" + e.toString());
+ log.error("Unable to check for item:" + e.toString());
throw new ItemStateException(e);
}
- // check version
+ // not found, throw
+ throw new NoSuchItemStateException(id.toString());
+ }
+
+ /**
+ * @see VirtualItemStateProvider#hasPropertyState(org.apache.jackrabbit.core.PropertyId)
+ */
+ public boolean hasPropertyState(PropertyId id) {
+
try {
- InternalVersion v = vMgr.getVersion(id.getUUID());
- if (v != null) {
- return new VersionNodeState(this, v);
+ // get parent state
+ NodeState parent = getNodeState(new NodeId(id.getParentUUID()));
+
+ // handle some default prop states
+ if (parent instanceof VirtualNodeState) {
+ return ((VirtualNodeState) parent).hasPropertyEntry(id.getName());
}
- } catch (RepositoryException e) {
- log.error("Unable to check for version:" + e.toString());
- throw new ItemStateException(e);
+ } catch (ItemStateException e) {
+ // ignore
}
-
- // not found, throw
- throw new NoSuchItemStateException(id.toString());
+ return false;
}
- public PropertyState getPropertyState(PropertyId id)
+ /**
+ * @see VirtualItemStateProvider#getPropertyState(org.apache.jackrabbit.core.PropertyId)
+ */
+ public VirtualPropertyState getPropertyState(PropertyId id)
throws NoSuchItemStateException, ItemStateException {
// get parent state
@@ -142,65 +261,177 @@
// handle some default prop states
if (parent instanceof VirtualNodeState) {
- return ((VirtualNodeState) parent).getPropertyState(id.getName());
+ return ((VirtualNodeState) parent).getProperty(id.getName());
}
throw new NoSuchItemStateException(id.toString());
}
- public boolean hasPropertyState(PropertyId id) {
+ /**
+ * @see VirtualItemStateProvider#createPropertyState(org.apache.jackrabbit.core.virtual.VirtualNodeState, org.apache.jackrabbit.core.QName, int, boolean)
+ */
+ public VirtualPropertyState createPropertyState(VirtualNodeState parent,
+ QName name, int type,
+ boolean multiValued)
+ throws RepositoryException {
+ PropertyDefImpl def = getApplicablePropertyDef(parent, name, type, multiValued);
+ VirtualPropertyState prop = new VirtualPropertyState(name, parent.getUUID());
+ prop.setType(type);
+ prop.setMultiValued(multiValued);
+ prop.setDefinitionId(new PropDefId(def.unwrap()));
+ items.put(prop.getId(), prop);
+ return prop;
+ }
- try {
- // get parent state
- NodeState parent = getNodeState(new NodeId(id.getParentUUID()));
+ /**
+ * @see VirtualItemStateProvider#createNodeState(org.apache.jackrabbit.core.virtual.VirtualNodeState, org.apache.jackrabbit.core.QName, String, org.apache.jackrabbit.core.QName)
+ */
+ public VirtualNodeState createNodeState(VirtualNodeState parent, QName name,
+ String uuid, QName nodeTypeName)
+ throws RepositoryException {
- // handle some default prop states
- if (parent instanceof VirtualNodeState) {
- return ((VirtualNodeState) parent).getPropertyState(id.getName()) != null;
+ NodeTypeImpl nodeType = getNodeTypeManager().getNodeType(nodeTypeName);
+ NodeDefImpl def;
+ try {
+ def = getApplicableChildNodeDef(parent, name, nodeType == null ? null : nodeType.getQName());
+ } catch (RepositoryException re) {
+ // hack, use nt:unstructured as parent
+ try {
+ NodeTypeRegistry ntReg = getNodeTypeManager().getNodeTypeRegistry();
+ EffectiveNodeType ent = ntReg.buildEffectiveNodeType(new QName[]{NodeTypeRegistry.NT_UNSTRUCTURED});
+ ChildNodeDef cnd = ent.getApplicableChildNodeDef(name, nodeTypeName);
+ def = getNodeTypeManager().getNodeDef(new NodeDefId(cnd));
+ } catch (NodeTypeConflictException e) {
+ String msg = "no definition found in parent node's node type for new node";
+ throw new ConstraintViolationException(msg, re);
}
- } catch (ItemStateException e) {
- // ignore
}
- return false;
+ if (nodeType == null) {
+ // use default node type
+ nodeType = (NodeTypeImpl) def.getDefaultPrimaryType();
+ }
+
+ // create a new node state
+ VirtualNodeState state = null;
+ if (uuid == null) {
+ uuid = UUID.randomUUID().toString(); // version 4 uuid
+ }
+ state = new VirtualNodeState(this, parent.getUUID(), uuid, nodeTypeName, new QName[0]);
+ state.setDefinitionId(new NodeDefId(def.unwrap()));
+
+ items.put(state.getId(), state);
+ return state;
}
- public boolean hasItemState(ItemId id) {
+ //-----------------------------------------------------< internal stuff >---
- // check cache
- if (items.containsKey(id)) {
- return true;
- } else if (id instanceof NodeId) {
- return hasNodeState((NodeId) id);
- } else {
- return hasPropertyState((PropertyId) id);
- }
+ /**
+ * returns the node type manager
+ * @return
+ */
+ private NodeTypeManagerImpl getNodeTypeManager() {
+ return ntMgr;
}
- public NodeDefId getNodeDefId(QName nodename) {
- return vMgr.getNodeDefId(nodename);
+ /**
+ * mapps a frozen node
+ * @param state
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ private VirtualNodeState mapFrozenNode(VirtualNodeState state,
+ InternalFrozenNode node)
+ throws RepositoryException {
+
+ // map native stuff
+ state.setMixinNodeTypes(node.getFrozenMixinTypes());
+ if (node.getFrozenUUID()!=null) {
+ state.setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(node.getFrozenUUID()));
+ }
+
+ // map properties
+ PropertyState[] props = node.getFrozenProperties();
+ for (int i=0; i<props.length; i++) {
+ if (props[i].isMultiValued()) {
+ state.setPropertyValues(props[i].getName(), props[i].getType(), props[i].getValues());
+ } else {
+ state.setPropertyValue(props[i].getName(), props[i].getValues()[0]);
+ }
+ }
+ // map child nodes
+ InternalFreeze[] nodes = node.getFrozenChildNodes();
+ for (int i=0; i<nodes.length; i++) {
+ state.addChildNodeEntry(nodes[i].getName(), nodes[i].getId());
+ }
+ return state;
}
- public PropDefId getPropDefId(QName propname) {
- return vMgr.getPropDefId(propname);
+ /**
+ * maps a frozen node
+ * @param state
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ private VirtualNodeState mapFrozenNode(VirtualNodeState state,
+ InternalFrozenVersionHistory node)
+ throws RepositoryException {
+
+ // map properties
+ state.setPropertyValue(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(node.getBaseVersionId()));
+ state.setPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY, InternalValue.create(node.getVersionHistoryId()));
+ return state;
}
/**
- * virtual item state provider do not have attics.
+ * retrieves the property definition for the given contraints
*
- * @throws NoSuchItemStateException always
+ * @param propertyName
+ * @param type
+ * @param multiValued
+ * @return
+ * @throws RepositoryException
*/
- public ItemState getItemStateInAttic(ItemId id) throws NoSuchItemStateException {
- // never has states in attic
- throw new NoSuchItemStateException(id.toString());
+ protected PropertyDefImpl getApplicablePropertyDef(NodeState parent, QName propertyName,
+ int type, boolean multiValued)
+ throws RepositoryException {
+ PropDef pd = getEffectiveNodeType(parent).getApplicablePropertyDef(propertyName, type, multiValued);
+ return getNodeTypeManager().getPropDef(new PropDefId(pd));
}
/**
- * virtual item state provider do not have attics.
+ * Retrieves the node definition for the given contraints.
*
- * @return <code>false</code>
+ * @param nodeName
+ * @param nodeTypeName
+ * @return
+ * @throws RepositoryException
*/
- public boolean hasItemStateInAttic(ItemId id) {
- // never has states in attic
- return false;
+ protected NodeDefImpl getApplicableChildNodeDef(NodeState parent, QName nodeName, QName nodeTypeName)
+ throws RepositoryException {
+ ChildNodeDef cnd = getEffectiveNodeType(parent).getApplicableChildNodeDef(nodeName, nodeTypeName);
+ return getNodeTypeManager().getNodeDef(new NodeDefId(cnd));
}
+ /**
+ * Returns the effective (i.e. merged and resolved) node type representation
+ * of this node's primary and mixin node types.
+ *
+ * @return the effective node type
+ * @throws RepositoryException
+ */
+ protected EffectiveNodeType getEffectiveNodeType(NodeState parent) throws RepositoryException {
+ // build effective node type of mixins & primary type
+ NodeTypeRegistry ntReg = getNodeTypeManager().getNodeTypeRegistry();
+ // existing mixin's
+ HashSet set = new HashSet(parent.getMixinTypeNames());
+ // primary type
+ set.add(parent.getNodeTypeName());
+ try {
+ return ntReg.buildEffectiveNodeType((QName[]) set.toArray(new QName[set.size()]));
+ } catch (NodeTypeConflictException ntce) {
+ String msg = "internal error: failed to build effective node type for node " + parent.getUUID();
+ throw new RepositoryException(msg, ntce);
+ }
+ }
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java Mon Dec 20 02:29:45 2004
@@ -16,41 +16,28 @@
package org.apache.jackrabbit.core.version;
import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.nodetype.NodeDefId;
-import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
-import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.nodetype.PropDefId;
import org.apache.jackrabbit.core.state.ItemStateProvider;
-import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
-import org.apache.log4j.Logger;
-import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.nodetype.NodeDef;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
-import java.util.HashMap;
import java.util.Iterator;
/**
- * This Class implements the session tied version manager. It is also repsonsible
- * for mapping the internal versions to the presentation layer using virtual
- * nodes and items.
+ * This interface defines the version manager. It gives access to the underlaying
+ * persistence layer of the versioning.
*/
-public class VersionManager {
-
- /**
- * the default logger
- */
- private static Logger log = Logger.getLogger(VersionManager.class);
-
+public interface VersionManager {
/**
* root path for version storage
*/
public static final QName NODENAME_HISTORY_ROOT = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionStorage");
/**
+ * the name of the frozen node
+ */
+ public static final QName NODENAME_FROZEN = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozen");
+ /**
* name of the 'jcr:frozenUUID' property
*/
public static final QName PROPNAME_FROZEN_UUID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozenUUID");
@@ -96,81 +83,14 @@
public static final QName NODENAME_ROOTVERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "rootVersion");
/**
- * The version manager of the internal versions
- */
- private final PersistentVersionManager vMgr;
-
- /**
- * The virtual item manager that exposes the versions to the content
- */
- private VersionItemStateProvider virtProvider;
-
- /**
- * the definition id manager helper class
- */
- private DefinitionIdMgr idMgr;
-
-
- /**
- * @param vMgr
- */
- protected VersionManager(PersistentVersionManager vMgr) {
- this.vMgr = vMgr;
- }
-
- /**
* returns the virtual item state provider that exposes the internal versions
* as items.
*
* @param base
* @return
*/
- public synchronized VirtualItemStateProvider getVirtualItemStateProvider(SessionImpl session, ItemStateProvider base) {
- if (virtProvider == null) {
- try {
- // init the definition id mgr
- idMgr = new DefinitionIdMgr(session.getNodeTypeManager());
-
- session.getNodeTypeManager().getNodeType(NodeTypeRegistry.NT_BASE).getApplicablePropertyDef(ItemImpl.PROPNAME_PRIMARYTYPE, PropertyType.NAME, false).unwrap();
- // check, if workspace of session has history root
- NodeImpl systemRoot = ((RepositoryImpl) session.getRepository()).getSystemRootNode(session);
- if (!systemRoot.hasNode(VersionManager.NODENAME_HISTORY_ROOT)) {
- // if not exist, create
- systemRoot.addNode(VersionManager.NODENAME_HISTORY_ROOT, NodeTypeRegistry.NT_UNSTRUCTURED);
- }
- systemRoot.save();
- String rootId = systemRoot.getNode(VersionManager.NODENAME_HISTORY_ROOT).internalGetUUID();
-
- NodeState virtRootState = (NodeState) base.getItemState(new NodeId(rootId));
- virtProvider = new VersionItemStateProvider(this, rootId, virtRootState.getParentUUID());
- } catch (Exception e) {
- // todo: better error handling
- log.error("Error while initializing virtual items.", e);
- throw new IllegalStateException(e.toString());
- }
- }
- return virtProvider;
- }
-
- /**
- * returns the node definition id for the given name
- *
- * @param name
- * @return
- */
- public NodeDefId getNodeDefId(QName name) {
- return idMgr.getNodeDefId(name);
- }
-
- /**
- * returns the property definition id for the given name
- *
- * @param name
- * @return
- */
- public PropDefId getPropDefId(QName name) {
- return idMgr.getPropDefId(name);
- }
+ public VirtualItemStateProvider getVirtualItemStateProvider(SessionImpl session,
+ ItemStateProvider base);
/**
* Creates a new version history. This action is needed either when creating
@@ -181,10 +101,8 @@
* @return
* @throws RepositoryException
*/
- public VersionHistory createVersionHistory(NodeImpl node) throws RepositoryException {
- InternalVersionHistory history = vMgr.createVersionHistory(node);
- return (VersionHistory) node.getSession().getNodeByUUID(history.getId());
- }
+ public VersionHistory createVersionHistory(NodeImpl node) throws RepositoryException;
+
/**
* Returns the base version of the given node. assuming mix:versionable
@@ -193,12 +111,7 @@
* @return
* @throws RepositoryException
*/
- public Version getBaseVersion(NodeImpl node) throws RepositoryException {
- String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
- InternalVersionHistory history = vMgr.getVersionHistory(histUUID);
- InternalVersion version = history.getVersion(node.getProperty(PROPNAME_BASE_VERSION).getString());
- return version == null ? null : (Version) node.getSession().getNodeByUUID(version.getId());
- }
+ public Version getBaseVersion(NodeImpl node) throws RepositoryException;
/**
* Returns the version history for the given node. assuming mix:versionable
@@ -209,38 +122,19 @@
* @throws RepositoryException
*/
public VersionHistory getVersionHistory(NodeImpl node)
- throws RepositoryException {
- String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
- InternalVersionHistory history = vMgr.getVersionHistory(histUUID);
- return (VersionHistory) node.getSession().getNodeByUUID(history.getId());
- }
-
- //-----------------------------------------------------< internal stuff >---
+ throws RepositoryException;
/**
- * Checks, if the version history with the given name exists
- *
- * @param name
- * @return
- */
- boolean hasVersionHistory(QName name) {
- // name is uuid of version history
- String id = name.getLocalName();
- return vMgr.hasVersionHistory(id);
- }
-
- /**
- * Returns the vesion history impl for the given name
+ * invokes the checkin() on the persistent version manager and remaps the
+ * newly created version objects.
*
- * @param name
+ * @param node
* @return
* @throws RepositoryException
*/
- InternalVersionHistory getVersionHistory(QName name) throws RepositoryException {
- // name is uuid of version history
- String id = name.getLocalName();
- return vMgr.getVersionHistory(id);
- }
+ public Version checkin(NodeImpl node) throws RepositoryException;
+
+ //-----------------------------------------------------< internal stuff >---
/**
* Checks if the version history with the given id exists
@@ -248,9 +142,7 @@
* @param id
* @return
*/
- boolean hasVersionHistory(String id) {
- return vMgr.hasVersionHistory(id);
- }
+ public boolean hasVersionHistory(String id);
/**
* Returns the version history with the given id
@@ -259,9 +151,7 @@
* @return
* @throws RepositoryException
*/
- InternalVersionHistory getVersionHistory(String id) throws RepositoryException {
- return vMgr.getVersionHistory(id);
- }
+ public InternalVersionHistory getVersionHistory(String id) throws RepositoryException;
/**
* Returns the number of version histories
@@ -269,19 +159,15 @@
* @return
* @throws RepositoryException
*/
- int getNumVersionHistories() throws RepositoryException {
- return vMgr.getNumVersionHistories();
- }
+ public int getNumVersionHistories() throws RepositoryException;
/**
- * Returns an iterator over all {@link InternalVersionHistory}s.
+ * Returns an iterator over all ids of {@link InternalVersionHistory}s.
*
* @return
* @throws RepositoryException
*/
- Iterator getVersionHistories() throws RepositoryException {
- return vMgr.getVersionHistories();
- }
+ public Iterator getVersionHistoryIds() throws RepositoryException;
/**
* Checks if the version with the given id exists
@@ -289,9 +175,7 @@
* @param id
* @return
*/
- boolean hasVersion(String id) {
- return vMgr.hasVersion(id);
- }
+ boolean hasVersion(String id);
/**
* Returns the version with the given id
@@ -300,151 +184,21 @@
* @return
* @throws RepositoryException
*/
- InternalVersion getVersion(String id) throws RepositoryException {
- return vMgr.getVersion(id);
- }
+ InternalVersion getVersion(String id) throws RepositoryException;
/**
- * Creates a new VersionHistoryImpl instance. this is usually called by
- * the {@link ItemManager}.
- *
- * @param session
- * @param state
- * @param def
- * @param itemMgr
- * @param listeners
- * @return
- * @throws RepositoryException
- */
- public VersionHistoryImpl createVersionHistoryInstance(SessionImpl session,
- NodeState state, NodeDef def,
- ItemManager itemMgr,
- ItemLifeCycleListener[] listeners)
- throws RepositoryException {
- if (!state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION_HISTORY)) {
- throw new RepositoryException("node not nt:versionhistory");
- }
- NodeId nodeId = (NodeId) state.getId();
- InternalVersionHistory history = vMgr.getVersionHistory(nodeId.getUUID());
- return new VersionHistoryImpl(itemMgr, session, nodeId, state, def, listeners, history);
- }
-
- /**
- * Creates a new VersionImpl instance. this is usually called by
- * the {@link ItemManager}.
- *
- * @param session
- * @param state
- * @param def
- * @param itemMgr
- * @param listeners
+ * checks, if the node with the given id exists
+ * @param id
* @return
- * @throws RepositoryException
*/
- public VersionImpl createVersionInstance(SessionImpl session,
- NodeState state, NodeDef def,
- ItemManager itemMgr,
- ItemLifeCycleListener[] listeners)
- throws RepositoryException {
- if (!state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION)) {
- throw new RepositoryException("node not nt:version");
- }
- NodeId nodeId = (NodeId) state.getId();
- String historyId = state.getParentUUID();
- InternalVersionHistory history = vMgr.getVersionHistory(historyId);
- InternalVersion version = history.getVersion(nodeId.getUUID());
- return new VersionImpl(itemMgr, session, nodeId, state, def, listeners, version);
- }
+ public boolean hasItem(String id);
/**
- * invokes the checkin() on the persistent version manager and remaps the
- * newly created version objects.
- *
- * @param node
+ * Returns the version item with the given id
+ * @param id
* @return
* @throws RepositoryException
*/
- public synchronized Version checkin(NodeImpl node) throws RepositoryException {
- InternalVersion version = vMgr.checkin(node);
-
- vMgr.onVersionHistoryModified(version.getVersionHistory());
-
- // invalidate predecessors 'sucessors' properties
- InternalVersion[] pred = version.getPredecessors();
- for (int i = 0; i < pred.length; i++) {
- onVersionModified(pred[i]);
- }
-
- return (Version) node.getSession().getNodeByUUID(version.getId());
- }
-
- /**
- * Called when a internal version has changed its internal structure, and
- * some of the properties has to be remapped to the content.
- *
- * @param v
- * @throws RepositoryException
- */
- protected synchronized void onVersionModified(InternalVersion v)
- throws RepositoryException {
- }
+ public InternalVersionItem getItem(String id) throws RepositoryException;
- /**
- * Called when a internal version history has changed its internal structure,
- * and the structure has to be remapped to the content.
- *
- * @param vh
- * @throws RepositoryException
- */
- protected synchronized void onVersionHistoryModified(InternalVersionHistory vh)
- throws RepositoryException {
- }
-
- /**
- * Helper class that generates and hold generic definition ids
- */
- private static class DefinitionIdMgr {
-
- private final HashMap ids = new HashMap();
-
- private final NodeTypeManagerImpl ntMgr;
-
- public DefinitionIdMgr(NodeTypeManagerImpl ntMgr)
- throws NoSuchNodeTypeException, RepositoryException {
- this.ntMgr = ntMgr;
- add(VersionManager.NODENAME_ROOTVERSION, NodeTypeRegistry.NT_VERSION, NodeTypeRegistry.NT_VERSION_HISTORY);
- add(VersionManager.NODENAME_HISTORY_ROOT, NodeTypeRegistry.NT_UNSTRUCTURED, NodeTypeRegistry.NT_UNSTRUCTURED);
- add(NodeTypeRegistry.NT_VERSION_HISTORY, NodeTypeRegistry.NT_VERSION_HISTORY, NodeTypeRegistry.NT_UNSTRUCTURED);
- add(ItemImpl.PROPNAME_PRIMARYTYPE, NodeTypeRegistry.NT_BASE, PropertyType.NAME, false);
- add(ItemImpl.PROPNAME_MIXINTYPES, NodeTypeRegistry.NT_BASE, PropertyType.NAME, true);
- add(ItemImpl.PROPNAME_UUID, NodeTypeRegistry.MIX_REFERENCEABLE, PropertyType.STRING, false);
- add(VersionManager.PROPNAME_CREATED, NodeTypeRegistry.NT_VERSION, PropertyType.DATE, false);
- add(VersionManager.PROPNAME_FROZEN_UUID, NodeTypeRegistry.NT_VERSION, PropertyType.STRING, false);
- add(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE, NodeTypeRegistry.NT_VERSION, PropertyType.NAME, false);
- add(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, NodeTypeRegistry.NT_VERSION, PropertyType.NAME, true);
- add(VersionManager.PROPNAME_VERSION_LABELS, NodeTypeRegistry.NT_VERSION, PropertyType.STRING, true);
- add(VersionManager.PROPNAME_PREDECESSORS, NodeTypeRegistry.NT_VERSION, PropertyType.REFERENCE, true);
- add(VersionManager.PROPNAME_SUCCESSORS, NodeTypeRegistry.NT_VERSION, PropertyType.REFERENCE, true);
- }
-
- private void add(QName nodeName, QName nt, QName parentNt)
- throws NoSuchNodeTypeException, RepositoryException {
- NodeDefId id = new NodeDefId(ntMgr.getNodeType(parentNt).getApplicableChildNodeDef(nodeName, nt).unwrap());
- ids.put(nodeName, id);
- }
-
- private void add(QName propName, QName nt, int type, boolean multivalued)
- throws NoSuchNodeTypeException, RepositoryException {
- PropDefId id = new PropDefId(ntMgr.getNodeType(nt).getApplicablePropertyDef(propName, type, multivalued).unwrap());
- ids.put(propName, id);
- }
-
- public NodeDefId getNodeDefId(QName name) {
- return (NodeDefId) ids.get(name);
- }
-
- public PropDefId getPropDefId(QName name) {
- return (PropDefId) ids.get(name);
- }
- }
}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.state.ItemStateProvider;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
+import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.Version;
+import java.util.Iterator;
+
+/**
+ * This Class implements a VersionManager. It more or less acts as proxy
+ * between the virtual item state manager that exposes the version to the
+ * version storage ({@link VersionItemStateProvider}) and the persistent
+ * version manager.
+ */
+public class VersionManagerImpl implements VersionManager {
+
+ /**
+ * the default logger
+ */
+ private static Logger log = Logger.getLogger(VersionManager.class);
+ /**
+ * The version manager of the internal versions
+ */
+ private final PersistentVersionManager vMgr;
+ /**
+ * The virtual item manager that exposes the versions to the content
+ */
+ private VersionItemStateProvider virtProvider;
+ /**
+ * the node type manager
+ */
+ private NodeTypeManagerImpl ntMgr;
+
+
+ /**
+ * Creates a bew vesuion manager
+ * @param vMgr
+ */
+ public VersionManagerImpl(PersistentVersionManager vMgr) {
+ this.vMgr = vMgr;
+ }
+
+ /**
+ * returns the virtual item state provider that exposes the internal versions
+ * as items.
+ *
+ * @param base
+ * @return
+ */
+ public synchronized VirtualItemStateProvider getVirtualItemStateProvider(SessionImpl session, ItemStateProvider base) {
+ if (virtProvider == null) {
+ try {
+ // init the definition id mgr
+ ntMgr = session.getNodeTypeManager();
+ ntMgr.getNodeType(NodeTypeRegistry.NT_BASE).getApplicablePropertyDef(ItemImpl.PROPNAME_PRIMARYTYPE, PropertyType.NAME, false).unwrap();
+ // check, if workspace of session has history root
+ NodeImpl systemRoot = ((RepositoryImpl) session.getRepository()).getSystemRootNode(session);
+ if (!systemRoot.hasNode(VersionManager.NODENAME_HISTORY_ROOT)) {
+ // if not exist, create
+ systemRoot.addNode(VersionManager.NODENAME_HISTORY_ROOT, NodeTypeRegistry.NT_UNSTRUCTURED);
+ }
+ systemRoot.save();
+ String rootId = systemRoot.getNode(VersionManager.NODENAME_HISTORY_ROOT).internalGetUUID();
+
+ NodeState virtRootState = (NodeState) base.getItemState(new NodeId(rootId));
+ virtProvider = new VersionItemStateProvider(this, ntMgr, rootId, virtRootState.getParentUUID());
+ } catch (Exception e) {
+ // todo: better error handling
+ log.error("Error while initializing virtual items.", e);
+ throw new IllegalStateException(e.toString());
+ }
+ }
+ return virtProvider;
+ }
+
+ /**
+ * returns the node type manager
+ * @return
+ */
+ NodeTypeManagerImpl getNodeTypeManager() {
+ return ntMgr;
+ }
+
+ /**
+ * Creates a new version history. This action is needed either when creating
+ * a new 'mix:versionable' node or when adding the 'mix:versionalbe' mixin
+ * to a node.
+ *
+ * @param node
+ * @return
+ * @throws javax.jcr.RepositoryException
+ */
+ public VersionHistory createVersionHistory(NodeImpl node) throws RepositoryException {
+ InternalVersionHistory history = vMgr.createVersionHistory(node);
+ return (VersionHistory) node.getSession().getNodeByUUID(history.getId());
+ }
+
+ /**
+ * Returns the base version of the given node. assuming mix:versionable
+ *
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ public Version getBaseVersion(NodeImpl node) throws RepositoryException {
+ String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
+ InternalVersionHistory history = vMgr.getVersionHistory(histUUID);
+ InternalVersion version = history.getVersion(node.getProperty(PROPNAME_BASE_VERSION).getString());
+ return version == null ? null : (Version) node.getSession().getNodeByUUID(version.getId());
+ }
+
+ /**
+ * Returns the version history for the given node. assuming mix:versionable
+ * and version history set in property
+ *
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ public VersionHistory getVersionHistory(NodeImpl node)
+ throws RepositoryException {
+ String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
+ InternalVersionHistory history = vMgr.getVersionHistory(histUUID);
+ return (VersionHistory) node.getSession().getNodeByUUID(history.getId());
+ }
+
+ /**
+ * Checks if the version history with the given id exists
+ *
+ * @param id
+ * @return
+ */
+ public boolean hasVersionHistory(String id) {
+ return vMgr.hasVersionHistory(id);
+ }
+
+ /**
+ * Returns the version history with the given id
+ *
+ * @param id
+ * @return
+ * @throws RepositoryException
+ */
+ public InternalVersionHistory getVersionHistory(String id) throws RepositoryException {
+ return vMgr.getVersionHistory(id);
+ }
+
+ /**
+ * Returns the number of version histories
+ *
+ * @return
+ * @throws RepositoryException
+ */
+ public int getNumVersionHistories() throws RepositoryException {
+ return vMgr.getNumVersionHistories();
+ }
+
+ /**
+ * Returns an iterator over all ids of {@link InternalVersionHistory}s.
+ *
+ * @return
+ * @throws RepositoryException
+ */
+ public Iterator getVersionHistoryIds() throws RepositoryException {
+ return vMgr.getVersionHistoryIds();
+ }
+
+ /**
+ * Checks if the version with the given id exists
+ *
+ * @param id
+ * @return
+ */
+ public boolean hasVersion(String id) {
+ return vMgr.hasVersion(id);
+ }
+
+ /**
+ * Returns the version with the given id
+ *
+ * @param id
+ * @return
+ * @throws RepositoryException
+ */
+ public InternalVersion getVersion(String id) throws RepositoryException {
+ return vMgr.getVersion(id);
+ }
+
+ /**
+ * checks, if the node with the given id exists
+ * @param id
+ * @return
+ */
+ public boolean hasItem(String id) {
+ return vMgr.hasItem(id);
+ }
+
+ /**
+ * Returns the version item with the given id
+ * @param id
+ * @return
+ * @throws RepositoryException
+ */
+ public InternalVersionItem getItem(String id) throws RepositoryException {
+ return vMgr.getItemByExternal(id);
+ }
+
+ /**
+ * invokes the checkin() on the persistent version manager and remaps the
+ * newly created version objects.
+ *
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized Version checkin(NodeImpl node) throws RepositoryException {
+ InternalVersion version = vMgr.checkin(node);
+ return (Version) node.getSession().getNodeByUUID(version.getId());
+ }
+
+
+}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionNodeState.java Mon Dec 20 02:29:45 2004
@@ -17,98 +17,73 @@
import org.apache.jackrabbit.core.InternalValue;
import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.version.VersionItemStateProvider;
+import org.apache.jackrabbit.core.version.InternalVersion;
+import org.apache.jackrabbit.core.version.VersionManager;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.jackrabbit.core.state.NoSuchItemStateException;
import org.apache.jackrabbit.core.util.uuid.UUID;
import org.apache.jackrabbit.core.virtual.VirtualNodeState;
import org.apache.jackrabbit.core.virtual.VirtualPropertyState;
-import javax.jcr.PropertyType;
-import java.util.Calendar;
+import javax.jcr.RepositoryException;
/**
- * This Class implements...
+ * This Class implements a virtual node state that represents a version.
+ * since some properties like 'jcr:versionLabels', 'jcr:predecessors' etc. can
+ * change over time, we treat them specially.
*/
public class VersionNodeState extends VirtualNodeState {
+ /**
+ * the internal version
+ */
private final InternalVersion v;
- public VersionNodeState(VersionItemStateProvider vm, InternalVersion v) {
- super(vm, v.getId(), NodeTypeRegistry.NT_VERSION, v.getVersionHistory().getId());
+ /**
+ * Creates a new version node state
+ * @param vm
+ * @param v
+ * @param parentUUID
+ * @throws RepositoryException
+ */
+ protected VersionNodeState(VersionItemStateProvider vm, InternalVersion v,
+ String parentUUID)
+ throws RepositoryException {
+ super(vm, parentUUID, v.getId(), NodeTypeRegistry.NT_VERSION, new QName[0]);
this.v = v;
- // we map the property entries, since they do not change
- addPropertyEntry(VersionManager.PROPNAME_CREATED);
- addPropertyEntry(VersionManager.PROPNAME_FROZEN_UUID);
- addPropertyEntry(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE);
- addPropertyEntry(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES);
- addPropertyEntry(VersionManager.PROPNAME_VERSION_LABELS);
- addPropertyEntry(VersionManager.PROPNAME_PREDECESSORS);
- addPropertyEntry(VersionManager.PROPNAME_SUCCESSORS);
-
- // and the frozen node if not root version
+ // add the frozen node id if not root version
if (!v.isRootVersion()) {
- addChildNodeEntry(v.getFrozenNode().getName(), v.getFrozenNode().getInternalUUID());
+ addChildNodeEntry(VersionManager.NODENAME_FROZEN, v.getFrozenNode().getId());
}
-
- setDefinitionId(vm.getNodeDefId(VersionManager.NODENAME_ROOTVERSION));
}
- public VirtualPropertyState getPropertyState(QName name) throws NoSuchItemStateException {
- if (name.equals(VersionManager.PROPNAME_CREATED)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(VersionManager.PROPNAME_CREATED));
- state.setType(PropertyType.DATE);
- state.setValues(InternalValue.create(new Calendar[]{v.getCreated()}));
- return state;
- } else if (name.equals(VersionManager.PROPNAME_FROZEN_UUID)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(VersionManager.PROPNAME_FROZEN_UUID));
- state.setType(PropertyType.STRING);
- state.setValues(InternalValue.create(new String[]{v.getFrozenNode().getUUID()}));
- return state;
- } else if (name.equals(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE));
- state.setType(PropertyType.NAME);
- state.setValues(InternalValue.create(new QName[]{v.getFrozenNode().getFrozenPrimaryType()}));
- return state;
- } else if (name.equals(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES));
- state.setType(PropertyType.NAME);
- state.setValues(InternalValue.create(v.getFrozenNode().getFrozenMixinTypes()));
- return state;
- } else if (name.equals(VersionManager.PROPNAME_VERSION_LABELS)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(VersionManager.PROPNAME_VERSION_LABELS));
- state.setType(PropertyType.STRING);
- state.setValues(InternalValue.create(v.internalGetLabels()));
- return state;
- } else if (name.equals(VersionManager.PROPNAME_PREDECESSORS)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(VersionManager.PROPNAME_PREDECESSORS));
- state.setType(PropertyType.STRING);
- InternalVersion[] preds = v.getPredecessors();
- InternalValue[] predV = new InternalValue[preds.length];
- for (int i = 0; i < preds.length; i++) {
- predV[i] = InternalValue.create(new UUID(preds[i].getId()));
- }
- state.setValues(predV);
- return state;
- } else if (name.equals(VersionManager.PROPNAME_SUCCESSORS)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(VersionManager.PROPNAME_SUCCESSORS));
- state.setType(PropertyType.STRING);
- InternalVersion[] succs = v.getSuccessors();
- InternalValue[] succV = new InternalValue[succs.length];
- for (int i = 0; i < succs.length; i++) {
- succV[i] = InternalValue.create(new UUID(succs[i].getId()));
+ /**
+ * @see VirtualNodeState#getProperty(org.apache.jackrabbit.core.QName)
+ */
+ public VirtualPropertyState getProperty(QName name)
+ throws NoSuchItemStateException {
+ VirtualPropertyState state = super.getProperty(name);
+ if (state!=null) {
+ if (name.equals(VersionManager.PROPNAME_VERSION_LABELS)) {
+ state.setValues(InternalValue.create(v.getLabels()));
+ } else if (name.equals(VersionManager.PROPNAME_PREDECESSORS)) {
+ InternalVersion[] preds = v.getPredecessors();
+ InternalValue[] predV = new InternalValue[preds.length];
+ for (int i = 0; i < preds.length; i++) {
+ predV[i] = InternalValue.create(new UUID(preds[i].getId()));
+ }
+ state.setValues(predV);
+ } else if (name.equals(VersionManager.PROPNAME_SUCCESSORS)) {
+ InternalVersion[] succs = v.getSuccessors();
+ InternalValue[] succV = new InternalValue[succs.length];
+ for (int i = 0; i < succs.length; i++) {
+ succV[i] = InternalValue.create(new UUID(succs[i].getId()));
+ }
+ state.setValues(succV);
}
- state.setValues(succV);
- return state;
- } else {
- return super.getPropertyState(name);
}
+ return state;
}
}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFreezeImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFreezeImpl.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFreezeImpl.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version.persistence;
+
+import org.apache.jackrabbit.core.version.InternalFreeze;
+import org.apache.jackrabbit.core.version.InternalVersionItem;
+import org.apache.jackrabbit.core.version.PersistentVersionManager;
+
+/**
+ *
+ */
+abstract class InternalFreezeImpl extends InternalVersionItemImpl implements InternalFreeze {
+
+ private final InternalVersionItem parent;
+
+ protected InternalFreezeImpl(PersistentVersionManager vMgr, InternalVersionItem parent) {
+ super(vMgr);
+ this.parent = parent;
+ }
+
+ public InternalVersionItem getParent() {
+ return parent;
+ }
+
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenNodeImpl.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version.persistence;
+
+import org.apache.jackrabbit.core.version.*;
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
+import javax.jcr.PropertyIterator;
+import javax.jcr.NodeIterator;
+import javax.jcr.version.OnParentVersionAction;
+import javax.jcr.version.VersionException;
+import javax.jcr.nodetype.NodeType;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ *
+ */
+class InternalFrozenNodeImpl extends InternalFreezeImpl implements InternalFrozenNode {
+
+ /**
+ * the underlaying persistance node
+ */
+ private PersistentNode node;
+
+ /**
+ * the list of frozen properties
+ */
+ private PropertyState[] frozenProperties;
+
+ /**
+ * the frozen uuid of the original node
+ */
+ private String frozenUUID = null;
+
+ /**
+ * the frozen primary type of the orginal node
+ */
+ private QName frozenPrimaryType = null;
+
+ /**
+ * the frozen list of mixin types of the original node
+ */
+ private QName[] frozenMixinTypes = null;
+
+ /**
+ * the external id of this node
+ */
+ private final String id;
+
+ /**
+ * Creates a new frozen node based on the given persistance node.
+ *
+ * @param node
+ * @throws javax.jcr.RepositoryException
+ */
+ protected InternalFrozenNodeImpl(PersistentVersionManager vMgr,
+ PersistentNode node,
+ String id,
+ InternalVersionItem parent) throws RepositoryException {
+ super(vMgr, parent);
+ this.node = node;
+ this.id = id;
+
+ // init the frozen properties
+ PropertyState[] props = node.getProperties();
+ List propList = new ArrayList();
+
+ for (int i = 0; i < props.length; i++) {
+ PropertyState prop = props[i];
+ if (prop.getName().equals(VersionManager.PROPNAME_FROZEN_UUID)) {
+ // special property
+ frozenUUID = node.getPropertyValue(VersionManager.PROPNAME_FROZEN_UUID).internalValue().toString();
+ } else if (prop.getName().equals(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE)) {
+ // special property
+ frozenPrimaryType = (QName) node.getPropertyValue(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE).internalValue();
+ } else if (prop.getName().equals(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES)) {
+ // special property
+ InternalValue[] values = node.getPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES);
+ if (values == null) {
+ frozenMixinTypes = new QName[0];
+ } else {
+ frozenMixinTypes = new QName[values.length];
+ for (int j = 0; j < values.length; j++) {
+ frozenMixinTypes[j] = (QName) values[j].internalValue();
+ }
+ }
+ } else if (prop.getName().equals(ItemImpl.PROPNAME_PRIMARYTYPE)) {
+ // ignore
+ } else if (prop.getName().equals(ItemImpl.PROPNAME_UUID)) {
+ // ignore
+ } else {
+ propList.add(prop);
+ }
+ }
+ frozenProperties = (PropertyState[]) propList.toArray(new PropertyState[propList.size()]);
+
+ // do some checks
+ if (frozenMixinTypes == null) {
+ frozenMixinTypes = new QName[0];
+ }
+ if (frozenPrimaryType == null) {
+ throw new RepositoryException("Illegal frozen node. Must have 'frozenPrimaryType'");
+ }
+ // init the frozen child nodes
+ /*
+ PersistentNode[] childNodes = node.getChildNodes();
+ frozenChildNodes = new InternalFreeze[childNodes.length];
+ for (int i = 0; i < childNodes.length; i++) {
+ if (childNodes[i].hasProperty(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE)) {
+ frozenChildNodes[i] = new InternalFrozenNode(this, childNodes[i]);
+ } else if (childNodes[i].hasProperty(VersionManager.PROPNAME_VERSION_HISTORY)) {
+ frozenChildNodes[i] = new InternalFrozenVersionHistory(this, childNodes[i]);
+ } else {
+ // unkown ?
+ }
+ }
+ */
+
+ }
+
+ /**
+ * Returns the name of this frozen node
+ *
+ * @return
+ */
+ public QName getName() {
+ return node.getName();
+ }
+
+
+ protected String getPersistentId() {
+ return node.getUUID();
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.version.InternalFrozenNode#getFrozenChildNodes()
+ */
+ public InternalFreeze[] getFrozenChildNodes() throws VersionException {
+ try {
+ // maybe add iterator?
+ List entries = node.getState().getChildNodeEntries();
+ InternalFreeze[] freezes = new InternalFreeze[entries.size()];
+ Iterator iter = entries.iterator();
+ int i=0;
+ while (iter.hasNext()) {
+ NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
+ freezes[i++] = (InternalFreeze) getVersionManager().getItemByInternal(entry.getUUID());
+ }
+ return freezes;
+ } catch (RepositoryException e) {
+ throw new VersionException("Unable to retrieve frozen child nodes", e);
+ }
+ }
+
+ /**
+ * Returns the list of frozen properties
+ *
+ * @return
+ */
+ public PropertyState[] getFrozenProperties() {
+ return frozenProperties;
+ }
+
+ /**
+ * Returns the frozen UUID
+ *
+ * @return
+ */
+ public String getFrozenUUID() {
+ return frozenUUID;
+ }
+
+ /**
+ * Returns the frozen primary type
+ *
+ * @return
+ */
+ public QName getFrozenPrimaryType() {
+ return frozenPrimaryType;
+ }
+
+ /**
+ * Returns the list of the frozen mixin types
+ *
+ * @return
+ */
+ public QName[] getFrozenMixinTypes() {
+ return frozenMixinTypes;
+ }
+
+ /**
+ * Checks-in a <code>src</code> node. It creates a new child node of
+ * <code>parent</code> with the given <code>name</code> and adds the
+ * source nodes properties according to their OPV value to the
+ * list of frozen properties. It creates frozen child nodes for each child
+ * node of <code>src</code> according to its OPV value.
+ *
+ * @param parent
+ * @param name
+ * @param src
+ * @return
+ * @throws RepositoryException
+ */
+ protected static PersistentNode checkin(PersistentNode parent, QName name, NodeImpl src, boolean initOnly, boolean forceCopy)
+ throws RepositoryException {
+
+ PersistentNode node;
+
+ // create new node
+ node = parent.addNode(name, NativePVM.NT_REP_FROZEN);
+
+ // initialize the internal properties
+ if (src.isNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
+ node.setPropertyValue(VersionManager.PROPNAME_FROZEN_UUID, InternalValue.create(src.getUUID()));
+ }
+
+ node.setPropertyValue(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE,
+ InternalValue.create(((NodeTypeImpl) src.getPrimaryNodeType()).getQName()));
+
+ if (src.hasProperty(NodeImpl.PROPNAME_MIXINTYPES)) {
+ NodeType[] mixins = src.getMixinNodeTypes();
+ InternalValue[] ivalues = new InternalValue[mixins.length];
+ for (int i = 0; i < mixins.length; i++) {
+ ivalues[i] = InternalValue.create(((NodeTypeImpl) mixins[i]).getQName());
+ }
+ node.setPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, PropertyType.NAME, ivalues);
+ }
+
+ if (!initOnly) {
+ // add the properties
+ PropertyIterator piter = src.getProperties();
+ while (piter.hasNext()) {
+ PropertyImpl prop = (PropertyImpl) piter.nextProperty();
+ int opv = forceCopy ? OnParentVersionAction.COPY : prop.getDefinition().getOnParentVersion();
+ switch (opv) {
+ case OnParentVersionAction.ABORT:
+ parent.reload();
+ throw new RepositoryException("Checkin aborted due to OPV in " + prop.safeGetJCRPath());
+ case OnParentVersionAction.COMPUTE:
+ case OnParentVersionAction.IGNORE:
+ case OnParentVersionAction.INITIALIZE:
+ break;
+ case OnParentVersionAction.VERSION:
+ case OnParentVersionAction.COPY:
+ node.copyFrom(prop);
+ break;
+ }
+ }
+
+
+ // add the frozen children and vistories
+ NodeIterator niter = src.getNodes();
+ while (niter.hasNext()) {
+ NodeImpl child = (NodeImpl) niter.nextNode();
+ int opv = forceCopy ? OnParentVersionAction.COPY : child.getDefinition().getOnParentVersion();
+ switch (opv) {
+ case OnParentVersionAction.ABORT:
+ throw new RepositoryException("Checkin aborted due to OPV in " + child.safeGetJCRPath());
+ case OnParentVersionAction.COMPUTE:
+ case OnParentVersionAction.IGNORE:
+ case OnParentVersionAction.INITIALIZE:
+ break;
+ case OnParentVersionAction.VERSION:
+ if (child.isNodeType(NodeTypeRegistry.MIX_VERSIONABLE)) {
+ // create frozen versionable child
+ PersistentNode newChild = node.addNode(child.getQName(), NodeTypeRegistry.NT_FROZEN_VERSIONABLE_CHILD);
+ newChild.setPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY,
+ InternalValue.create(UUID.fromString(child.getVersionHistory().getUUID())));
+ newChild.setPropertyValue(VersionManager.PROPNAME_BASE_VERSION,
+ InternalValue.create(UUID.fromString(child.getBaseVersion().getUUID())));
+ break;
+ }
+ // else copy
+ case OnParentVersionAction.COPY:
+ checkin(node, child.getQName(), child, false, true);
+ break;
+ }
+ }
+ }
+ parent.store();
+ return node;
+ }
+
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalFrozenVHImpl.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version.persistence;
+
+import org.apache.jackrabbit.core.version.*;
+import org.apache.jackrabbit.core.QName;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.version.VersionException;
+
+/**
+ *
+ */
+class InternalFrozenVHImpl extends InternalFreezeImpl implements InternalFrozenVersionHistory {
+
+ /**
+ * the underlaying persistence node
+ */
+ private PersistentNode node;
+
+ private final String id;
+
+ /**
+ * Creates a new frozen version history.
+ *
+ * @param node
+ */
+ protected InternalFrozenVHImpl(PersistentVersionManager vMgr, PersistentNode node, String id, InternalVersionItem parent) {
+ super(vMgr, parent);
+ this.node = node;
+ this.id = id;
+ }
+
+ /**
+ * Returns the name of this frozen version history
+ *
+ * @return
+ */
+ public QName getName() {
+ return node.getName();
+ }
+
+ protected String getPersistentId() {
+ return node.getUUID();
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.version.InternalFrozenVersionHistory#getVersionHistoryId()
+ */
+ public String getVersionHistoryId() {
+ return (String) node.getPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY).internalValue();
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.version.InternalFrozenVersionHistory#getVersionHistory()
+ */
+ public InternalVersionHistory getVersionHistory()
+ throws VersionException {
+ try {
+ return getVersionManager().getVersionHistory(getVersionHistoryId());
+ } catch (RepositoryException e) {
+ throw new VersionException(e);
+ }
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.version.InternalFrozenVersionHistory#getBaseVersionId()
+ */
+ public String getBaseVersionId() {
+ return (String) node.getPropertyValue(VersionManager.PROPNAME_BASE_VERSION).internalValue();
+ }
+
+ /**
+ * @see org.apache.jackrabbit.core.version.InternalFrozenVersionHistory#getBaseVesion()
+ */
+ public InternalVersion getBaseVesion()
+ throws VersionException {
+ try {
+ return getVersionManager().getVersion(getVersionHistoryId(), getBaseVersionId());
+ } catch (RepositoryException e) {
+ throw new VersionException(e);
+ }
+ }
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionHistoryImpl.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version.persistence;
+
+import org.apache.jackrabbit.core.version.*;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.InternalValue;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.NamespaceRegistryImpl;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.util.Text;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.log4j.Logger;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.PropertyType;
+import javax.jcr.version.VersionException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Calendar;
+
+/**
+ *
+ */
+class InternalVersionHistoryImpl extends InternalVersionItemImpl implements InternalVersionHistory {
+ /**
+ * default logger
+ */
+ private static Logger log = Logger.getLogger(InternalVersionHistory.class);
+
+ /**
+ * the cache of the version labels
+ * key = version label (String)
+ * value = version
+ */
+ private HashMap labelCache = new HashMap();
+
+ /**
+ * the root version of this history
+ */
+ private InternalVersion rootVersion;
+
+ /**
+ * the hashmap of all versions
+ * key = versionId (String)
+ * value = version
+ */
+ private HashMap versionCache = new HashMap();
+
+ /**
+ * The nodes state of this version history
+ */
+ private PersistentNode node;
+
+ /**
+ * the node that holds the label nodes
+ */
+ private PersistentNode labelNode;
+
+ /**
+ * the id of this history
+ */
+ private String historyId;
+
+ /**
+ * Creates a new VersionHistory object for the given node state.
+ */
+ InternalVersionHistoryImpl(PersistentVersionManager vMgr, PersistentNode node) throws RepositoryException {
+ super(vMgr);
+ this.node = node;
+ init();
+ }
+
+ /**
+ * Initialies the history and loads all internal caches
+ *
+ * @throws RepositoryException
+ */
+ private void init() throws RepositoryException {
+ versionCache.clear();
+ labelCache.clear();
+
+ // get id
+ historyId = (String) node.getPropertyValue(NativePVM.PROPNAME_HISTORY_ID).internalValue();
+
+ // get entries
+ PersistentNode[] children = node.getChildNodes();
+ for (int i = 0; i < children.length; i++) {
+ PersistentNode child = children[i];
+ if (child.getName().equals(NativePVM.NODENAME_VERSION_LABELS)) {
+ labelNode = child;
+ continue;
+ }
+ InternalVersionImpl v = new InternalVersionImpl(getVersionManager(), this, child);
+ versionCache.put(v.getId(), v);
+ if (v.isRootVersion()) {
+ rootVersion = v;
+ }
+ }
+
+ // resolve successors and predecessors
+ Iterator iter = versionCache.values().iterator();
+ while (iter.hasNext()) {
+ InternalVersionImpl v = (InternalVersionImpl) iter.next();
+ v.resolvePredecessors();
+ }
+
+ // init label cache
+ PersistentNode labels[] = labelNode.getChildNodes();
+ for (int i = 0; i < labels.length; i++) {
+ PersistentNode lNode = labels[i];
+ String name = (String) lNode.getPropertyValue(NativePVM.PROPNAME_NAME).internalValue();
+ String ref = (String) lNode.getPropertyValue(NativePVM.PROPNAME_VERSION).internalValue();
+ InternalVersionImpl v = (InternalVersionImpl) getVersion(ref);
+ labelCache.put(name, v);
+ v.internalAddLabel(name);
+ }
+ }
+
+ /**
+ * Returns the id of this version history
+ *
+ * @return
+ */
+ public String getId() {
+ return historyId;
+ }
+
+ protected String getPersistentId() {
+ return node.getUUID();
+ }
+
+ public InternalVersionItem getParent() {
+ return null;
+ }
+
+ /**
+ * @see javax.jcr.version.VersionHistory#getRootVersion()
+ */
+ public InternalVersion getRootVersion() {
+ return rootVersion;
+ }
+
+ /**
+ * @see javax.jcr.version.VersionHistory#getVersion(java.lang.String)
+ */
+ public InternalVersion getVersion(QName versionName) throws VersionException {
+ // maybe add cache by name?
+ Iterator iter = versionCache.values().iterator();
+ while (iter.hasNext()) {
+ InternalVersion v = (InternalVersion) iter.next();
+ if (v.getName().equals(versionName)) {
+ return v;
+ }
+ }
+ throw new VersionException("Version " + versionName + " does not exist.");
+ }
+
+ /**
+ *
+ * @param versionName
+ * @return
+ */
+ public boolean hasVersion(QName versionName) {
+ // maybe add cache?
+ Iterator iter = versionCache.values().iterator();
+ while (iter.hasNext()) {
+ InternalVersion v = (InternalVersion) iter.next();
+ if (v.getName().equals(versionName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the version for the given uuid exists
+ *
+ * @param uuid
+ * @return
+ */
+ public boolean hasVersion(String uuid) {
+ return versionCache.containsKey(uuid);
+ }
+
+ /**
+ * Returns the version with the given uuid or <code>null</code> if the
+ * respective version does not exist.
+ *
+ * @param uuid
+ * @return
+ */
+ public InternalVersion getVersion(String uuid) {
+ return (InternalVersion) versionCache.get(uuid);
+ }
+
+ /**
+ * @see javax.jcr.version.VersionHistory#getVersionByLabel(java.lang.String)
+ */
+ public InternalVersion getVersionByLabel(String label) {
+ return (InternalVersion) labelCache.get(label);
+ }
+
+ /**
+ * Removes the indicated version from this VersionHistory. If the specified
+ * vesion does not exist, if it specifies the root version or if it is
+ * referenced by any node e.g. as base version, a VersionException is thrown.
+ * <p/>
+ * all successors of the removed version become successors of the
+ * predecessors of the removed version and vice versa. then, the entire
+ * version node and all its subnodes are removed.
+ *
+ * @param versionName
+ * @throws VersionException
+ */
+ public void removeVersion(QName versionName) throws VersionException {
+ InternalVersionImpl v = (InternalVersionImpl) getVersion(versionName);
+ if (v.equals(rootVersion)) {
+ String msg = "Removal of " + versionName + " not allowed.";
+ log.error(msg);
+ throw new VersionException(msg);
+ }
+
+ try {
+ // remove from persistance state
+ node.removeNode(versionName);
+
+ // unregister from labels
+ String[] labels = v.internalGetLabels();
+ for (int i = 0; i < labels.length; i++) {
+ v.internalRemoveLabel(labels[i]);
+ QName name = new QName("", Text.md5(labels[i]));
+ labelNode.removeNode(name);
+ }
+
+ // detach from the version graph
+ v.internalDetach();
+
+ // and remove from history
+ versionCache.remove(v.getId());
+ store();
+ } catch (RepositoryException e) {
+ throw new VersionException("error while storing modifications", e);
+ }
+ }
+
+ /**
+ * @see InternalVersionHistory#addVersionLabel(org.apache.jackrabbit.core.QName, String, boolean)
+ */
+ public InternalVersion addVersionLabel(QName versionName, String label, boolean move)
+ throws VersionException {
+
+ InternalVersion version = getVersion(versionName);
+ if (version == null) {
+ throw new VersionException("Version " + versionName + " does not exist in this version history.");
+ }
+
+ InternalVersionImpl prev = (InternalVersionImpl) labelCache.get(label);
+ if (version.equals(prev)) {
+ // ignore
+ return version;
+ } else if (prev != null && !move) {
+ // already defined elsewhere, throw
+ throw new VersionException("Version label " + label + " already defined for version " + prev.getName());
+ } else if (prev != null) {
+ // if already defined, but move, remove old label first
+ removeVersionLabel(label);
+ }
+ labelCache.put(label, version);
+ ((InternalVersionImpl) version).internalAddLabel(label);
+ QName name = new QName("", Text.md5(label));
+ try {
+ PersistentNode lNode = labelNode.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
+ lNode.setPropertyValue(NativePVM.PROPNAME_NAME, InternalValue.create(label));
+ lNode.setPropertyValue(NativePVM.PROPNAME_VERSION, InternalValue.create(version.getId()));
+ labelNode.store();
+ } catch (RepositoryException e) {
+ throw new VersionException("Error while storing modifications", e);
+ }
+ return prev;
+ }
+
+ /**
+ * @see InternalVersionHistory#removeVersionLabel(String)
+ */
+ public InternalVersion removeVersionLabel(String label) throws VersionException {
+ InternalVersionImpl v = (InternalVersionImpl) labelCache.remove(label);
+ if (v == null) {
+ throw new VersionException("Version label " + label + " is not in version history.");
+ }
+ v.internalRemoveLabel(label);
+ QName name = new QName("", Text.md5(label));
+
+ try {
+ labelNode.removeNode(name);
+ labelNode.store();
+ } catch (RepositoryException e) {
+ throw new VersionException("Unable to store modifications", e);
+ }
+
+ return v;
+ }
+
+ /**
+ * Checks in a node. It creates a new version with the given name and freezes
+ * the state of the given node.
+ *
+ * @param name
+ * @param src
+ * @return
+ * @throws RepositoryException
+ */
+ protected InternalVersionImpl checkin(QName name, NodeImpl src)
+ throws RepositoryException {
+
+ // copy predecessors from src node
+ Value[] preds = src.getProperty(VersionManager.PROPNAME_PREDECESSORS).getValues();
+ InternalValue[] predecessors = new InternalValue[preds.length];
+ for (int i = 0; i < preds.length; i++) {
+ String predId = preds[i].getString();
+ // check if version exist
+ if (!versionCache.containsKey(predId)) {
+ throw new RepositoryException("invalid predecessor in source node");
+ }
+ predecessors[i] = InternalValue.create(predId);
+ }
+
+ String versionId = UUID.randomUUID().toString();
+ QName nodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, versionId);
+ PersistentNode vNode = node.addNode(nodeName, NativePVM.NT_REP_VERSION);
+ vNode.setPropertyValue(NativePVM.PROPNAME_VERSION_ID, InternalValue.create(versionId));
+ vNode.setPropertyValue(NativePVM.PROPNAME_VERSION_NAME, InternalValue.create(name));
+
+ // initialize 'created' and 'predecessors'
+ vNode.setPropertyValue(VersionManager.PROPNAME_CREATED, InternalValue.create(Calendar.getInstance()));
+ vNode.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.STRING, predecessors);
+
+ // checkin source node
+ InternalFrozenNodeImpl.checkin(vNode, VersionManager.NODENAME_FROZEN, src, false, false);
+
+ // and store
+ store();
+
+ // update version graph
+ InternalVersionImpl version = new InternalVersionImpl(getVersionManager(), this, vNode);
+ version.resolvePredecessors();
+
+ // update cache
+ versionCache.put(version.getId(), version);
+
+ return version;
+ }
+
+
+ /**
+ * Stores the changes made to this version history
+ *
+ * @throws RepositoryException
+ */
+ protected void store() throws RepositoryException {
+ node.store();
+ }
+
+ /**
+ * discards the changes made to this version history
+ *
+ * @throws RepositoryException
+ */
+ protected void reload() throws RepositoryException {
+ node.reload();
+ init();
+ }
+
+ /**
+ * Returns an iterator over all versions (not ordered yet)
+ *
+ * @return
+ */
+ public Iterator getVersions() {
+ return versionCache.values().iterator();
+ }
+
+ /**
+ * Returns the number of versions
+ *
+ * @return
+ */
+ public int getNumVersions() {
+ return versionCache.size();
+ }
+
+ protected String getUUID() {
+ return node.getUUID();
+ }
+
+ protected PersistentNode getNode() {
+ return node;
+ }
+
+ /**
+ * Creates a new <code>InternalVersionHistory</code> below the given parent
+ * node and with the given name.
+ *
+ * @param parent
+ * @param name
+ * @return
+ * @throws RepositoryException
+ */
+ protected static InternalVersionHistoryImpl create(PersistentVersionManager vMgr, PersistentNode parent, String historyId, QName name, NodeImpl src)
+ throws RepositoryException {
+
+ // create history node
+ PersistentNode pNode = parent.addNode(name, NativePVM.NT_REP_VERSION_HISTORY);
+ pNode.setPropertyValue(NativePVM.PROPNAME_HISTORY_ID, InternalValue.create(historyId));
+
+ // create label node
+ pNode.addNode(NativePVM.NODENAME_VERSION_LABELS, NodeTypeRegistry.NT_UNSTRUCTURED);
+
+ // create root version
+ String versionId = UUID.randomUUID().toString();
+ QName nodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, versionId);
+
+ PersistentNode vNode = pNode.addNode(nodeName, NativePVM.NT_REP_VERSION);
+ vNode.setPropertyValue(NativePVM.PROPNAME_VERSION_ID, InternalValue.create(versionId));
+ vNode.setPropertyValue(NativePVM.PROPNAME_VERSION_NAME, InternalValue.create(VersionManager.NODENAME_ROOTVERSION));
+
+ // initialize 'created' and 'predecessors'
+ vNode.setPropertyValue(VersionManager.PROPNAME_CREATED, InternalValue.create(Calendar.getInstance()));
+ vNode.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.REFERENCE, new InternalValue[0]);
+
+ // add also an empty frozen node to the root version
+ InternalFrozenNodeImpl.checkin(vNode, VersionManager.NODENAME_FROZEN, src, true, false);
+
+ parent.store();
+ return new InternalVersionHistoryImpl(vMgr, pNode);
+ }
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionImpl.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version.persistence;
+
+import org.apache.jackrabbit.core.version.*;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.InternalValue;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.Arrays;
+
+/**
+ *
+ */
+class InternalVersionImpl extends InternalVersionItemImpl implements InternalVersion {
+
+ /**
+ * the list/cache of predecessors (values == InternalVersion)
+ */
+ private ArrayList predecessors = new ArrayList();
+
+ /**
+ * the list of successors (values == InternalVersion)
+ */
+ private ArrayList successors = new ArrayList();
+
+ /**
+ * the underlaying persistance node of this version
+ */
+ private PersistentNode node;
+
+ /**
+ * the date when this version was created
+ */
+ private Calendar created;
+
+ /**
+ * the set of version labes of this history (values == String)
+ */
+ private HashSet labelCache = null;
+
+ /**
+ * the id of this version
+ */
+ private String versionId;
+
+ /**
+ * specifies if this is the root version
+ */
+ private final boolean isRoot;
+
+ /**
+ * the version name
+ */
+ private final QName name;
+
+ /**
+ * the version history
+ */
+ private final InternalVersionHistory versionHistory;
+
+ /**
+ * Creates a new internal version with the given version history and
+ * persistance node
+ *
+ * @param node
+ */
+ InternalVersionImpl(PersistentVersionManager vMgr, InternalVersionHistory vh, PersistentNode node) {
+ super(vMgr);
+ this.versionHistory = vh;
+ this.node = node;
+
+ // get id
+ versionId = (String) node.getPropertyValue(NativePVM.PROPNAME_VERSION_ID).internalValue();
+
+ // init internal values
+ InternalValue[] values = node.getPropertyValues(VersionManager.PROPNAME_CREATED);
+ if (values != null) {
+ created = (Calendar) values[0].internalValue();
+ }
+ values = node.getPropertyValues(NativePVM.PROPNAME_VERSION_NAME);
+ if (values != null) {
+ name = (QName) values[0].internalValue();
+ } else {
+ name = null; // ????
+ }
+ isRoot = name.equals(VersionManager.NODENAME_ROOTVERSION);
+ }
+
+ public String getId() {
+ return versionId;
+ }
+
+ protected String getPersistentId() {
+ return node.getUUID();
+ }
+
+ public InternalVersionItem getParent() {
+ return versionHistory;
+ }
+
+ /**
+ * Returns the name of this version
+ *
+ * @return
+ */
+ public QName getName() {
+ return name;
+ }
+
+ protected PersistentNode getNode() {
+ return node;
+ }
+
+ /**
+ * Returns the frozen node
+ *
+ * @return
+ */
+ public InternalFrozenNode getFrozenNode() {
+ // get frozen node
+ try {
+ // assuming only child
+ PersistentNode[] nodes = node.getChildNodes();
+ return nodes.length==0 ? null : (InternalFrozenNode) getVersionManager().getItemByInternal(nodes[0].getUUID());
+ } catch (RepositoryException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ /**
+ * adds a successor version to the internal cache
+ *
+ * @param successor
+ */
+ private void addSuccessor(InternalVersion successor) {
+ successors.add(successor);
+ }
+
+ /**
+ * resolves the predecessors property and indirectly adds it self to their
+ * successor list.
+ */
+ void resolvePredecessors() {
+ InternalValue[] values = node.getPropertyValues(VersionManager.PROPNAME_PREDECESSORS);
+ if (values != null) {
+ for (int i = 0; i < values.length; i++) {
+ InternalVersionImpl v = (InternalVersionImpl) versionHistory.getVersion(values[i].internalValue().toString());
+ predecessors.add(v);
+ v.addSuccessor(this);
+ }
+ }
+ }
+
+ /**
+ * @see javax.jcr.version.Version#getCreated()
+ */
+ public Calendar getCreated() {
+ return created;
+ }
+
+ /**
+ * @see javax.jcr.version.Version#getSuccessors()
+ */
+ public InternalVersion[] getSuccessors() {
+ return (InternalVersion[]) successors.toArray(new InternalVersion[successors.size()]);
+ }
+
+ /**
+ * @see javax.jcr.version.Version#getSuccessors()
+ */
+ public InternalVersion[] getPredecessors() {
+ return (InternalVersion[]) predecessors.toArray(new InternalVersion[predecessors.size()]);
+ }
+
+ /**
+ * stores the internal predecessor cache to the persistance node
+ *
+ * @throws RepositoryException
+ */
+ private void storePredecessors() throws RepositoryException {
+ InternalValue[] values = new InternalValue[predecessors.size()];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = InternalValue.create(new UUID(((InternalVersion) predecessors.get(i)).getId()));
+ }
+ node.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.STRING, values);
+ }
+
+ /**
+ * Detaches itself from the version graph.
+ *
+ * @throws RepositoryException
+ */
+ void internalDetach() throws RepositoryException {
+ // detach this from all successors
+ InternalVersionImpl[] succ = (InternalVersionImpl[]) getSuccessors();
+ for (int i = 0; i < succ.length; i++) {
+ succ[i].internalDetachPredecessor(this);
+ }
+
+ // clear properties
+ successors.clear();
+ predecessors.clear();
+ labelCache = null;
+ storePredecessors();
+ }
+
+ /**
+ * Removes the predecessor V of this predecessor list and adds all of Vs
+ * predecessors to it.
+ * <p/>
+ * please note, that this operation might corrupt the version graph
+ *
+ * @param v the successor to detach
+ */
+ private void internalDetachPredecessor(InternalVersion v) throws RepositoryException {
+ // remove 'v' from predecessor list
+ for (int i = 0; i < predecessors.size(); i++) {
+ if (predecessors.get(i).equals(v)) {
+ predecessors.remove(i);
+ break;
+ }
+ }
+ // attach v's successors
+ predecessors.clear();
+ predecessors.addAll(Arrays.asList(v.getPredecessors()));
+ storePredecessors();
+ }
+
+ /**
+ * Checks if this version is more recent than the given version <code>v</code>.
+ * A version is more recent if and only if it is a successor (or a successor
+ * of a successor, etc., to any degree of separation) of the compared one.
+ *
+ * @param v the version to check
+ * @return <code>true</code> if the version is more recent;
+ * <code>false</code> otherwise.
+ */
+ public boolean isMoreRecent(InternalVersion v) {
+ for (int i = 0; i < predecessors.size(); i++) {
+ InternalVersion pred = (InternalVersion) predecessors.get(i);
+ if (pred.equals(this) || pred.isMoreRecent(v)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * returns the internal version history of this version
+ *
+ * @return
+ */
+ public InternalVersionHistory getVersionHistory() {
+ return versionHistory;
+ }
+
+ /**
+ * adds a label to the label cache. does not affect storage
+ *
+ * @param label
+ * @return
+ */
+ protected boolean internalAddLabel(String label) {
+ if (labelCache == null) {
+ labelCache = new HashSet();
+ }
+ return labelCache.add(label);
+ }
+
+ /**
+ * removes a label from the label cache. does not affect storage
+ *
+ * @param label
+ * @return
+ */
+ protected boolean internalRemoveLabel(String label) {
+ if (labelCache == null) {
+ return false;
+ } else {
+ return labelCache.remove(label);
+ }
+ }
+
+ /**
+ * checks, if a label is in the label cache
+ *
+ * @param label
+ * @return
+ */
+ protected boolean internalHasLabel(String label) {
+ return labelCache == null ? false : labelCache.contains(label);
+ }
+
+ /**
+ * @see InternalVersion#hasLabel(String)
+ */
+ public boolean hasLabel(String label) {
+ return internalHasLabel(label);
+ }
+
+ /**
+ * returns the array of the cached labels
+ *
+ * @return
+ */
+ protected String[] internalGetLabels() {
+ return labelCache == null ? new String[0] : (String[]) labelCache.toArray(new String[labelCache.size()]);
+ }
+
+ /**
+ * @see InternalVersionImpl#getLabels()
+ */
+ public String[] getLabels() {
+ return internalGetLabels();
+ }
+
+ /**
+ * checks if this is the root version.
+ *
+ * @return <code>true</code> if this version is the root version;
+ * <code>false</code> otherwise.
+ */
+ public boolean isRootVersion() {
+ return isRoot;
+ }
+
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/InternalVersionItemImpl.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version.persistence;
+
+import org.apache.jackrabbit.core.version.PersistentVersionManager;
+import org.apache.jackrabbit.core.version.InternalVersionItem;
+
+/**
+ *
+ */
+abstract class InternalVersionItemImpl {
+
+ /**
+ * the version manager
+ */
+ private final PersistentVersionManager vMgr;
+
+ /**
+ * Creates a new Internal version item impl
+ * @param vMgr
+ */
+ protected InternalVersionItemImpl(PersistentVersionManager vMgr) {
+ this.vMgr = vMgr;
+ }
+
+ /**
+ * Returns the persistent version manager for this item
+ * @return
+ */
+ protected PersistentVersionManager getVersionManager() {
+ return vMgr;
+ }
+
+ /**
+ * Returns the internal persistent id of this item
+ * @return
+ */
+ protected abstract String getPersistentId();
+
+ /**
+ * Returns the external id of this item
+ * @return
+ */
+ public abstract String getId();
+
+
+ /**
+ * returns the parent version item or null
+ * @return
+ */
+ public abstract InternalVersionItem getParent();
+
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/NativePVM.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,557 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version.persistence;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.core.version.*;
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.nodetype.NodeDefId;
+import org.apache.jackrabbit.core.state.PersistentItemStateProvider;
+import org.apache.jackrabbit.core.state.PersistentNodeState;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.commons.collections.ReferenceMap;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Iterator;
+
+/**
+ * This Class implements the persistent part of the versioning. the
+ * current implementation uses the 'normal' repository content as storage.
+ * <p>
+ * although the nodes need to be mapped again virtually in the real content,
+ * the persistent nodes use a different structure as exposed later.
+ * each versioning element (version history, version, freezes) is stored in a
+ * persistent node state, where the name is the original UUID. eg. the name of
+ * a persistentnodestate that represents a version, is the UUID of that version.
+ * the hierarchy is somewhat similar, thus histories contain versions, contain
+ * frozen nodes, etc.
+ * <p>
+ * on startup, the entire structure is traversed, in order to get a mapping
+ * from real to persistent uuids.
+ */
+public class NativePVM implements PersistentVersionManager {
+
+ /**
+ * the logger
+ */
+ private static Logger log = Logger.getLogger(PersistentVersionManager.class);
+
+ /**
+ * root path for version storage
+ */
+ public static final QName VERSION_HISTORY_ROOT_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "persistentVersionStorage");
+
+ /**
+ * name of the 'jcr:historyId' property
+ */
+ public static final QName PROPNAME_HISTORY_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "historyId");
+ /**
+ * name of the 'jcr:versionId' property
+ */
+ public static final QName PROPNAME_VERSION_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionId");
+ /**
+ * name of the 'jcr:versionName' property
+ */
+ public static final QName PROPNAME_VERSION_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionName");
+ /**
+ * name of the 'jcr:versionLabels' node
+ */
+ public static final QName NODENAME_VERSION_LABELS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionLabels");
+ /**
+ * name of the 'jcr:name' property
+ */
+ public static final QName PROPNAME_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "name");
+ /**
+ * name of the 'jcr:version' property
+ */
+ public static final QName PROPNAME_VERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "version");
+
+ /**
+ * the id of the persisten root node
+ */
+ private static final NodeId PERSISTENT_ROOT_ID = new NodeId("faceface-ab3b-48a9-b31b-e7d0a9c1c3b1");
+
+ /**
+ * The nodetype name of a persistent version
+ */
+ protected static final QName NT_REP_VERSION = new QName(NamespaceRegistryImpl.NS_REP_URI, "version");
+
+ /**
+ * The nodetype name of a presistent version history
+ */
+ protected static final QName NT_REP_VERSION_HISTORY = new QName(NamespaceRegistryImpl.NS_REP_URI, "versionHistory");
+
+ /**
+ * the nodetype name of a persistent frozen node
+ */
+ protected static final QName NT_REP_FROZEN = new QName(NamespaceRegistryImpl.NS_REP_URI, "frozen");
+
+ /**
+ * the persistent root node of the version histories
+ */
+ private final PersistentNode historyRoot;
+
+ /**
+ * the state manager for the version storage
+ */
+ private PersistentItemStateProvider stateMgr;
+
+ /**
+ * the nodetype manager for the version storage
+ */
+ private NodeTypeManagerImpl ntMgr;
+
+ /**
+ * mapping from virtual uuids to persistent ids of the persistent nodes
+ * key=externalId, value=PersistentId
+ */
+ private HashMap idsByExternal = new HashMap();
+
+ /**
+ * mapping from virtual uuids to persistent ids of the persistent nodes
+ * key=internalId, value=PersistentId
+ */
+ private HashMap idsByInternal= new HashMap();
+
+ /**
+ * list of histories for fast retrieval
+ */
+ private LinkedList histories = new LinkedList();
+
+ /**
+ * the version histories. key=uuid, value=version history
+ */
+ private Map items = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
+
+ /**
+ * Creates a new PersistentVersionManager.
+ *
+ * @param session
+ * @throws javax.jcr.RepositoryException
+ */
+ public NativePVM(SessionImpl session) throws RepositoryException {
+ this.stateMgr = ((WorkspaceImpl) session.getWorkspace()).getPersistentStateManager();
+ this.ntMgr = session.getNodeTypeManager();
+
+ try {
+ NodeImpl systemRoot = ((RepositoryImpl) session.getRepository()).getSystemRootNode(session);
+ // enable this to make the persistence storage visible
+ if (true) {
+ // check for versionhistory root
+ if (!systemRoot.hasNode(VERSION_HISTORY_ROOT_NAME)) {
+ // if not exist, create
+ systemRoot.addNode(VERSION_HISTORY_ROOT_NAME, NodeTypeRegistry.NT_UNSTRUCTURED);
+ systemRoot.save();
+ }
+ PersistentNodeState nodeState = (PersistentNodeState) stateMgr.getItemState(new NodeId(systemRoot.getNode(VERSION_HISTORY_ROOT_NAME).internalGetUUID()));
+ historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
+ } else {
+ if (!stateMgr.hasItemState(PERSISTENT_ROOT_ID)) {
+ PersistentNodeState nodeState = stateMgr.createNodeState(PERSISTENT_ROOT_ID.getUUID(), NodeTypeRegistry.NT_UNSTRUCTURED, null);
+ nodeState.setDefinitionId(new NodeDefId(ntMgr.getRootNodeDefinition().unwrap()));
+ nodeState.store();
+ historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
+ } else {
+ PersistentNodeState nodeState = (PersistentNodeState) stateMgr.getItemState(PERSISTENT_ROOT_ID);
+ historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
+ }
+ }
+ initVirtualIds(historyRoot.getState());
+ log.info("loaded " + idsByExternal.size() + " virtual ids.");
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to initialize PersistentVersionManager: " + e.toString());
+ }
+ }
+
+ /**
+ * initializes the internal item ids
+ * @param parent
+ * @throws RepositoryException
+ * @throws ItemStateException
+ */
+ private void initVirtualIds(NodeState parent)
+ throws RepositoryException, ItemStateException {
+
+ Iterator iter = parent.getChildNodeEntries().iterator();
+ while (iter.hasNext()) {
+ NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
+ String realUUID = entry.getName().getLocalName();
+ initVirtualIds(realUUID, (NodeState) stateMgr.getItemState(new NodeId(entry.getUUID())));
+ }
+ }
+
+ /**
+ * initializes the internal item ids
+ * @param realUUID
+ * @param state
+ * @throws ItemStateException
+ * @throws RepositoryException
+ */
+ private void initVirtualIds(String realUUID, NodeState state)
+ throws ItemStateException, RepositoryException {
+ PersistentId id = new PersistentId(realUUID, state);
+ if (id.type != PersistentId.TYPE_UNDEFINED) {
+ idsByExternal.put(id.externalId, id);
+ idsByInternal.put(id.internalId, id);
+ if (id.type == PersistentId.TYPE_HISTORY) {
+ histories.add(id.externalId);
+ }
+ }
+ initVirtualIds(state);
+ }
+
+ /**
+ * returns the persistentid for a given external uuid
+ * @param uuid
+ * @return
+ */
+ private PersistentId getIdByExternal(String uuid) {
+ return (PersistentId) idsByExternal.get(uuid);
+ }
+
+ /**
+ * returns the persustentid for a given internal uuid
+ * @param uuid
+ * @return
+ */
+ private PersistentId getIdByInternal(String uuid) {
+ return (PersistentId) idsByInternal.get(uuid);
+ }
+
+ /**
+ * returns the persustentid for a give internal uuid and item type
+ * @param uuid
+ * @param type
+ * @return
+ */
+ private PersistentId getIdByExternal(String uuid, int type) {
+ PersistentId id = (PersistentId) idsByExternal.get(uuid);
+ return id != null && id.type == type ? id : null;
+ }
+
+ /**
+ * Creates a new Version History.
+ *
+ * @param node the node for which the version history is to be initialized
+ * @return the newly created version history.
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersionHistory createVersionHistory(NodeImpl node)
+ throws RepositoryException {
+
+ // create deep path
+ String uuid = UUID.randomUUID().toString();
+ PersistentNode root = historyRoot;
+ for (int i=0; i<3; i++) {
+ QName name = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(i*2, i*2+2));
+ if (!root.hasNode(name)) {
+ root.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
+ root.store();
+ }
+ root = root.getNode(name, 1);
+ }
+ QName historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid);
+
+ // create new history node in the persistent state
+ InternalVersionHistoryImpl hist = InternalVersionHistoryImpl.create(this, root, uuid, historyNodeName, node);
+ try {
+ initVirtualIds(hist.getId(), hist.getNode().getState());
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
+
+ log.info("Created new version history " + uuid + ". NumHistories=" + histories.size());
+ return hist;
+ }
+
+ /**
+ * returns the internal version history for the id
+ *
+ * @param histId the id of the history
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersionHistory getVersionHistory(String histId)
+ throws RepositoryException {
+
+ PersistentId pid = getIdByExternal(histId, PersistentId.TYPE_HISTORY);
+ return pid==null ? null : (InternalVersionHistory) getItem(pid);
+ }
+
+ /**
+ * Checks if the versionhistory for the given id exists
+ *
+ * @param histId
+ * @return
+ */
+ public synchronized boolean hasVersionHistory(String histId) {
+ return getIdByExternal(histId, PersistentId.TYPE_HISTORY) != null;
+ }
+
+ /**
+ * returns an iterator over the external ids of the version histories
+ *
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized Iterator getVersionHistoryIds() throws RepositoryException {
+ return histories.iterator();
+ }
+
+ /**
+ * returns the number of version histories
+ *
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized int getNumVersionHistories() throws RepositoryException {
+ return histories.size();
+ }
+
+ /**
+ * returns the internal version for the id
+ *
+ * @param versionId
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersion getVersion(String histId, String versionId)
+ throws RepositoryException {
+ InternalVersionHistory history = getVersionHistory(histId);
+ return history.getVersion(versionId);
+ }
+
+ /**
+ * returns the version with the given id
+ *
+ * @param versionId
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersion getVersion(String versionId)
+ throws RepositoryException {
+
+ PersistentId pid = getIdByExternal(versionId, PersistentId.TYPE_VERSION);
+ return pid==null ? null : (InternalVersion) getItem(pid);
+ }
+
+ /**
+ * Checks if the version with the given id exists
+ *
+ * @param versionId
+ * @return
+ */
+ public synchronized boolean hasVersion(String versionId) {
+ return getIdByExternal(versionId, PersistentId.TYPE_VERSION) != null;
+ }
+
+ /**
+ * checks, if the item with the given external id exists
+ * @param externalId
+ * @return
+ */
+ public synchronized boolean hasItem(String externalId) {
+ return getIdByExternal(externalId) != null;
+ }
+
+ /**
+ * returns the item referred by the external id
+ * @param externalId
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersionItem getItemByExternal(String externalId)
+ throws RepositoryException {
+ PersistentId pid = getIdByExternal(externalId);
+ return pid==null ? null : getItem(pid);
+ }
+
+ /**
+ * returns the item referred by the internal id
+ * @param internalId
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersionItem getItemByInternal(String internalId)
+ throws RepositoryException {
+ PersistentId pid = getIdByInternal(internalId);
+ return pid==null ? null : getItem(pid);
+ }
+
+ /**
+ * returns the item with the given persistent id
+ * @param pid
+ * @return
+ * @throws RepositoryException
+ */
+ synchronized private InternalVersionItem getItem(PersistentId pid)
+ throws RepositoryException {
+
+ InternalVersionItem item =(InternalVersionItem) items.get(pid);
+ if (item==null) {
+ PersistentNode pNode = historyRoot.getNodeByUUID(pid.internalId);
+ if (pNode!=null) {
+ InternalVersionItem parent = getItemByInternal(pNode.getParentUUID());
+ if (pid.type == PersistentId.TYPE_FROZEN) {
+ item = new InternalFrozenNodeImpl(this, pNode, pid.externalId, parent);
+ } else if (pid.type == PersistentId.TYPE_FROZEN_HISTORY) {
+ item = new InternalFrozenVHImpl(this, pNode, pid.externalId, parent);
+ } else if (pid.type == PersistentId.TYPE_VERSION) {
+ item = new InternalVersionImpl(this, (InternalVersionHistory) parent, pNode);
+ } else if (pid.type == PersistentId.TYPE_HISTORY) {
+ item = new InternalVersionHistoryImpl(this, pNode);
+ } else {
+ //return null;
+ }
+ }
+ if (item!=null) {
+ items.put(pid, item);
+ }
+ }
+ return item;
+ }
+
+ /**
+ * Checks in a node
+ *
+ * @param node
+ * @return
+ * @throws RepositoryException
+ * @see javax.jcr.Node#checkin()
+ */
+ public synchronized InternalVersion checkin(NodeImpl node) throws RepositoryException {
+ // assuming node is versionable and checkout (check in nodeimpl)
+ // To create a new version of a versionable node N, the client calls N.checkin.
+ // This causes the following series of events:
+ String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
+ InternalVersionHistoryImpl history = (InternalVersionHistoryImpl) getVersionHistory(histUUID);
+
+ // 0. resolve the predecessors
+ Value[] values = node.getProperty(VersionManager.PROPNAME_PREDECESSORS).getValues();
+ InternalVersion[] preds = new InternalVersion[values.length];
+ for (int i = 0; i < values.length; i++) {
+ preds[i] = history.getVersion(values[i].getString());
+ }
+
+ // 0.1 search a predecessor, suitable for generating the new name
+ String versionName = null;
+ int maxDots = Integer.MAX_VALUE;
+ for (int i = 0; i < preds.length; i++) {
+ // take the first pred. without a successor
+ if (preds[i].getSuccessors().length == 0) {
+ versionName = preds[i].getName().getLocalName(); //assuming no namespaces in version names
+ // need to count the dots
+ int pos = -1;
+ int numDots = 0;
+ while (versionName.indexOf('.', pos + 1) >= 0) {
+ pos = versionName.indexOf('.', pos + 1);
+ numDots++;
+ }
+ if (numDots < maxDots) {
+ maxDots = numDots;
+ versionName = pos < 0 ? "1.0" : versionName.substring(0, pos + 1) + (Integer.parseInt(versionName.substring(pos + 1)) + 1);
+ }
+ break;
+ }
+ }
+ // if no empty found, generate new name
+ if (versionName == null) {
+ versionName = preds[0].getName().getLocalName();
+ do {
+ versionName += ".1";
+ } while (history.hasVersion(new QName("", versionName)));
+ }
+
+ InternalVersionImpl v = history.checkin(new QName("", versionName), node);
+ try {
+ initVirtualIds(v.getId(), v.getNode().getState());
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
+ return v;
+ }
+
+ /**
+ * Helper class for persistent items
+ */
+ public static final class PersistentId {
+
+ private static final int TYPE_UNDEFINED = 0;
+ private static final int TYPE_HISTORY = 1;
+ private static final int TYPE_VERSION = 2;
+ private static final int TYPE_FROZEN = 3;
+ private static final int TYPE_FROZEN_HISTORY = 3;
+
+ /** the type of the persistent node */
+ private final int type;
+
+ /** the persistent uuid of the node */
+ private final String externalId;
+
+ /** the persistent uuid of the node */
+ private final String internalId;
+
+ public PersistentId(int type, String external, String internal) {
+ this.type = type;
+ this.internalId = internal;
+ this.externalId = external;
+ }
+
+ public PersistentId(String external, NodeState state) {
+ this.internalId = state.getUUID();
+ if (state.getNodeTypeName().equals(NT_REP_VERSION)) {
+ this.externalId = external;
+ type = TYPE_VERSION;
+ } else if (state.getNodeTypeName().equals(NT_REP_VERSION_HISTORY)) {
+ this.externalId = external;
+ type = TYPE_HISTORY;
+ } else if (state.getNodeTypeName().equals(NT_REP_FROZEN)) {
+ // ignore given externalid, and generate new one
+ this.externalId = UUID.randomUUID().toString();
+ type = TYPE_FROZEN;
+ } else if (state.getNodeTypeName().equals(NodeTypeRegistry.NT_FROZEN_VERSIONABLE_CHILD)) {
+ // ignore given externalid, and generate new one
+ this.externalId = UUID.randomUUID().toString();
+ type = TYPE_FROZEN_HISTORY;
+ } else {
+ // ignore given externalid, and generate new one
+ this.externalId = UUID.randomUUID().toString();
+ type = TYPE_UNDEFINED;
+ }
+ }
+
+ public boolean isVersion() {
+ return type == TYPE_VERSION;
+ }
+
+ public boolean isHistory() {
+ return type == TYPE_HISTORY;
+ }
+
+ public boolean isFrozen() {
+ return type == TYPE_FROZEN;
+ }
+ }
+
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java?view=auto&rev=122838
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/persistence/PersistentNode.java Mon Dec 20 02:29:45 2004
@@ -0,0 +1,607 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version.persistence;
+
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.nodetype.*;
+import org.apache.jackrabbit.core.state.*;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeDef;
+import javax.jcr.nodetype.PropertyDef;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * This Class provides some basic node operations directly on the persistent
+ * state.
+ */
+class PersistentNode {
+
+ /**
+ * the underlaying persistent state
+ */
+ private PersistentNodeState nodeState;
+
+ /**
+ * the state manager
+ */
+ private final PersistentItemStateProvider stateMgr;
+
+ /**
+ * the node type manager
+ */
+ private final NodeTypeManagerImpl ntMgr;
+
+ /**
+ * the cached name
+ */
+ private QName name = null;
+
+ /**
+ * Creates a new persistent node
+ *
+ * @param statemgr
+ * @param ntMgr
+ * @param nodeState
+ */
+ protected PersistentNode(PersistentItemStateProvider statemgr,
+ NodeTypeManagerImpl ntMgr,
+ PersistentNodeState nodeState) {
+ this.nodeState = nodeState;
+ this.stateMgr = statemgr;
+ this.ntMgr = ntMgr;
+ }
+
+
+ /**
+ * returns the name of this node
+ *
+ * @return
+ */
+ protected QName getName() {
+ if (name == null) {
+ try {
+ String parentId = nodeState.getParentUUID();
+ NodeState parent = (NodeState) stateMgr.getItemState(new NodeId(parentId));
+ name = ((NodeState.ChildNodeEntry) parent.getChildNodeEntries(nodeState.getUUID()).get(0)).getName();
+ } catch (ItemStateException e) {
+ // should never occurr
+ throw new IllegalStateException(e.toString());
+ }
+ }
+ return name;
+ }
+
+ /**
+ * Returns the uuid of this node
+ *
+ * @return
+ */
+ protected String getUUID() {
+ return nodeState.getUUID();
+ }
+
+ protected String getParentUUID() {
+ return nodeState.getParentUUID();
+ }
+
+ protected PersistentNodeState getState() {
+ return nodeState;
+ }
+
+ /**
+ * Returns the properties of this node
+ *
+ * @return
+ */
+ protected PropertyState[] getProperties() {
+ try {
+ List list = nodeState.getPropertyEntries();
+ PropertyState[] props = new PropertyState[list.size()];
+ for (int i = 0; i < list.size(); i++) {
+ NodeState.PropertyEntry entry = (NodeState.PropertyEntry) list.get(i);
+ PropertyId propId = new PropertyId(nodeState.getUUID(), entry.getName());
+ props[i] = (PropertyState) stateMgr.getItemState(propId);
+ }
+ return props;
+ } catch (ItemStateException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Checks if the given property exists
+ *
+ * @param name
+ * @return
+ */
+ protected boolean hasProperty(QName name) {
+ PropertyId propId = new PropertyId(nodeState.getUUID(), name);
+ return stateMgr.hasItemState(propId);
+ }
+
+ /**
+ * Returns the values of the given property of <code>null</code>
+ *
+ * @param name
+ * @return
+ */
+ protected InternalValue[] getPropertyValues(QName name) {
+ PropertyId propId = new PropertyId(nodeState.getUUID(), name);
+ try {
+ PropertyState ps = (PropertyState) stateMgr.getItemState(propId);
+ return ps.getValues();
+ } catch (ItemStateException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value of the given property or <code>null</code>
+ *
+ * @param name
+ * @return
+ */
+ protected InternalValue getPropertyValue(QName name) {
+ PropertyId propId = new PropertyId(nodeState.getUUID(), name);
+ try {
+ PropertyState ps = (PropertyState) stateMgr.getItemState(propId);
+ return ps.getValues()[0];
+ } catch (ItemStateException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the property value
+ *
+ * @param name
+ * @param value
+ * @throws RepositoryException
+ */
+ protected void setPropertyValue(QName name, InternalValue value)
+ throws RepositoryException {
+ setPropertyValues(name, value.getType(), new InternalValue[]{value}, false);
+ }
+
+ /**
+ * Sets the property values
+ *
+ * @param name
+ * @param type
+ * @param values
+ * @throws RepositoryException
+ */
+ protected void setPropertyValues(QName name, int type, InternalValue[] values)
+ throws RepositoryException {
+ setPropertyValues(name, type, values, true);
+ }
+
+ /**
+ * Sets the property values
+ *
+ * @param name
+ * @param type
+ * @param values
+ * @throws RepositoryException
+ */
+ protected void setPropertyValues(QName name, int type, InternalValue[] values, boolean multiple)
+ throws RepositoryException {
+ PersistentPropertyState prop = getOrCreatePropertyState(name, type, multiple);
+ prop.setValues(values);
+ }
+
+ /**
+ * Retrieves or creates a new property state as child property of this node
+ *
+ * @param name
+ * @param type
+ * @param multiValued
+ * @return
+ * @throws RepositoryException
+ */
+ private PersistentPropertyState getOrCreatePropertyState(QName name, int type, boolean multiValued)
+ throws RepositoryException {
+
+ PropertyId propId = new PropertyId(nodeState.getUUID(), name);
+ if (stateMgr.hasItemState(propId)) {
+ try {
+ PersistentPropertyState propState = (PersistentPropertyState) stateMgr.getItemState(propId);
+ // someone calling this method will always alter the property state, so set status to modified
+ propState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+ return propState;
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to create property: " + e.toString());
+ }
+ } else {
+ try {
+ PropertyDefImpl def = getApplicablePropertyDef(name, type, multiValued);
+ PersistentPropertyState propState = stateMgr.createPropertyState(nodeState.getUUID(), name);
+ propState.setType(type);
+ propState.setMultiValued(multiValued);
+ propState.setDefinitionId(new PropDefId(def.unwrap()));
+
+ // need to store nodestate
+ nodeState.addPropertyEntry(name);
+ nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+ return propState;
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to store property: " + e.toString());
+ }
+ }
+ }
+
+ /**
+ * retrieves the property definition for the given contraints
+ *
+ * @param propertyName
+ * @param type
+ * @param multiValued
+ * @return
+ * @throws RepositoryException
+ */
+ protected PropertyDefImpl getApplicablePropertyDef(QName propertyName,
+ int type, boolean multiValued)
+ throws RepositoryException {
+ PropDef pd = getEffectiveNodeType().getApplicablePropertyDef(propertyName, type, multiValued);
+ return ntMgr.getPropDef(new PropDefId(pd));
+ }
+
+ /**
+ * Retrieves the node definition for the given contraints.
+ *
+ * @param nodeName
+ * @param nodeTypeName
+ * @return
+ * @throws RepositoryException
+ */
+ protected NodeDefImpl getApplicableChildNodeDef(QName nodeName, QName nodeTypeName)
+ throws RepositoryException {
+ ChildNodeDef cnd = getEffectiveNodeType().getApplicableChildNodeDef(nodeName, nodeTypeName);
+ return ntMgr.getNodeDef(new NodeDefId(cnd));
+ }
+
+ /**
+ * Returns the effective (i.e. merged and resolved) node type representation
+ * of this node's primary and mixin node types.
+ *
+ * @return the effective node type
+ * @throws RepositoryException
+ */
+ protected EffectiveNodeType getEffectiveNodeType() throws RepositoryException {
+ // build effective node type of mixins & primary type
+ NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
+ // existing mixin's
+ HashSet set = new HashSet(nodeState.getMixinTypeNames());
+ // primary type
+ set.add(nodeState.getNodeTypeName());
+ try {
+ return ntReg.buildEffectiveNodeType((QName[]) set.toArray(new QName[set.size()]));
+ } catch (NodeTypeConflictException ntce) {
+ String msg = "internal error: failed to build effective node type for node " + nodeState.getUUID();
+ throw new RepositoryException(msg, ntce);
+ }
+ }
+
+ /**
+ * checks if the given child node exists.
+ *
+ * @param name
+ * @return
+ */
+ protected boolean hasNode(QName name) {
+ return nodeState.hasChildNodeEntry(name);
+ }
+
+ /**
+ * removes the (first) child node with the given name.
+ *
+ * @param name
+ * @return
+ * @throws RepositoryException
+ */
+ protected boolean removeNode(QName name) throws RepositoryException {
+ return removeNode(name, 1);
+ }
+
+ /**
+ * removes the child node with the given name and 1-based index
+ *
+ * @param name
+ * @param index
+ * @return
+ * @throws RepositoryException
+ */
+ protected boolean removeNode(QName name, int index) throws RepositoryException {
+ if (nodeState.removeChildNodeEntry(name, index)) {
+ nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * retrieves the child node with the given name and 1-base index or
+ * <code>null</code> if the node does not exist.
+ *
+ * @param name
+ * @param index
+ * @return
+ * @throws RepositoryException
+ */
+ protected PersistentNode getNode(QName name, int index) throws RepositoryException {
+ NodeState.ChildNodeEntry entry = nodeState.getChildNodeEntry(name, index);
+ if (entry == null) {
+ return null;
+ }
+ try {
+ PersistentNodeState state = (PersistentNodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
+ return new PersistentNode(stateMgr, ntMgr, state);
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to getNode: " + e.toString());
+ }
+ }
+
+ /**
+ * returns the node with the given uuid.
+ *
+ * @param uuid
+ * @return
+ * @throws RepositoryException
+ */
+ protected PersistentNode getNodeByUUID(String uuid) throws RepositoryException {
+ try {
+ PersistentNodeState state = (PersistentNodeState) stateMgr.getItemState(new NodeId(uuid));
+ return new PersistentNode(stateMgr, ntMgr, state);
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to getNode: " + e.toString());
+ }
+ }
+
+ /**
+ * Adds a new child node with the given name
+ *
+ * @param nodeName
+ * @param nodeTypeName
+ * @return
+ * @throws NoSuchNodeTypeException
+ * @throws ConstraintViolationException
+ * @throws RepositoryException
+ */
+ protected PersistentNode addNode(QName nodeName, QName nodeTypeName)
+ throws NoSuchNodeTypeException, ConstraintViolationException, RepositoryException {
+ NodeTypeImpl nodeType = ntMgr.getNodeType(nodeTypeName);
+ NodeDefImpl def;
+ try {
+ def = getApplicableChildNodeDef(name, nodeType == null ? null : nodeType.getQName());
+ } catch (RepositoryException re) {
+ // hack, use nt:unstructured as parent
+ try {
+ NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
+ EffectiveNodeType ent = ntReg.buildEffectiveNodeType(new QName[]{NodeTypeRegistry.NT_UNSTRUCTURED});
+ ChildNodeDef cnd = ent.getApplicableChildNodeDef(name, nodeTypeName);
+ def = ntMgr.getNodeDef(new NodeDefId(cnd));
+ } catch (NodeTypeConflictException e) {
+ String msg = "no definition found in parent node's node type for new node";
+ throw new ConstraintViolationException(msg, re);
+ }
+ }
+
+ if (nodeType == null) {
+ // use default node type
+ nodeType = (NodeTypeImpl) def.getDefaultPrimaryType();
+ }
+ return createChildNode(nodeName, def, nodeType, null);
+ }
+
+ /**
+ * creates a new child node
+ *
+ * @param name
+ * @param def
+ * @param nodeType
+ * @param uuid
+ * @return
+ * @throws RepositoryException
+ */
+ private PersistentNode createChildNode(QName name, NodeDefImpl def,
+ NodeTypeImpl nodeType, String uuid)
+ throws RepositoryException {
+
+ String parentUUID = nodeState.getUUID();
+ // create a new node state
+ PersistentNodeState state = null;
+ try {
+ if (uuid == null) {
+ uuid = UUID.randomUUID().toString(); // version 4 uuid
+ }
+ state = stateMgr.createNodeState(uuid, nodeType.getQName(), parentUUID);
+ state.setDefinitionId(new NodeDefId(def.unwrap()));
+ } catch (ItemStateException ise) {
+ String msg = "failed to add child node " + name + " to " + parentUUID;
+ throw new RepositoryException(msg, ise);
+ }
+
+ // create Node instance wrapping new node state
+ PersistentNode node = new PersistentNode(stateMgr, ntMgr, state);
+ // add new child node entry
+ nodeState.addChildNodeEntry(name, state.getUUID());
+ nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+
+ // add 'auto-create' properties defined in node type
+ PropertyDef[] pda = nodeType.getAutoCreatePropertyDefs();
+ for (int i = 0; i < pda.length; i++) {
+ PropertyDefImpl pd = (PropertyDefImpl) pda[i];
+ node.getOrCreatePropertyState(pd.getQName(), pd.getRequiredType(), pd.isMultiple());
+ }
+
+ // recursively add 'auto-create' child nodes defined in node type
+ NodeDef[] nda = nodeType.getAutoCreateNodeDefs();
+ for (int i = 0; i < nda.length; i++) {
+ NodeDefImpl nd = (NodeDefImpl) nda[i];
+ node.createChildNode(nd.getQName(), nd, (NodeTypeImpl) nd.getDefaultPrimaryType(), null);
+ }
+
+ // store primary type
+ node.setPropertyValue(ItemImpl.PROPNAME_PRIMARYTYPE, InternalValue.create(nodeType.getQName()));
+ return node;
+ }
+
+ /**
+ * returns all child nodes
+ *
+ * @return
+ * @throws RepositoryException
+ */
+ protected PersistentNode[] getChildNodes() throws RepositoryException {
+ try {
+ List entries = nodeState.getChildNodeEntries();
+ PersistentNode[] children = new PersistentNode[entries.size()];
+ for (int i = 0; i < entries.size(); i++) {
+ NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) entries.get(i);
+ PersistentNodeState state = (PersistentNodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
+ children[i] = new PersistentNode(stateMgr, ntMgr, state);
+ }
+ return children;
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * stores the persistent state recursively
+ *
+ * @throws RepositoryException
+ */
+ protected void store() throws RepositoryException {
+ try {
+ store(nodeState);
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * stores the given persistent state recursively
+ *
+ * @param state
+ * @throws ItemStateException
+ */
+ private void store(PersistentNodeState state) throws ItemStateException {
+ if (state.isTransient()) {
+ // first store all transient properties
+ List props = state.getPropertyEntries();
+ for (int i = 0; i < props.size(); i++) {
+ NodeState.PropertyEntry entry = (NodeState.PropertyEntry) props.get(i);
+ PersistentPropertyState pstate = (PersistentPropertyState) stateMgr.getItemState(new PropertyId(state.getUUID(), entry.getName()));
+ if (pstate.isTransient()) {
+ pstate.store();
+ }
+ }
+ // now store all child node entries
+ List nodes = state.getChildNodeEntries();
+ for (int i = 0; i < nodes.size(); i++) {
+ NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) nodes.get(i);
+ PersistentNodeState nstate = (PersistentNodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
+ store(nstate);
+ }
+ // and store itself
+ state.store();
+ }
+ }
+
+ /**
+ * reloads the persistent state recursively
+ *
+ * @throws RepositoryException
+ */
+ protected void reload() throws RepositoryException {
+ try {
+ reload(nodeState);
+ // refetch nodestate if discarded
+ nodeState = (PersistentNodeState) stateMgr.getItemState(nodeState.getId());
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * reloads the given persistent state recursively
+ *
+ * @param state
+ * @throws ItemStateException
+ */
+ private void reload(PersistentNodeState state) throws ItemStateException {
+ if (state.isTransient()) {
+ // first discard all all transient properties
+ List props = state.getPropertyEntries();
+ for (int i = 0; i < props.size(); i++) {
+ NodeState.PropertyEntry entry = (NodeState.PropertyEntry) props.get(i);
+ PersistentPropertyState pstate = (PersistentPropertyState) stateMgr.getItemState(new PropertyId(state.getUUID(), entry.getName()));
+ if (pstate.isTransient()) {
+ pstate.discard();
+ }
+ }
+ // now reload all child node entries
+ List nodes = state.getChildNodeEntries();
+ for (int i = 0; i < nodes.size(); i++) {
+ NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) nodes.get(i);
+ PersistentNodeState nstate = (PersistentNodeState) stateMgr.getItemState(new NodeId(entry.getUUID()));
+ reload(nstate);
+ }
+ // and reload itself
+ state.discard();
+ }
+ }
+
+ /**
+ * copies a property
+ *
+ * @param prop
+ * @throws RepositoryException
+ */
+ protected void copyFrom(PropertyImpl prop) throws RepositoryException {
+ if (prop.getDefinition().isMultiple()) {
+ InternalValue[] values = prop.internalGetValues();
+ setPropertyValues(prop.getQName(), values[0].getType(), values);
+ } else {
+ setPropertyValue(prop.getQName(), prop.internalGetValue());
+ }
+ }
+
+ /**
+ * sets the mixing node type and adds the respective property
+ *
+ * @param mixins
+ * @throws RepositoryException
+ */
+ protected void setMixinNodeTypes(QName[] mixins) throws RepositoryException {
+ HashSet set = new HashSet();
+ InternalValue[] values = new InternalValue[mixins.length];
+ for (int i = 0; i < mixins.length; i++) {
+ set.add(mixins[i]);
+ values[i] = InternalValue.create(mixins[i]);
+ }
+ nodeState.setMixinTypeNames(set);
+ setPropertyValues(ItemImpl.PROPNAME_MIXINTYPES, PropertyType.NAME, values);
+ }
+}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java Mon Dec 20 02:29:45 2004
@@ -18,31 +18,91 @@
import org.apache.jackrabbit.core.QName;
import org.apache.jackrabbit.core.nodetype.NodeDefId;
import org.apache.jackrabbit.core.nodetype.PropDefId;
-import org.apache.jackrabbit.core.state.ItemStateProvider;
+import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.core.state.*;
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.PropertyId;
+
+import javax.jcr.RepositoryException;
/**
* This Interface defines a virtual item state provider.
*/
public interface VirtualItemStateProvider extends ItemStateProvider {
+
/**
- * Returns a predefined node definition id.
- *
- * @param nodename
+ * Checks if the id referrs to the root of a virtual tree.
+ * @param id
* @return
*/
- public NodeDefId getNodeDefId(QName nodename);
+ public boolean isVirtualRoot(ItemId id);
/**
- * Returns a predefined property definition id
- *
- * @param propname
+ * Returns the id of the root node of the virtual tree.
* @return
*/
- public PropDefId getPropDefId(QName propname);
+ public NodeId getVirtualRootId();
- public boolean isVirtualRoot(ItemId id);
+ /**
+ * Checks if the node with the given id exists in this item state provider.
+ * @param id
+ * @return
+ */
+ public boolean hasNodeState(NodeId id);
+
+ /**
+ * Checks if the property with the given id exists in this item state provider.
+ * @param id
+ * @return
+ */
+ public boolean hasPropertyState(PropertyId id);
+
+ /**
+ * Returns the node state for the given node id
+ * @param id
+ * @return
+ * @throws ItemStateException
+ * @throws NoSuchItemStateException
+ */
+ public VirtualNodeState getNodeState(NodeId id)
+ throws ItemStateException, NoSuchItemStateException;
+
+ /**
+ * Returns the property state for the give property id
+ * @param id
+ * @return
+ * @throws ItemStateException
+ * @throws NoSuchItemStateException
+ */
+ public VirtualPropertyState getPropertyState(PropertyId id)
+ throws ItemStateException, NoSuchItemStateException;
+
+ /**
+ * Creats a new virtual property state
+ * @param parent
+ * @param name
+ * @param type
+ * @param multiValued
+ * @return
+ * @throws RepositoryException
+ */
+ public VirtualPropertyState createPropertyState(VirtualNodeState parent,
+ QName name, int type,
+ boolean multiValued)
+ throws RepositoryException;
+
+ /**
+ * Creates a new virtual node state
+ * @param parent
+ * @param name
+ * @param uuid
+ * @param nodeTypeName
+ * @return
+ * @throws RepositoryException
+ */
+ public VirtualNodeState createNodeState(VirtualNodeState parent, QName name,
+ String uuid, QName nodeTypeName)
+ throws RepositoryException;
- public NodeId getVirtualRootId();
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java Mon Dec 20 02:29:45 2004
@@ -23,51 +23,165 @@
import org.apache.jackrabbit.core.state.NodeState;
import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import java.util.HashMap;
+import java.util.HashSet;
/**
* This Class implements a virtual node state
*/
public class VirtualNodeState extends NodeState {
- protected VirtualItemStateProvider provider;
+ /**
+ * The virtual item state provide that created this node state
+ */
+ protected final VirtualItemStateProvider stateMgr;
+
+ /**
+ * map of property states of this node state
+ * key=propname, value={@link VirtualPropertyState}
+ */
+ private final HashMap properties = new HashMap();
/**
+ * creates a new virtual node state
+ * @param stateMgr
+ * @param parentUUID
* @param uuid
* @param nodeTypeName
- * @param parentUUID
+ * @param mixins
+ * @throws RepositoryException
*/
- protected VirtualNodeState(VirtualItemStateProvider provider,
- String uuid, QName nodeTypeName, String parentUUID) {
+ public VirtualNodeState(VirtualItemStateProvider stateMgr,
+ String parentUUID,
+ String uuid,
+ QName nodeTypeName,
+ QName[] mixins)
+ throws RepositoryException {
super(uuid, nodeTypeName, parentUUID, ItemState.STATUS_EXISTING);
+ this.stateMgr = stateMgr;
+
+ // add default properties
+ setPropertyValue(ItemImpl.PROPNAME_PRIMARYTYPE, InternalValue.create(nodeTypeName));
+ setMixinNodeTypes(mixins);
+ }
- this.provider = provider;
+ /**
+ * Returns the properties of this node
+ *
+ * @return
+ */
+ public VirtualPropertyState[] getProperties() {
+ return (VirtualPropertyState[]) properties.values().toArray(new VirtualPropertyState[properties.size()]);
+ }
- // add some props
- addPropertyEntry(ItemImpl.PROPNAME_PRIMARYTYPE);
- addPropertyEntry(ItemImpl.PROPNAME_MIXINTYPES);
- }
-
- public VirtualPropertyState getPropertyState(QName name)
- throws NoSuchItemStateException {
- if (name.equals(ItemImpl.PROPNAME_PRIMARYTYPE)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(ItemImpl.PROPNAME_PRIMARYTYPE));
- state.setType(PropertyType.NAME);
- state.setValues(InternalValue.create(new QName[]{getNodeTypeName()}));
- return state;
- } else if (name.equals(ItemImpl.PROPNAME_MIXINTYPES)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(ItemImpl.PROPNAME_MIXINTYPES));
- state.setType(PropertyType.NAME);
- state.setValues(InternalValue.create((QName[]) getMixinTypeNames().toArray(new QName[getMixinTypeNames().size()])));
- return state;
- } else if (name.equals(ItemImpl.PROPNAME_UUID)) {
- VirtualPropertyState state = new VirtualPropertyState(name, getUUID());
- state.setDefinitionId(provider.getPropDefId(ItemImpl.PROPNAME_UUID));
- state.setType(PropertyType.STRING);
- state.setValues(InternalValue.create(new String[]{getUUID()}));
- return state;
+
+ /**
+ * Returns the values of the given property of <code>null</code>
+ *
+ * @param name
+ * @return
+ */
+ public InternalValue[] getPropertyValues(QName name) throws NoSuchItemStateException {
+ VirtualPropertyState ps = getProperty(name);
+ return ps==null ? null : ps.getValues();
+ }
+
+ /**
+ * Returns the value of the given property or <code>null</code>
+ *
+ * @param name
+ * @return
+ */
+ public InternalValue getPropertyValue(QName name) throws NoSuchItemStateException {
+ VirtualPropertyState ps = getProperty(name);
+ return ps==null || ps.getValues().length==0 ? null : ps.getValues()[0];
+ }
+
+ /**
+ * returns the property state of the given name
+ * @param name
+ * @return
+ * @throws NoSuchItemStateException
+ */
+ public VirtualPropertyState getProperty(QName name) throws NoSuchItemStateException {
+ return (VirtualPropertyState) properties.get(name);
+ }
+
+ /**
+ * Sets the property value
+ *
+ * @param name
+ * @param value
+ * @throws javax.jcr.RepositoryException
+ */
+ public void setPropertyValue(QName name, InternalValue value)
+ throws RepositoryException {
+ setPropertyValues(name, value.getType(), new InternalValue[]{value}, false);
+ }
+
+ /**
+ * Sets the property values
+ *
+ * @param name
+ * @param type
+ * @param values
+ * @throws RepositoryException
+ */
+ public void setPropertyValues(QName name, int type, InternalValue[] values)
+ throws RepositoryException {
+ setPropertyValues(name, type, values, true);
+ }
+
+ /**
+ * Sets the property values
+ *
+ * @param name
+ * @param type
+ * @param values
+ * @throws RepositoryException
+ */
+ public void setPropertyValues(QName name, int type, InternalValue[] values, boolean multiple)
+ throws RepositoryException {
+ VirtualPropertyState prop = getOrCreatePropertyState(name, type, multiple);
+ prop.setValues(values);
+ }
+
+ /**
+ * Retrieves or creates a new property state as child property of this node
+ *
+ * @param name
+ * @param type
+ * @param multiValued
+ * @return
+ * @throws RepositoryException
+ */
+ private VirtualPropertyState getOrCreatePropertyState(QName name, int type, boolean multiValued)
+ throws RepositoryException {
+
+ VirtualPropertyState prop = (VirtualPropertyState) properties.get(name);
+ if (prop==null) {
+ prop = stateMgr.createPropertyState(this, name, type, multiValued);
+ properties.put(name, prop);
+ addPropertyEntry(name);
+ }
+ return prop;
+ }
+
+ /**
+ * sets the mixing node type and adds the respective property
+ *
+ * @param mixins
+ * @throws RepositoryException
+ */
+ public void setMixinNodeTypes(QName[] mixins) throws RepositoryException {
+ HashSet set = new HashSet();
+ InternalValue[] values = new InternalValue[mixins.length];
+ for (int i = 0; i < mixins.length; i++) {
+ set.add(mixins[i]);
+ values[i] = InternalValue.create(mixins[i]);
}
- throw new NoSuchItemStateException(name.toString());
+ setMixinTypeNames(set);
+ setPropertyValues(ItemImpl.PROPNAME_MIXINTYPES, PropertyType.NAME, values);
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java?view=diff&rev=122838&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java&r1=122837&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java&r2=122838
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java Mon Dec 20 02:29:45 2004
@@ -25,6 +25,7 @@
public class VirtualPropertyState extends PropertyState {
/**
+ * Creates a new virtual property state
* @param name
* @param parentUUID
*/