You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by st...@apache.org on 2004/07/21 18:58:04 UTC
cvs commit: jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/util ValueHelper.java
stefan 2004/07/21 09:58:04
Modified: proposals/jcrri/src/org/apache/slide/jcr/core ItemImpl.java
ItemManager.java NodeImpl.java RepositoryImpl.java
SystemTicket.java Test.java TicketImpl.java
WorkspaceImpl.java
proposals/jcrri/src/org/apache/slide/jcr/core/nodetype
NodeTypeManagerImpl.java NodeTypeRegistry.java
builtin_nodetypes.xml
proposals/jcrri/src/org/apache/slide/jcr/core/state
ItemState.java PersistentItemStateManager.java
proposals/jcrri/src/org/apache/slide/jcr/core/version
VersionImpl.java VersionManager.java
proposals/jcrri/src/org/apache/slide/jcr/util
ValueHelper.java
Log:
jcrri
Revision Changes Path
1.14 +49 -27 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemImpl.java
Index: ItemImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemImpl.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- ItemImpl.java 20 Jul 2004 08:28:33 -0000 1.13
+++ ItemImpl.java 21 Jul 2004 16:58:03 -0000 1.14
@@ -33,6 +33,7 @@
import org.apache.slide.jcr.core.state.*;
import org.apache.slide.jcr.core.version.VersionImpl;
import org.apache.slide.jcr.util.IteratorHelper;
+import org.apache.slide.jcr.util.UUID;
import javax.jcr.*;
import javax.jcr.access.AccessDeniedException;
@@ -212,12 +213,17 @@
* (i.e. it has been temporarily rendered 'invalid').
*/
private void notifyCreated() {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ ItemLifeCycleListener[] la = new ItemLifeCycleListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- ItemLifeCycleListener listener = (ItemLifeCycleListener) iter.next();
- listener.itemCreated(this);
+ la[cnt++] = (ItemLifeCycleListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].itemCreated(this);
+ }
}
}
@@ -226,12 +232,17 @@
* (i.e. it has been temporarily rendered 'invalid').
*/
protected void notifyInvalidated() {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ ItemLifeCycleListener[] la = new ItemLifeCycleListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- ItemLifeCycleListener listener = (ItemLifeCycleListener) iter.next();
- listener.itemInvalidated(id, this);
+ la[cnt++] = (ItemLifeCycleListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].itemInvalidated(id, this);
+ }
}
}
@@ -240,12 +251,17 @@
* (i.e. it has been rendered 'valid' again).
*/
protected void notifyResurrected() {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ ItemLifeCycleListener[] la = new ItemLifeCycleListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- ItemLifeCycleListener listener = (ItemLifeCycleListener) iter.next();
- listener.itemResurrected(this);
+ la[cnt++] = (ItemLifeCycleListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].itemResurrected(this);
+ }
}
}
@@ -254,12 +270,17 @@
* (i.e. it has been permanently rendered 'invalid').
*/
protected void notifyDestroyed() {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ ItemLifeCycleListener[] la = new ItemLifeCycleListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- ItemLifeCycleListener listener = (ItemLifeCycleListener) iter.next();
- listener.itemDestroyed(id, this);
+ la[cnt++] = (ItemLifeCycleListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].itemDestroyed(id, this);
+ }
}
}
@@ -493,9 +514,10 @@
NodeImpl node = (NodeImpl) itemMgr.getItem(itemState.getId());
if (node.isNodeType(NodeTypeRegistry.MIX_VERSIONABLE)) {
VersionHistory hist = rep.getVersionManager().createVersionHistory(node);
- node.internalSetProperty(VersionImpl.PROPNAME_VERSION_HISTORY, InternalValue.create(hist.getUUID()));
- node.internalSetProperty(VersionImpl.PROPNAME_BASE_VERSION, InternalValue.create(hist.getRootVersion().getUUID()));
+ node.internalSetProperty(VersionImpl.PROPNAME_VERSION_HISTORY, InternalValue.create(new UUID(hist.getUUID())));
+ node.internalSetProperty(VersionImpl.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(hist.getRootVersion().getUUID())));
node.internalSetProperty(VersionImpl.PROPNAME_IS_CHECKED_OUT, InternalValue.create(true));
+ node.internalSetProperty(VersionImpl.PROPNAME_PREDESESSORS, new InternalValue[]{InternalValue.create(new UUID(hist.getRootVersion().getUUID()))});
}
}
}
@@ -507,7 +529,7 @@
*
* @return JCR path or some fallback value
*/
- protected String safeGetJCRPath() {
+ public String safeGetJCRPath() {
return itemMgr.safeGetJCRPath(id);
}
@@ -850,8 +872,8 @@
}
// all changes are persisted, now dispatch events
- WorkspaceImpl ws = (WorkspaceImpl) ticket.getWorkspace();
- ws.getRepository().getObservationManagerFactory(ws.wsDef).dispatchEvents(events);
+ WorkspaceImpl wsp = (WorkspaceImpl) ticket.getWorkspace();
+ wsp.getRepository().getObservationManagerFactory(wsp.getName()).dispatchEvents(events);
}
/**
1.10 +5 -2 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemManager.java
Index: ItemManager.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemManager.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ItemManager.java 20 Jul 2004 08:28:33 -0000 1.9
+++ ItemManager.java 21 Jul 2004 16:58:03 -0000 1.10
@@ -31,6 +31,7 @@
import org.apache.slide.jcr.core.state.*;
import org.apache.slide.jcr.core.version.VersionHistoryImpl;
import org.apache.slide.jcr.core.version.VersionImpl;
+import org.apache.slide.jcr.core.version.FrozenNode;
import org.apache.slide.jcr.util.IteratorHelper;
import javax.jcr.*;
@@ -364,6 +365,8 @@
// primary types (i.e. nt:version & nt:versionHistory)
if (state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION_HISTORY)) {
return new VersionHistoryImpl(this, ticket, id, state, def, listeners);
+ } else if (state.getNodeTypeName().equals(NodeTypeRegistry.NT_FROZEN)) {
+ return new FrozenNode(this, ticket, id, state, def, listeners);
} else if (state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION)) {
return new VersionImpl(this, ticket, id, state, def, listeners);
} else {
1.24 +46 -29 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NodeImpl.java
Index: NodeImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NodeImpl.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- NodeImpl.java 20 Jul 2004 08:28:33 -0000 1.23
+++ NodeImpl.java 21 Jul 2004 16:58:03 -0000 1.24
@@ -114,7 +114,7 @@
// mix:referenceable node type
if (name.equals(PROPNAME_UUID)) {
// jcr:uuid property
- genValues = new InternalValue[]{InternalValue.create(new UUID(((NodeState) state).getUUID()))};
+ genValues = new InternalValue[]{InternalValue.create(((NodeState) state).getUUID())};
}
} else if (nt.getQName().equals(NodeTypeRegistry.NT_HIERARCHYNODE)) {
// nt:hierarchyNode node type
@@ -159,7 +159,7 @@
throws RepositoryException {
try {
return (PropertyImpl) getProperty(name);
- } catch (PathNotFoundException pnfe) {
+ } catch (ItemNotFoundException e) {
// does not exist yet:
// find definition for the specified property and create property
PropertyDefImpl def = getApplicablePropertyDef(name, type);
@@ -358,7 +358,7 @@
}
}
- private NodeImpl internalAddNode(String relPath, NodeTypeImpl nodeType)
+ protected NodeImpl internalAddNode(String relPath, NodeTypeImpl nodeType)
throws ItemExistsException, PathNotFoundException,
ConstraintViolationException, RepositoryException {
Path nodePath;
@@ -603,6 +603,10 @@
/**
* Sets the internal value of a property without checking any constraints.
+ * <p/>
+ * Note that no type conversion is being performed, i.e. it's the caller's
+ * responsibility to make sure the type of the given value is compatible
+ * with the specified property's definition.
*
* @param name
* @param value
@@ -610,19 +614,17 @@
* @throws ValueFormatException
* @throws RepositoryException
*/
- protected Property internalSetProperty(QName name, InternalValue value)
+ public Property internalSetProperty(QName name, InternalValue value)
throws ValueFormatException, RepositoryException {
- // check state of this instance
- checkItemState();
-
- int type = (value == null) ? PropertyType.STRING : value.getType();
- PropertyImpl prop = getOrCreateProperty(name, type);
- prop.internalSetValue(new InternalValue[]{value}, type);
- return prop;
+ return internalSetProperty(name, new InternalValue[]{value});
}
/**
* Sets the internal value of a property without checking any constraints.
+ * <p/>
+ * Note that no type conversion is being performed, i.e. it's the caller's
+ * responsibility to make sure the type of the given values is compatible
+ * with the specified property's definition.
*
* @param name
* @param values
@@ -1786,7 +1788,7 @@
throws UnsupportedRepositoryOperationException, RepositoryException {
if (!isNodeType(NodeTypeRegistry.MIX_VERSIONABLE)) {
String msg = "Unable to perform versioning operation on non versionable node: " + safeGetJCRPath();
- log.warn(msg);
+ log.debug(msg);
throw new UnsupportedRepositoryOperationException(msg);
}
}
@@ -1796,10 +1798,21 @@
*/
public Version checkin()
throws UnsupportedRepositoryOperationException, RepositoryException {
- checkVersionable();
-
- // @todo implement versioning support
- throw new UnsupportedRepositoryOperationException();
+ if (!isCheckedOut()) {
+ throw new VersionException("Node is not checked out.");
+ }
+ // check transient state
+ if (isModified()) {
+ throw new IllegalStateException("Checkin not allowed on transient node.");
+ }
+ Version v = rep.getVersionManager().checkin(this);
+ Property prop = internalSetProperty(VersionImpl.PROPNAME_IS_CHECKED_OUT, InternalValue.create(false));
+ prop.save();
+ prop = internalSetProperty(VersionImpl.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(v.getUUID())));
+ prop.save();
+ prop = internalSetProperty(VersionImpl.PROPNAME_PREDESESSORS, new InternalValue[0]);
+ prop.save();
+ return v;
}
/**
@@ -1807,10 +1820,21 @@
*/
public void checkout()
throws UnsupportedRepositoryOperationException, RepositoryException {
- checkVersionable();
+ if (isCheckedOut()) {
+ throw new VersionException("Node already checked out.");
+ }
+ // check transient state
+ if (isModified()) {
+ throw new IllegalStateException("Checkout not allowed on transient node.");
+ }
+ Property prop = internalSetProperty(VersionImpl.PROPNAME_IS_CHECKED_OUT, InternalValue.create(true));
+ prop.save();
+ prop = internalSetProperty(VersionImpl.PROPNAME_PREDESESSORS,
+ new InternalValue[]{
+ InternalValue.create(new UUID(getBaseVersion().getUUID()))
+ });
+ prop.save();
- // @todo implement versioning support
- throw new UnsupportedRepositoryOperationException();
}
/**
@@ -1866,12 +1890,7 @@
public boolean isCheckedOut()
throws UnsupportedRepositoryOperationException, RepositoryException {
checkVersionable();
-
- try {
- return getProperty(VersionImpl.PROPNAME_IS_CHECKED_OUT).getBoolean();
- } catch (ItemNotFoundException infe) {
- return false;
- }
+ return getProperty(VersionImpl.PROPNAME_IS_CHECKED_OUT).getBoolean();
}
/**
@@ -1927,7 +1946,6 @@
public VersionHistory getVersionHistory()
throws UnsupportedRepositoryOperationException, RepositoryException {
checkVersionable();
-
return rep.getVersionManager().getVersionHistory(this);
}
@@ -1937,7 +1955,6 @@
public Version getBaseVersion()
throws UnsupportedRepositoryOperationException, RepositoryException {
checkVersionable();
-
return rep.getVersionManager().getBaseVersion(this);
}
1.16 +28 -24 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java
Index: RepositoryImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- RepositoryImpl.java 20 Jul 2004 08:28:33 -0000 1.15
+++ RepositoryImpl.java 21 Jul 2004 16:58:03 -0000 1.16
@@ -275,13 +275,13 @@
// FIXME version manager should not operate on default workspace
// check system root node of system workspace
- TicketImpl sysTicket = getSystemTicket((WorkspaceDef) wspDefs.get(DEFAULT_WORKSPACE_NAME));
+ TicketImpl sysTicket = getSystemTicket(DEFAULT_WORKSPACE_NAME);
if (!sysTicket.getRootNode().hasNode(SYSTEM_ROOT_NAME.toJCRName(sysTicket.getNamespaceResolver()))) {
sysTicket.getRootNode().addNode(SYSTEM_ROOT_NAME.toJCRName(sysTicket.getNamespaceResolver()), NodeTypeRegistry.NT_UNSTRUCTURED.toJCRName(sysTicket.getNamespaceResolver()));
sysTicket.getRootNode().save();
}
// init version manager
- vMgr = new VersionManager(getSystemTicket((WorkspaceDef) wspDefs.get(DEFAULT_WORKSPACE_NAME)));
+ vMgr = new VersionManager(sysTicket);
// load repository properties
repProps = new Properties();
@@ -294,7 +294,7 @@
// register as an event listener
Iterator iter = wspDefs.values().iterator();
while (iter.hasNext()) {
- Ticket t = getSystemTicket((WorkspaceDef) iter.next());
+ Ticket t = getSystemTicket(((WorkspaceDef) iter.next()).getName());
t.getWorkspace().getObservationManager().addEventListener(this,
EventType.CHILD_NODE_ADDED | EventType.CHILD_NODE_REMOVED |
EventType.PROPERTY_ADDED | EventType.PROPERTY_REMOVED,
@@ -318,12 +318,15 @@
return rootNodeUUID;
}
- synchronized PersistentItemStateManager getWorkspaceStateManager(WorkspaceDef wd)
- throws RepositoryException {
+ synchronized PersistentItemStateManager getWorkspaceStateManager(String workspaceName)
+ throws NoSuchWorkspaceException, RepositoryException {
+ WorkspaceDef wd = (WorkspaceDef) wspDefs.get(workspaceName);
+ if (wd == null) {
+ throw new NoSuchWorkspaceException(workspaceName);
+ }
// get/create per named workspace (i.e. per physical storage) item state manager
- String wspName = wd.getName();
PersistentItemStateManager stateMgr =
- (PersistentItemStateManager) wspStateMgrs.get(wspName);
+ (PersistentItemStateManager) wspStateMgrs.get(workspaceName);
if (stateMgr == null) {
if (wd.isDynamic()) {
/*
@@ -347,30 +350,32 @@
throw new RepositoryException(msg, ise);
}
}
- wspStateMgrs.put(wspName, stateMgr);
+ wspStateMgrs.put(workspaceName, stateMgr);
}
return stateMgr;
}
- synchronized ObservationManagerFactory getObservationManagerFactory(WorkspaceDef wd) {
- String wspName = wd.getName();
+ synchronized ObservationManagerFactory getObservationManagerFactory(String workspaceName)
+ throws NoSuchWorkspaceException {
+ if (!wspDefs.containsKey(workspaceName)) {
+ throw new NoSuchWorkspaceException(workspaceName);
+ }
ObservationManagerFactory obsMgr
- = (ObservationManagerFactory) wspObsMgrFactory.get(wspName);
+ = (ObservationManagerFactory) wspObsMgrFactory.get(workspaceName);
if (obsMgr == null) {
obsMgr = new ObservationManagerFactory();
- wspObsMgrFactory.put(wspName, obsMgr);
+ wspObsMgrFactory.put(workspaceName, obsMgr);
}
return obsMgr;
}
- synchronized SystemTicket getSystemTicket(WorkspaceDef wd)
- throws RepositoryException {
- String wspName = wd.getName();
+ synchronized SystemTicket getSystemTicket(String workspaceName)
+ throws NoSuchWorkspaceException, RepositoryException {
SystemTicket systemTicket
- = (SystemTicket) wspSystemTickets.get(wspName);
+ = (SystemTicket) wspSystemTickets.get(workspaceName);
if (systemTicket == null) {
- systemTicket = new SystemTicket(this, wd);
- wspSystemTickets.put(wspName, systemTicket);
+ systemTicket = new SystemTicket(this, workspaceName);
+ wspSystemTickets.put(workspaceName, systemTicket);
}
return systemTicket;
}
@@ -521,14 +526,13 @@
if (workspaceName == null) {
workspaceName = DEFAULT_WORKSPACE_NAME;
}
- WorkspaceDef wd = (WorkspaceDef) wspDefs.get(workspaceName);
- if (wd == null) {
+ if (!wspDefs.containsKey(workspaceName)) {
throw new NoSuchWorkspaceException(workspaceName);
}
if (credentials == null) {
// anonymous login
try {
- return new TicketImpl(this, ANONYMOUS_CREDENTIALS, wd);
+ return new TicketImpl(this, ANONYMOUS_CREDENTIALS, workspaceName);
} catch (RepositoryException re) {
String msg = "failed to instantiate ticket";
log.error(msg, re);
@@ -539,7 +543,7 @@
// @todo implement authentication/authorization
try {
- return new TicketImpl(this, credentials, wd);
+ return new TicketImpl(this, credentials, workspaceName);
} catch (RepositoryException re) {
String msg = "failed to instantiate ticket";
log.error(msg, re);
1.3 +5 -4 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/SystemTicket.java
Index: SystemTicket.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/SystemTicket.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- SystemTicket.java 20 Jul 2004 08:28:33 -0000 1.2
+++ SystemTicket.java 21 Jul 2004 16:58:03 -0000 1.3
@@ -44,10 +44,11 @@
* Package private constructor.
*
* @param rep
+ * @param wspName
*/
- SystemTicket(RepositoryImpl rep, WorkspaceDef wd)
+ SystemTicket(RepositoryImpl rep, String wspName)
throws RepositoryException {
- super(rep, SYSTEM_USER_ID, wd);
+ super(rep, SYSTEM_USER_ID, wspName);
accessMgr = new SystemAccessManqager();
}
1.10 +4 -3 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/Test.java
Index: Test.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/Test.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- Test.java 20 Jul 2004 08:28:33 -0000 1.9
+++ Test.java 21 Jul 2004 16:58:03 -0000 1.10
@@ -130,8 +130,6 @@
root.save();
- //t.getWorkspace().move("/imported/src", "/misc/gurk");
-
System.out.println("after save()...");
System.out.println();
dumpTree(root, System.out);
@@ -190,6 +188,9 @@
dumpTree(root, System.out);
root.save();
+
+ t.getWorkspace().copy("/imported", "/misc/bla");
+ t.getWorkspace().move("/misc/bla", "/misc/blabla");
System.out.println("after save()...");
System.out.println();
1.15 +8 -8 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/TicketImpl.java
Index: TicketImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/TicketImpl.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- TicketImpl.java 20 Jul 2004 08:28:33 -0000 1.14
+++ TicketImpl.java 21 Jul 2004 16:58:03 -0000 1.15
@@ -105,9 +105,9 @@
*
* @param rep
* @param credentials
- * @param wd
+ * @param wspName
*/
- TicketImpl(RepositoryImpl rep, Credentials credentials, WorkspaceDef wd)
+ TicketImpl(RepositoryImpl rep, Credentials credentials, String wspName)
throws RepositoryException {
this.rep = rep;
@@ -132,7 +132,7 @@
nsMappings = new TransientNamespaceMappings(rep.getNamespaceRegistry());
ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), getNamespaceResolver());
- wsp = new WorkspaceImpl(wd, rep.getWorkspaceStateManager(wd), rep, this);
+ wsp = new WorkspaceImpl(wspName, rep.getWorkspaceStateManager(wspName), rep, this);
itemStateMgr = new TicketItemStateManager(rep.getRootNodeUUID(), wsp.getPersistentStateManager(), getNamespaceResolver());
hierMgr = itemStateMgr.getHierarchyMgr();
itemMgr = new ItemManager(itemStateMgr, hierMgr, this, ntMgr.getRootNodeDefinition(), rep.getRootNodeUUID());
@@ -144,9 +144,9 @@
*
* @param rep
* @param userId
- * @param wd
+ * @param wspName
*/
- protected TicketImpl(RepositoryImpl rep, String userId, WorkspaceDef wd)
+ protected TicketImpl(RepositoryImpl rep, String userId, String wspName)
throws RepositoryException {
this.rep = rep;
@@ -155,7 +155,7 @@
nsMappings = new TransientNamespaceMappings(rep.getNamespaceRegistry());
ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), getNamespaceResolver());
- wsp = new WorkspaceImpl(wd, rep.getWorkspaceStateManager(wd), rep, this);
+ wsp = new WorkspaceImpl(wspName, rep.getWorkspaceStateManager(wspName), rep, this);
itemStateMgr = new TicketItemStateManager(rep.getRootNodeUUID(), wsp.getPersistentStateManager(), getNamespaceResolver());
hierMgr = itemStateMgr.getHierarchyMgr();
itemMgr = new ItemManager(itemStateMgr, hierMgr, this, ntMgr.getRootNodeDefinition(), rep.getRootNodeUUID());
1.7 +311 -178 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/WorkspaceImpl.java
Index: WorkspaceImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/WorkspaceImpl.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- WorkspaceImpl.java 20 Jul 2004 08:28:33 -0000 1.6
+++ WorkspaceImpl.java 21 Jul 2004 16:58:03 -0000 1.7
@@ -53,7 +53,7 @@
/**
* A <code>WorkspaceImpl</code> ...
- *
+ *
* @author Stefan Guggisberg
* @version $Revision$, $Date$
*/
@@ -62,9 +62,9 @@
private static Logger log = Logger.getLogger(WorkspaceImpl.class);
/**
- * The <code>WorkspaceDef</code> for this <code>Workspace</code> instance.
+ * The name of this <code>Workspace</code>
*/
- protected final WorkspaceDef wsDef;
+ protected final String wspName;
/**
* The repository that created this workspace instance
@@ -96,14 +96,14 @@
/**
* Package private constructor.
- *
- * @param wsDef
- * @param persistentStateMgr
- * @param rep
- * @param ticket
+ *
+ * @param wspName
+ * @param persistentStateMgr
+ * @param rep
+ * @param ticket
*/
- WorkspaceImpl(WorkspaceDef wsDef, PersistentItemStateManager persistentStateMgr, RepositoryImpl rep, TicketImpl ticket) {
- this.wsDef = wsDef;
+ WorkspaceImpl(String wspName, PersistentItemStateManager persistentStateMgr, RepositoryImpl rep, TicketImpl ticket) {
+ this.wspName = wspName;
this.rep = rep;
this.persistentStateMgr = persistentStateMgr;
hierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(), persistentStateMgr, ticket.getNamespaceResolver());
@@ -121,12 +121,12 @@
/**
* Dumps the state of this <code>Workspace</code> instance
* (used for diagnostic purposes).
- *
- * @param ps
- * @throws RepositoryException
+ *
+ * @param ps
+ * @throws RepositoryException
*/
void dump(PrintStream ps) throws RepositoryException {
- ps.println("Workspace: " + wsDef.getName() + " (" + this + ")");
+ ps.println("Workspace: " + wspName + " (" + this + ")");
ps.println();
persistentStateMgr.dump(ps);
}
@@ -148,17 +148,23 @@
}
}
+ //-----------< misc. static helper methods for cross-workspace operations >
/**
- *
* @param nodePath
+ * @param nsResolver
+ * @param hierMgr
+ * @param stateMgr
* @return
* @throws PathNotFoundException
* @throws RepositoryException
*/
- protected PersistentNodeState getNodeState(String nodePath)
- throws PathNotFoundException, RepositoryException {
+ protected static PersistentNodeState getNodeState(String nodePath,
+ NamespaceResolver nsResolver,
+ HierarchyManagerImpl hierMgr,
+ PersistentItemStateManager stateMgr)
+ throws PathNotFoundException, RepositoryException {
try {
- return getNodeState(Path.create(nodePath, ticket.getNamespaceResolver(), true));
+ return getNodeState(Path.create(nodePath, nsResolver, true), hierMgr, stateMgr);
} catch (MalformedPathException mpe) {
String msg = "invalid path: " + nodePath;
log.error(msg, mpe);
@@ -167,16 +173,22 @@
}
/**
- *
* @param path
+ * @param nsResolver
+ * @param hierMgr
+ * @param stateMgr
* @return
* @throws PathNotFoundException
* @throws RepositoryException
*/
- protected PersistentNodeState getParentNodeState(String path)
- throws PathNotFoundException, RepositoryException {
+ protected static PersistentNodeState getParentNodeState(String path,
+ NamespaceResolver nsResolver,
+ HierarchyManagerImpl hierMgr,
+ PersistentItemStateManager stateMgr)
+
+ throws PathNotFoundException, RepositoryException {
try {
- return getNodeState(Path.create(path, ticket.getNamespaceResolver(), true).getAncestor(1));
+ return getNodeState(Path.create(path, nsResolver, true).getAncestor(1), hierMgr, stateMgr);
} catch (MalformedPathException mpe) {
String msg = "invalid path: " + path;
log.error(msg, mpe);
@@ -185,20 +197,23 @@
}
/**
- *
- * @param nodePath
- * @return
- * @throws PathNotFoundException
- * @throws RepositoryException
- */
- protected PersistentNodeState getNodeState(Path nodePath)
- throws PathNotFoundException, RepositoryException {
+ * @param nodePath
+ * @param hierMgr
+ * @param stateMgr
+ * @return
+ * @throws PathNotFoundException
+ * @throws RepositoryException
+ */
+ protected static PersistentNodeState getNodeState(Path nodePath,
+ HierarchyManagerImpl hierMgr,
+ PersistentItemStateManager stateMgr)
+ throws PathNotFoundException, RepositoryException {
try {
ItemId id = hierMgr.resolvePath(nodePath);
if (!id.denotesNode()) {
throw new PathNotFoundException(hierMgr.safeGetJCRPath(nodePath));
}
- return getNodeState((NodeId) id);
+ return getNodeState((NodeId) id, stateMgr);
} catch (NoSuchItemStateException nsise) {
throw new PathNotFoundException(hierMgr.safeGetJCRPath(nodePath));
} catch (ItemStateException ise) {
@@ -209,37 +224,44 @@
}
/**
- *
* @param id
+ * @param stateMgr
* @return
* @throws NoSuchItemStateException
* @throws ItemStateException
*/
- protected PersistentNodeState getNodeState(NodeId id)
- throws NoSuchItemStateException, ItemStateException {
- return (PersistentNodeState) persistentStateMgr.getItemState(id);
+ protected static PersistentNodeState getNodeState(NodeId id,
+ PersistentItemStateManager stateMgr)
+ throws NoSuchItemStateException, ItemStateException {
+ return (PersistentNodeState) stateMgr.getItemState(id);
}
/**
- *
* @param nodePath
* @param nodeTypeName
+ * @param ntReg
+ * @param accessMgr
+ * @param hierMgr
+ * @param stateMgr
* @throws ConstraintViolationException
* @throws AccessDeniedException
* @throws PathNotFoundException
* @throws ItemExistsException
* @throws RepositoryException
*/
- protected void checkAddNode(Path nodePath, QName nodeTypeName)
- throws ConstraintViolationException, AccessDeniedException,
- PathNotFoundException, ItemExistsException, RepositoryException {
+ protected static void checkAddNode(Path nodePath, QName nodeTypeName,
+ NodeTypeRegistry ntReg,
+ AccessManagerImpl accessMgr,
+ HierarchyManagerImpl hierMgr,
+ PersistentItemStateManager stateMgr)
+ throws ConstraintViolationException, AccessDeniedException,
+ PathNotFoundException, ItemExistsException, RepositoryException {
Path parentPath = nodePath.getAncestor(1);
- PersistentNodeState parentState = getNodeState(parentPath);
+ PersistentNodeState parentState = getNodeState(parentPath, hierMgr, stateMgr);
// 1. check path & access rights
- AccessManagerImpl accessMgr = ticket.getAccessManager();
Path.PathElement nodeName = nodePath.getNameElement();
try {
// check access rights
@@ -257,13 +279,13 @@
// 2. check note type constraints
- ChildNodeDef parentDef = getDefinition(parentPath);
+ ChildNodeDef parentDef = getDefinition(parentPath, ntReg, hierMgr, stateMgr);
if (parentDef.isProtected()) {
throw new ConstraintViolationException(hierMgr.safeGetJCRPath(parentPath) + ": cannot add child node to protected parent node");
}
- EffectiveNodeType entParent = getEffectiveNodeType(parentState);
+ EffectiveNodeType entParent = getEffectiveNodeType(parentState, ntReg);
entParent.checkAddNodeConstraints(nodeName.getName(), nodeTypeName);
- ChildNodeDef newNodeDef = findApplicableDefinition(nodeName.getName(), nodeTypeName, parentState);
+ ChildNodeDef newNodeDef = findApplicableDefinition(nodeName.getName(), nodeTypeName, parentState, ntReg);
// 3. check for name collisions
@@ -279,13 +301,13 @@
NodeState conflictingState;
NodeId conflictingId = new NodeId(entry.getUUID());
try {
- conflictingState = (NodeState) persistentStateMgr.getItemState(conflictingId);
+ conflictingState = (NodeState) stateMgr.getItemState(conflictingId);
} catch (ItemStateException ise) {
String msg = "internal error: failed to retrieve state of " + hierMgr.safeGetJCRPath(conflictingId);
log.error(msg, ise);
throw new RepositoryException(msg, ise);
}
- ChildNodeDef conflictingTargetDef = getDefinition(conflictingState, nodeName.getName(), parentState);
+ ChildNodeDef conflictingTargetDef = getDefinition(conflictingState, nodeName.getName(), parentState, ntReg);
// check same-name sibling setting of both target and existing node
if (!conflictingTargetDef.allowSameNameSibs() ||
!newNodeDef.allowSameNameSibs()) {
@@ -295,24 +317,30 @@
}
/**
- *
* @param nodePath
+ * @param ntReg
+ * @param accessMgr
+ * @param hierMgr
+ * @param stateMgr
* @throws ConstraintViolationException
* @throws AccessDeniedException
* @throws PathNotFoundException
* @throws RepositoryException
*/
- protected void checkRemoveNode(Path nodePath)
- throws ConstraintViolationException, AccessDeniedException,
- PathNotFoundException, RepositoryException {
+ protected static void checkRemoveNode(Path nodePath,
+ NodeTypeRegistry ntReg,
+ AccessManagerImpl accessMgr,
+ HierarchyManagerImpl hierMgr,
+ PersistentItemStateManager stateMgr)
+ throws ConstraintViolationException, AccessDeniedException,
+ PathNotFoundException, RepositoryException {
- PersistentNodeState targetState = getNodeState(nodePath);
+ PersistentNodeState targetState = getNodeState(nodePath, hierMgr, stateMgr);
Path parentPath = nodePath.getAncestor(1);
- PersistentNodeState parentState = getNodeState(parentPath);
+ PersistentNodeState parentState = getNodeState(parentPath, hierMgr, stateMgr);
// 1. check path & access rights
- AccessManagerImpl accessMgr = ticket.getAccessManager();
try {
// check access rights
if (!accessMgr.isGranted(targetState.getId(), Permission.READ_ITEM)) {
@@ -329,11 +357,11 @@
// 2. check note type constraints
- ChildNodeDef parentDef = getDefinition(parentPath);
+ ChildNodeDef parentDef = getDefinition(parentPath, ntReg, hierMgr, stateMgr);
if (parentDef.isProtected()) {
throw new ConstraintViolationException(hierMgr.safeGetJCRPath(parentPath) + ": cannot remove child node of protected parent node");
}
- ChildNodeDef targetDef = getDefinition(nodePath);
+ ChildNodeDef targetDef = getDefinition(nodePath, ntReg, hierMgr, stateMgr);
if (targetDef.isMandatory()) {
throw new ConstraintViolationException(hierMgr.safeGetJCRPath(nodePath) + ": cannot remove mandatory node");
}
@@ -348,13 +376,14 @@
* node types.
*
* @param state
+ * @param ntReg
* @return the effective node type
* @throws RepositoryException
*/
- protected EffectiveNodeType getEffectiveNodeType(NodeState state)
+ protected static EffectiveNodeType getEffectiveNodeType(NodeState state,
+ NodeTypeRegistry ntReg)
throws RepositoryException {
- // build effective node type of mixins & primary type
- NodeTypeRegistry ntReg = ticket.getNodeTypeManager().getNodeTypeRegistry();
+ // build effective node type of mixins & primary type:
// existing mixin's
HashSet set = new HashSet(((NodeState) state).getMixinTypeNames());
// primary type
@@ -372,21 +401,32 @@
* Helper method that returns the definition of the specified node.
*
* @param nodePath
+ * @param ntReg
+ * @param hierMgr
+ * @param stateMgr
* @return
* @throws PathNotFoundException
- * @throws RepositoryException if no applicable child node definition
- * could be found or if another error occured
+ * @throws RepositoryException if no applicable child node definition
+ * could be found or if another error occured
*/
- protected ChildNodeDef getDefinition(Path nodePath)
+ protected static ChildNodeDef getDefinition(Path nodePath,
+ NodeTypeRegistry ntReg,
+ HierarchyManagerImpl hierMgr,
+ PersistentItemStateManager stateMgr)
throws PathNotFoundException, RepositoryException {
- NodeState state = getNodeState(nodePath);
- NodeState parentState = getNodeState(nodePath.getAncestor(1));
+ if (nodePath.denotesRoot()) {
+ // shortcut
+ return ntReg.getRootNodeDef();
+ }
+ NodeState state = getNodeState(nodePath, hierMgr, stateMgr);
NodeDefId defId = state.getDefinitionId();
if (defId != null) {
- return ticket.getNodeTypeManager().getNodeDef(defId).unwrap();
+ return ntReg.getNodeDef(defId);
} else {
// fallback: find matching definition in parent node's node type
- return findApplicableDefinition(nodePath.getNameElement().getName(), state.getNodeTypeName(), parentState);
+ NodeState parentState = getNodeState(nodePath.getAncestor(1), hierMgr, stateMgr);
+ return findApplicableDefinition(nodePath.getNameElement().getName(),
+ state.getNodeTypeName(), parentState, ntReg);
}
}
@@ -396,18 +436,21 @@
* @param state
* @param name
* @param parentState
+ * @param ntReg
* @return a <code>ChildNodeDef</code>
* @throws RepositoryException if no applicable child node definition
* could be found
*/
- protected ChildNodeDef getDefinition(NodeState state, QName name, NodeState parentState)
+ protected static ChildNodeDef getDefinition(NodeState state, QName name,
+ NodeState parentState,
+ NodeTypeRegistry ntReg)
throws RepositoryException {
NodeDefId defId = state.getDefinitionId();
if (defId != null) {
- return ticket.getNodeTypeManager().getNodeDef(defId).unwrap();
+ return ntReg.getNodeDef(defId);
} else {
// fallback: find matching definition in parent node's node type
- return findApplicableDefinition(name, state.getNodeTypeName(), parentState);
+ return findApplicableDefinition(name, state.getNodeTypeName(), parentState, ntReg);
}
}
@@ -415,48 +458,61 @@
* Helper method that finds the applicable definition for the
* a child node with the given name and node type in the parent node's
* node type and mixin types.
- *
- * @param name
- * @param nodeTypeName
- * @param parentState
+ *
+ * @param name
+ * @param nodeTypeName
+ * @param parentState
+ * @param ntReg
* @return a <code>ChildNodeDef</code>
* @throws ConstraintViolationException if no applicable child node definition
* could be found
* @throws RepositoryException if another error occurs
*/
- protected ChildNodeDef findApplicableDefinition(QName name, QName nodeTypeName, NodeState parentState)
+ protected static ChildNodeDef findApplicableDefinition(QName name,
+ QName nodeTypeName,
+ NodeState parentState,
+ NodeTypeRegistry ntReg)
throws RepositoryException, ConstraintViolationException {
- EffectiveNodeType entParent = getEffectiveNodeType(parentState);
+ EffectiveNodeType entParent = getEffectiveNodeType(parentState, ntReg);
return entParent.getApplicableChildNodeDef(name, nodeTypeName);
}
- private PersistentNodeState copyNodeState(NodeState srcState, String parentUUID)
+ private static PersistentNodeState copyNodeState(NodeState srcState,
+ String parentUUID,
+ NodeTypeRegistry ntReg,
+ HierarchyManagerImpl srcHierMgr,
+ PersistentItemStateManager srcStateMgr,
+ PersistentItemStateManager destStateMgr)
throws RepositoryException {
PersistentNodeState newState;
try {
String uuid = new UUID().toString(); // create new version 4 uuid
- newState = persistentStateMgr.createNodeState(uuid, srcState.getNodeTypeName(), parentUUID);
+ newState = destStateMgr.createNodeState(uuid, srcState.getNodeTypeName(), parentUUID);
// copy node state
+ // @todo special handling required for nodes with special semantics (e.g. those defined by mix:versionable, et.al.)
+ // FIXME delegate to 'node type instance handler'
newState.setMixinTypeNames(srcState.getMixinTypeNames());
newState.setDefinitionId(srcState.getDefinitionId());
// copy child nodes
Iterator iter = srcState.getChildNodeEntries().iterator();
while (iter.hasNext()) {
NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
- NodeState childState = (NodeState) persistentStateMgr.getItemState(new NodeId(entry.getUUID()));
+ NodeState srcChildState = (NodeState) srcStateMgr.getItemState(new NodeId(entry.getUUID()));
// recursive copying of child node
- PersistentNodeState newChildState = copyNodeState(childState, uuid);
+ PersistentNodeState newChildState = copyNodeState(srcChildState, uuid,
+ ntReg, srcHierMgr, srcStateMgr, destStateMgr);
// persist new child node
newChildState.store();
// add new child node entry to new node
newState.addChildNodeEntry(entry.getName(), newChildState.getUUID());
}
// copy properties
- iter = srcState.getChildNodeEntries().iterator();
+ iter = srcState.getPropertyEntries().iterator();
while (iter.hasNext()) {
NodeState.PropertyEntry entry = (NodeState.PropertyEntry) iter.next();
- PropertyState childState = (PropertyState) persistentStateMgr.getItemState(new PropertyId(uuid, entry.getName()));
- PersistentPropertyState newChildState = copyPropertyState(childState, uuid, entry.getName());
+ PropertyState srcChildState = (PropertyState) srcStateMgr.getItemState(new PropertyId(srcState.getUUID(), entry.getName()));
+ PersistentPropertyState newChildState = copyPropertyState(srcChildState, uuid, entry.getName(),
+ ntReg, srcHierMgr, srcStateMgr, destStateMgr);
// persist new property
newChildState.store();
// add new property entry to new node
@@ -464,18 +520,26 @@
}
return newState;
} catch (ItemStateException ise) {
- String msg = "internal error: failed to copy state of " + hierMgr.safeGetJCRPath(srcState.getId());
+ String msg = "internal error: failed to copy state of " + srcHierMgr.safeGetJCRPath(srcState.getId());
log.error(msg, ise);
throw new RepositoryException(msg, ise);
}
}
- private PersistentPropertyState copyPropertyState(PropertyState srcState, String parentUUID, QName propName)
+ private static PersistentPropertyState copyPropertyState(PropertyState srcState,
+ String parentUUID,
+ QName propName,
+ NodeTypeRegistry ntReg,
+ HierarchyManagerImpl srcHierMgr,
+ PersistentItemStateManager srcStateMgr,
+ PersistentItemStateManager destStateMgr)
throws RepositoryException {
+ // @todo special handling required for properties with special semantics (e.g. those defined by mix:versionable, et.al.)
PersistentPropertyState newState;
try {
- newState = persistentStateMgr.createPropertyState(parentUUID, propName);
- newState.setDefinitionId(srcState.getDefinitionId());
+ newState = destStateMgr.createPropertyState(parentUUID, propName);
+ PropDefId defId = srcState.getDefinitionId();
+ newState.setDefinitionId(defId);
newState.setType(srcState.getType());
InternalValue[] values = srcState.getValues();
if (values != null) {
@@ -484,64 +548,34 @@
newValues[i] = values[i] != null ? values[i].createCopy() : null;
}
newState.setValues(values);
+ // FIXME delegate to 'node type instance handler'
+ if (defId != null) {
+ PropDef def = ntReg.getPropDef(defId);
+ if (def.getDeclaringNodeType().equals(NodeTypeRegistry.MIX_REFERENCEABLE)) {
+ if (propName.equals(ItemImpl.PROPNAME_UUID)) {
+ // set correct value of jcr:uuid property
+ newState.setValues(new InternalValue[]{InternalValue.create(parentUUID)});
+ }
+ }
+ }
}
return newState;
} catch (ItemStateException ise) {
- String msg = "internal error: failed to copy state of " + hierMgr.safeGetJCRPath(srcState.getId());
+ String msg = "internal error: failed to copy state of " + srcHierMgr.safeGetJCRPath(srcState.getId());
log.error(msg, ise);
throw new RepositoryException(msg, ise);
}
}
- //------------------------------------------------------------< Workspace >
- /**
- * @see Workspace#getName
- */
- public String getName() {
- return wsDef.getName();
- }
-
- /**
- * @see Workspace#getTicket
- */
- public Ticket getTicket() {
- return ticket;
- }
-
- /**
- * @see Workspace#getQueryManager
- */
- public QueryManager getQueryManager() {
- // @todo implement query support
- return null;
- }
-
- /**
- * @see Workspace#getNamespaceRegistry
- */
- public NamespaceRegistry getNamespaceRegistry() {
- return rep.getNamespaceRegistry();
- }
-
- /**
- * @see Workspace#getNodeTypeManager
- */
- public NodeTypeManager getNodeTypeManager() {
- return ticket.getNodeTypeManager();
- }
-
- /**
- * @see Workspace#clone(String, String, String)
- */
- public void clone(String srcAbsPath, String destAbsPath, String destWorkspace) throws NoSuchWorkspaceException, ConstraintViolationException, AccessDeniedException, PathNotFoundException, ItemExistsException, RepositoryException {
- // @todo implement workspace clone
- throw new RepositoryException("not yet implemented");
- }
-
- /**
- * @see Workspace#copy(String, String)
- */
- public void copy(String srcAbsPath, String destAbsPath)
+ private static void internalCopy(String srcAbsPath,
+ PersistentItemStateManager srcStateMgr,
+ HierarchyManagerImpl srcHierMgr,
+ String destAbsPath,
+ PersistentItemStateManager destStateMgr,
+ HierarchyManagerImpl destHierMgr,
+ AccessManagerImpl accessMgr,
+ NamespaceResolver nsResolver,
+ NodeTypeRegistry ntReg)
throws ConstraintViolationException, AccessDeniedException,
PathNotFoundException, ItemExistsException, RepositoryException {
@@ -550,8 +584,8 @@
Path srcPath;
PersistentNodeState srcState;
try {
- srcPath = Path.create(srcAbsPath, ticket.getNamespaceResolver(), true);
- srcState = getNodeState(srcPath);
+ srcPath = Path.create(srcAbsPath, nsResolver, true);
+ srcState = getNodeState(srcPath, srcHierMgr, srcStateMgr);
} catch (MalformedPathException mpe) {
String msg = "invalid path: " + srcAbsPath;
log.error(msg, mpe);
@@ -563,10 +597,10 @@
Path destParentPath;
PersistentNodeState destParentState;
try {
- destPath = Path.create(destAbsPath, ticket.getNamespaceResolver(), true);
+ destPath = Path.create(destAbsPath, nsResolver, true);
destName = destPath.getNameElement();
destParentPath = destPath.getAncestor(1);
- destParentState = getNodeState(destParentPath);
+ destParentState = getNodeState(destParentPath, destHierMgr, destStateMgr);
} catch (MalformedPathException mpe) {
String msg = "invalid path: " + destAbsPath;
log.error(msg, mpe);
@@ -577,7 +611,7 @@
try {
// check read access right on source node
- if (!ticket.getAccessManager().isGranted(srcState.getId(), Permission.READ_ITEM)) {
+ if (!accessMgr.isGranted(srcState.getId(), Permission.READ_ITEM)) {
throw new PathNotFoundException(srcAbsPath);
}
} catch (ItemNotFoundException infe) {
@@ -585,15 +619,9 @@
log.error(msg, infe);
throw new RepositoryException(msg, infe);
}
- checkAddNode(destPath, srcState.getNodeTypeName());
-
- // 3. do copy operation (modify and persist affected states)
-
- // create new node state
- String uuid = new UUID().toString(); // create new version 4 uuid
- PersistentNodeState newState = copyNodeState(srcState, uuid);
-
- // add to new parent
+ // check node type constraints
+ checkAddNode(destPath, srcState.getNodeTypeName(), ntReg, accessMgr, destHierMgr, destStateMgr);
+ // check if target node needs to be inserted at specific location in child node entries list
boolean insertTargetEntry = false;
int ind = destName.getIndex();
if (ind > 0) {
@@ -607,6 +635,20 @@
}
insertTargetEntry = (ind < sameNameSibs.size() + 1) ? true : false;
}
+ if (insertTargetEntry) {
+ // check hasOrderableChildNodes flag
+ if (!ntReg.getNodeTypeDef(destParentState.getNodeTypeName()).hasOrderableChildNodes()) {
+ throw new ConstraintViolationException(destAbsPath + ": parent node's node type does not allow explicit ordering of child nodes");
+ }
+ }
+
+ // 3. do copy operation (modify and persist affected states)
+
+ // create deep copy of source node state
+ PersistentNodeState newState = copyNodeState(srcState, destParentState.getUUID(),
+ ntReg, srcHierMgr, srcStateMgr, destStateMgr);
+
+ // add to new parent
if (!insertTargetEntry) {
// append target entry
destParentState.addChildNodeEntry(destName.getName(), newState.getUUID());
@@ -624,7 +666,7 @@
}
}
// change definition (id) of new node
- ChildNodeDef newNodeDef = findApplicableDefinition(destName.getName(), srcState.getNodeTypeName(), destParentState);
+ ChildNodeDef newNodeDef = findApplicableDefinition(destName.getName(), srcState.getNodeTypeName(), destParentState, ntReg);
newState.setDefinitionId(new NodeDefId(newNodeDef));
// persist states
@@ -638,6 +680,62 @@
}
}
+ //------------------------------------------------------------< Workspace >
+ /**
+ * @see Workspace#getName
+ */
+ public String getName() {
+ return wspName;
+ }
+
+ /**
+ * @see Workspace#getTicket
+ */
+ public Ticket getTicket() {
+ return ticket;
+ }
+
+ /**
+ * @see Workspace#getNamespaceRegistry
+ */
+ public NamespaceRegistry getNamespaceRegistry() {
+ return rep.getNamespaceRegistry();
+ }
+
+ /**
+ * @see Workspace#getNodeTypeManager
+ */
+ public NodeTypeManager getNodeTypeManager() {
+ return ticket.getNodeTypeManager();
+ }
+
+ /**
+ * @see Workspace#clone(String, String, String)
+ */
+ public void clone(String srcAbsPath, String destAbsPath, String destWorkspace) throws NoSuchWorkspaceException, ConstraintViolationException, AccessDeniedException, PathNotFoundException, ItemExistsException, RepositoryException {
+ PersistentItemStateManager destStateMgr = rep.getWorkspaceStateManager(destWorkspace);
+ // FIXME need to setup a hierarchy manager for destination workspace
+ HierarchyManagerImpl destHierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(), destStateMgr, ticket.getNamespaceResolver());
+ // do cross-workspace copy
+ internalCopy(srcAbsPath, persistentStateMgr, hierMgr,
+ destAbsPath, destStateMgr, destHierMgr,
+ ticket.getAccessManager(), ticket.getNamespaceResolver(),
+ rep.getNodeTypeRegistry());
+ }
+
+ /**
+ * @see Workspace#copy(String, String)
+ */
+ public void copy(String srcAbsPath, String destAbsPath)
+ throws ConstraintViolationException, AccessDeniedException,
+ PathNotFoundException, ItemExistsException, RepositoryException {
+ // do intra-workspace copy
+ internalCopy(srcAbsPath, persistentStateMgr, hierMgr,
+ destAbsPath, persistentStateMgr, hierMgr,
+ ticket.getAccessManager(), ticket.getNamespaceResolver(),
+ rep.getNodeTypeRegistry());
+ }
+
/**
* @see Workspace#move
*/
@@ -645,6 +743,8 @@
throws ConstraintViolationException, AccessDeniedException,
PathNotFoundException, ItemExistsException, RepositoryException {
+ // intra-workspace move...
+
// 1. check paths & retrieve state
Path srcPath;
@@ -656,8 +756,8 @@
srcPath = Path.create(srcAbsPath, ticket.getNamespaceResolver(), true);
srcName = srcPath.getNameElement();
srcParentPath = srcPath.getAncestor(1);
- targetState = getNodeState(srcPath);
- srcParentState = getNodeState(srcParentPath);
+ targetState = getNodeState(srcPath, hierMgr, persistentStateMgr);
+ srcParentState = getNodeState(srcParentPath, hierMgr, persistentStateMgr);
} catch (MalformedPathException mpe) {
String msg = "invalid path: " + srcAbsPath;
log.error(msg, mpe);
@@ -672,7 +772,7 @@
destPath = Path.create(destAbsPath, ticket.getNamespaceResolver(), true);
destName = destPath.getNameElement();
destParentPath = destPath.getAncestor(1);
- destParentState = getNodeState(destParentPath);
+ destParentState = getNodeState(destParentPath, hierMgr, persistentStateMgr);
} catch (MalformedPathException mpe) {
String msg = "invalid path: " + destAbsPath;
log.error(msg, mpe);
@@ -681,17 +781,11 @@
// 2. check node type constraints & access rights
- checkRemoveNode(srcPath);
- checkAddNode(destPath, targetState.getNodeTypeName());
-
- // 3. do move operation (modify and persist affected states)
-
- boolean renameOnly = srcParentState.getUUID().equals(destParentState.getUUID());
-
- // add to new parent
- if (!renameOnly) {
- targetState.addParentUUID(destParentState.getUUID());
- }
+ checkRemoveNode(srcPath, rep.getNodeTypeRegistry(), ticket.getAccessManager(), hierMgr, persistentStateMgr);
+ checkAddNode(destPath, targetState.getNodeTypeName(),
+ rep.getNodeTypeRegistry(), ticket.getAccessManager(),
+ hierMgr, persistentStateMgr);
+ // check if target node needs to be inserted at specific location in child node entries list
boolean insertTargetEntry = false;
int ind = destName.getIndex();
if (ind > 0) {
@@ -705,6 +799,21 @@
}
insertTargetEntry = (ind < sameNameSibs.size() + 1) ? true : false;
}
+ if (insertTargetEntry) {
+ // check hasOrderableChildNodes flag
+ if (!rep.getNodeTypeRegistry().getNodeTypeDef(destParentState.getNodeTypeName()).hasOrderableChildNodes()) {
+ throw new ConstraintViolationException(destAbsPath + ": parent node's node type does not allow explicit ordering of child nodes");
+ }
+ }
+
+ // 3. do move operation (modify and persist affected states)
+
+ boolean renameOnly = srcParentState.getUUID().equals(destParentState.getUUID());
+
+ // add to new parent
+ if (!renameOnly) {
+ targetState.addParentUUID(destParentState.getUUID());
+ }
if (!insertTargetEntry) {
// append target entry
destParentState.addChildNodeEntry(destName.getName(), targetState.getUUID());
@@ -722,14 +831,22 @@
}
}
// change definition (id) of target node
- ChildNodeDef newTargetDef = findApplicableDefinition(destName.getName(), targetState.getNodeTypeName(), destParentState);
+ ChildNodeDef newTargetDef = findApplicableDefinition(destName.getName(), targetState.getNodeTypeName(), destParentState, rep.getNodeTypeRegistry());
targetState.setDefinitionId(new NodeDefId(newTargetDef));
// remove from old parent
if (!renameOnly) {
targetState.removeParentUUID(srcParentState.getUUID());
}
- srcParentState.removeChildNodeEntry(srcName.getName(), srcName.getIndex() == 0 ? 1 : srcName.getIndex());
+ int srcNameIndex = srcName.getIndex() == 0 ? 1 : srcName.getIndex();
+ // if the net result of the move is changing the position of a child node
+ // among its same-same siblings, the subscript of the child node entry
+ // to be removed might need adjustment
+ if (renameOnly && srcName.getName().equals(destName.getName()) &&
+ insertTargetEntry && destName.getIndex() <= srcNameIndex) {
+ srcNameIndex++;
+ }
+ srcParentState.removeChildNodeEntry(srcName.getName(), srcNameIndex);
// persist states
try {
@@ -748,14 +865,6 @@
}
/**
- * @see Workspace#restore(Version[])
- */
- public void restore(Version[] versions) throws UnsupportedRepositoryOperationException, VersionException, RepositoryException {
- // @todo implement versioning support
- throw new UnsupportedRepositoryOperationException();
- }
-
- /**
* @see Workspace#getAccessManager
*/
public AccessManager getAccessManager() throws UnsupportedRepositoryOperationException {
@@ -765,11 +874,35 @@
/**
* @see Workspace#getObservationManager
*/
- public synchronized ObservationManager getObservationManager() {
+ public synchronized ObservationManager getObservationManager()
+ throws UnsupportedRepositoryOperationException {
if (obsMgr == null) {
- obsMgr = rep.getObservationManagerFactory(wsDef).createObservationManager(ticket, ticket.getItemManager());
+ try {
+ obsMgr = rep.getObservationManagerFactory(wspName).createObservationManager(ticket, ticket.getItemManager());
+ } catch (NoSuchWorkspaceException nswe) {
+ // should never get here
+ String msg = "internal error: failed to instantiate observation manager";
+ log.error(msg, nswe);
+ throw new UnsupportedRepositoryOperationException(msg, nswe);
+ }
}
return obsMgr;
+ }
+
+ /**
+ * @see Workspace#getQueryManager
+ */
+ public QueryManager getQueryManager() {
+ // @todo implement query support
+ return null;
+ }
+
+ /**
+ * @see Workspace#restore(Version[])
+ */
+ public void restore(Version[] versions) throws UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ // @todo implement versioning support
+ throw new UnsupportedRepositoryOperationException();
}
/**
1.8 +5 -26 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/nodetype/NodeTypeManagerImpl.java
Index: NodeTypeManagerImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/nodetype/NodeTypeManagerImpl.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- NodeTypeManagerImpl.java 20 Jul 2004 08:28:35 -0000 1.7
+++ NodeTypeManagerImpl.java 21 Jul 2004 16:58:04 -0000 1.8
@@ -32,7 +32,6 @@
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.*;
-import javax.jcr.version.OnParentVersionAction;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
@@ -70,7 +69,7 @@
// setup item cache with soft references to node type instances
ntCache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
- rootNodeDef = RootNodeDefinition.create(this, nsResolver);
+ rootNodeDef = new RootNodeDefinition(ntReg.getRootNodeDef(), this, nsResolver);
}
/**
@@ -221,30 +220,10 @@
private static class RootNodeDefinition extends NodeDefImpl {
/**
- * private constructor
- */
- private RootNodeDefinition(ChildNodeDef def, NodeTypeManagerImpl ntMgr, NamespaceResolver nsResolver) {
- super(def, ntMgr, nsResolver);
- }
-
- /**
* Creates a new <code>RootNodeDefinition</code>.
*/
- static RootNodeDefinition create(NodeTypeManagerImpl ntMgr, NamespaceResolver nsResolver) {
- ChildNodeDef def = new ChildNodeDef();
-
- //def.setName(null);
- //def.setDeclaringNodeType(null);
- def.setRequiredPrimaryTypes(new QName[]{NodeTypeRegistry.NT_BASE});
- def.setDefaultPrimaryType(NodeTypeRegistry.NT_UNSTRUCTURED);
- def.setMandatory(true);
- def.setProtected(false);
- def.setOnParentVersion(OnParentVersionAction.VERSION);
- def.setPrimaryItem(false);
- def.setAllowSameNameSibs(false);
- def.setAutoCreate(true);
-
- return new RootNodeDefinition(def, ntMgr, nsResolver);
+ RootNodeDefinition(ChildNodeDef def, NodeTypeManagerImpl ntMgr, NamespaceResolver nsResolver) {
+ super(def, ntMgr, nsResolver);
}
/**
1.10 +57 -12 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/nodetype/NodeTypeRegistry.java
Index: NodeTypeRegistry.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/nodetype/NodeTypeRegistry.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- NodeTypeRegistry.java 20 Jul 2004 08:28:35 -0000 1.9
+++ NodeTypeRegistry.java 21 Jul 2004 16:58:04 -0000 1.10
@@ -72,6 +72,9 @@
// nt:version
public static final QName NT_VERSION =
new QName(NamespaceRegistryImpl.NS_NT_URI, "version");
+ // nt:frozen
+ public static final QName NT_FROZEN =
+ new QName(NamespaceRegistryImpl.NS_NT_URI, "frozen");
private static final String BUILTIN_NODETYPES_RESOURCE_PATH =
"org/apache/slide/jcr/core/nodetype/builtin_nodetypes.xml";
@@ -97,6 +100,9 @@
// map of node type names and node type definitions
private final HashMap registeredNTDefs;
+ // definition of the root node
+ private final ChildNodeDef rootNodeDef;
+
// map of id's and property definitions
private final HashMap propDefs;
// map of id's and node definitions
@@ -153,6 +159,10 @@
propDefs = new HashMap();
nodeDefs = new HashMap();
+ // setup definition of root node
+ rootNodeDef = createRootNodeDef();
+ nodeDefs.put(new NodeDefId(rootNodeDef), rootNodeDef);
+
// load and register pre-defined (i.e. built-in) node types
builtInNTDefs = new NodeTypeDefStore();
InputStream in = null;
@@ -214,6 +224,23 @@
}
}
+ private static ChildNodeDef createRootNodeDef() {
+ ChildNodeDef def = new ChildNodeDef();
+
+ //def.setName(null);
+ // FIXME need a fake declaring node type
+ def.setDeclaringNodeType(new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, ""));
+ def.setRequiredPrimaryTypes(new QName[]{NT_BASE});
+ def.setDefaultPrimaryType(NT_UNSTRUCTURED);
+ def.setMandatory(true);
+ def.setProtected(false);
+ def.setOnParentVersion(OnParentVersionAction.VERSION);
+ def.setPrimaryItem(false);
+ def.setAllowSameNameSibs(false);
+ def.setAutoCreate(true);
+ return def;
+ }
+
/**
* Validates and registers the specified collection of <code>NodeTypeDef</code>
* objects. An <code>InvalidNodeTypeDefException</code> is thrown if the
@@ -330,12 +357,17 @@
* Notify the listeners that a node type <code>ntName</code> has been registered.
*/
private void notifyRegistered(QName ntName) {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ NodeTypeRegistryListener[] la = new NodeTypeRegistryListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- NodeTypeRegistryListener listener = (NodeTypeRegistryListener) iter.next();
- listener.nodeTypeRegistered(ntName);
+ la[cnt++] = (NodeTypeRegistryListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].nodeTypeRegistered(ntName);
+ }
}
}
@@ -343,12 +375,17 @@
* Notify the listeners that a node type <code>ntName</code> has been unregistered.
*/
private void notifyUnregistered(QName ntName) {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ NodeTypeRegistryListener[] la = new NodeTypeRegistryListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- NodeTypeRegistryListener listener = (NodeTypeRegistryListener) iter.next();
- listener.nodeTypeUnregistered(ntName);
+ la[cnt++] = (NodeTypeRegistryListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].nodeTypeUnregistered(ntName);
+ }
}
}
@@ -604,6 +641,14 @@
*/
synchronized QName[] getRegisteredNodeTypes() {
return (QName[]) registeredNTDefs.keySet().toArray(new QName[registeredNTDefs.size()]);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public ChildNodeDef getRootNodeDef() {
+ return rootNodeDef;
}
/**
1.4 +8 -4 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/nodetype/builtin_nodetypes.xml
Index: builtin_nodetypes.xml
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/nodetype/builtin_nodetypes.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- builtin_nodetypes.xml 16 Jul 2004 16:37:23 -0000 1.3
+++ builtin_nodetypes.xml 21 Jul 2004 16:58:04 -0000 1.4
@@ -56,7 +56,7 @@
<propertyDef name="jcr:encoding" type="String" valueConstraint="" defaultValue="" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:mimeType" type="String" valueConstraint="" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:data" type="Binary" valueConstraint="" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="true" multiple="false"/>
- <propertyDef name="jcr:lastModified" type="Date" valueConstraint="" defaultValue="" autoCreate="false" mandatory="true" onParentVersion="IGNORE" protected="false" primaryItem="false" multiple="false"/>
+ <propertyDef name="jcr:lastModified" type="Date" valueConstraint="" defaultValue="" autoCreate="false" mandatory="true" onParentVersion="COMPUTE" protected="false" primaryItem="false" multiple="false"/>
</nodeType>
<nodeType name="nt:folder" mixin="false" orderableChildNodes="false" supertypes="nt:hierarchyNode">
<childNodeDef name="" requiredPrimaryTypes="nt:hierarchyNode" defaultPrimaryType="" autoCreate="false" mandatory="false" onParentVersion="VERSION" protected="false" primaryItem="false" sameNameSibs="false"/>
@@ -96,18 +96,21 @@
<childNodeDef name="jcr:rootVersion" requiredPrimaryTypes="nt:version" defaultPrimaryType="nt:version" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" sameNameSibs="false"/>
<childNodeDef name="" requiredPrimaryTypes="nt:version" defaultPrimaryType="nt:version" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" sameNameSibs="false"/>
</nodeType>
+ <nodeType name="nt:frozenChild" mixin="false" orderableChildNodes="false" supertypes="nt:base">
+ <propertyDef name="jcr:versionHistory" type="Reference" valueConstraint="nt:versionHistory" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="COPY" protected="true" primaryItem="false" multiple="false"/>
+ </nodeType>
<nodeType name="nt:frozen" mixin="false" orderableChildNodes="false" supertypes="nt:base">
<propertyDef name="jcr:frozenPrimaryType" type="String" valueConstraint="" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:frozenMixinTypes" type="String" valueConstraint="" defaultValue="" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
<propertyDef name="jcr:frozenUUID" type="String" valueConstraint="" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
<propertyDef name="" type="undefined" valueConstraint="" defaultValue="" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
- <childNodeDef name="" requiredPrimaryTypes="nt:base" defaultPrimaryType="" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" sameNameSibs="true"/>
+ <childNodeDef name="" requiredPrimaryTypes="nt:base" defaultPrimaryType="nt:frozen" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" sameNameSibs="true"/>
</nodeType>
<nodeType name="nt:version" mixin="false" orderableChildNodes="false" supertypes="nt:frozen,mix:referenceable">
<propertyDef name="jcr:versionLabels" type="String" valueConstraint="" defaultValue="" autoCreate="true" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
<propertyDef name="jcr:created" type="Date" valueConstraint="" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
- <propertyDef name="jcr:predecessors" type="Reference" valueConstraint="nt:version" defaultValue="" autoCreate="true" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
- <propertyDef name="jcr:successors" type="Reference" valueConstraint="nt:version" defaultValue="" autoCreate="true" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
+ <propertyDef name="jcr:predecessors" type="Reference" valueConstraint="nt:version" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
+ <propertyDef name="jcr:successors" type="Reference" valueConstraint="nt:version" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
</nodeType>
<nodeType name="nt:query" mixin="false" orderableChildNodes="false" supertypes="nt:base">
<propertyDef name="jcr:statement" type="String" valueConstraint="" defaultValue="" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
@@ -127,5 +130,6 @@
<propertyDef name="jcr:versionHistory" type="Reference" valueConstraint="nt:versionHistory" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="COPY" protected="true" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:baseVersion" type="Reference" valueConstraint="nt:version" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="IGNORE" protected="true" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:isCheckedOut" type="Boolean" valueConstraint="" defaultValue="true" autoCreate="true" mandatory="true" onParentVersion="IGNORE" protected="true" primaryItem="false" multiple="false"/>
+ <propertyDef name="jcr:predecessors" type="Reference" valueConstraint="nt:version" defaultValue="" autoCreate="true" mandatory="true" onParentVersion="COPY" protected="true" primaryItem="false" multiple="true"/>
</nodeType>
</nodeTypes>
1.6 +42 -21 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/ItemState.java
Index: ItemState.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/ItemState.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ItemState.java 20 Jul 2004 08:28:36 -0000 1.5
+++ ItemState.java 21 Jul 2004 16:58:04 -0000 1.6
@@ -167,12 +167,17 @@
* representing has been discarded.
*/
protected void notifyStateDiscarded() {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ ItemStateListener[] la = new ItemStateListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- ItemStateListener listener = (ItemStateListener) iter.next();
- listener.stateDiscarded(this);
+ la[cnt++] = (ItemStateListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].stateDiscarded(this);
+ }
}
}
@@ -181,11 +186,17 @@
* representing has been created.
*/
protected void notifyStateCreated() {
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ ItemStateListener[] la = new ItemStateListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- ItemStateListener listener = (ItemStateListener) iter.next();
- listener.stateCreated(this);
+ la[cnt++] = (ItemStateListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].stateCreated(this);
+ }
}
}
@@ -194,12 +205,17 @@
* representing has been changed.
*/
protected void notifyStateModified() {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ ItemStateListener[] la = new ItemStateListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- ItemStateListener listener = (ItemStateListener) iter.next();
- listener.stateModified(this);
+ la[cnt++] = (ItemStateListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].stateModified(this);
+ }
}
}
@@ -208,12 +224,17 @@
* representing has been destroyed.
*/
protected void notifyStateDestroyed() {
- // use temp array to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(listeners.values());
- Iterator iter = tmp.iterator();
+ // copy listeners to array to avoid ConcurrentModificationException
+ ItemStateListener[] la = new ItemStateListener[listeners.size()];
+ Iterator iter = listeners.values().iterator();
+ int cnt = 0;
while (iter.hasNext()) {
- ItemStateListener listener = (ItemStateListener) iter.next();
- listener.stateDestroyed(this);
+ la[cnt++] = (ItemStateListener) iter.next();
+ }
+ for (int i = 0; i < la.length; i++) {
+ if (la[i] != null) {
+ la[i].stateDestroyed(this);
+ }
}
}
1.8 +0 -0 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/PersistentItemStateManager.java
Index: PersistentItemStateManager.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/PersistentItemStateManager.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
1.3 +78 -104 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/version/VersionImpl.java
Index: VersionImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/version/VersionImpl.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- VersionImpl.java 20 Jul 2004 08:28:37 -0000 1.2
+++ VersionImpl.java 21 Jul 2004 16:58:04 -0000 1.3
@@ -23,14 +23,13 @@
*/
package org.apache.slide.jcr.core.version;
-import org.apache.slide.jcr.core.*;
import org.apache.slide.jcr.core.state.NodeState;
+import org.apache.slide.jcr.core.*;
+import org.apache.slide.jcr.util.UUID;
-import javax.jcr.RepositoryException;
-import javax.jcr.StringValue;
-import javax.jcr.Value;
-import javax.jcr.nodetype.NodeDef;
import javax.jcr.version.Version;
+import javax.jcr.*;
+import javax.jcr.nodetype.NodeDef;
import java.util.Calendar;
/**
@@ -39,62 +38,34 @@
* @author Tobias Strasser
* @version $Revision$, $Date$
*/
-public class VersionImpl extends NodeImpl implements Version {
+public class VersionImpl extends FrozenNode implements Version {
- /**
- * name of the 'jcr:versionLabels' property
- */
+ /** name of the 'jcr:versionLabels' property */
public static final QName PROPNAME_VERSION_LABELS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "uuid");
- /**
- * name of the 'jcr:predecessors' property
- */
+ /** name of the 'jcr:predecessors' property */
public static final QName PROPNAME_PREDESESSORS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "predecessors");
- /**
- * name of the 'jcr:successors' property
- */
+ /** name of the 'jcr:successors' property */
public static final QName PROPNAME_SUCCESSORS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "successors");
- /**
- * name of the 'jcr:isCheckedOut' property
- */
+ /** name of the 'jcr:isCheckedOut' property */
public static final QName PROPNAME_IS_CHECKED_OUT = new QName(NamespaceRegistryImpl.NS_JCR_URI, "isCheckedOut");
- /**
- * name of the 'jcr:versionHistory' property
- */
+ /** name of the 'jcr:versionHistory' property */
public static final QName PROPNAME_VERSION_HISTORY = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionHistory");
- /**
- * name of the 'jcr:frozenUUID' property
- */
- public static final QName PROPNAME_FROZEN_UUID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozenUUID");
-
- /**
- * name of the 'jcr:frozenPrimaryType' property
- */
- public static final QName PROPNAME_FROZEN_PRIMARY_TYPE = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozenPrimaryType");
-
- /**
- * name of the 'jcr:frozenMixinTypes' property
- */
- public static final QName PROPNAME_FROZEN_MIXIN_TYPES = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozenMixinTypes");
-
- /**
- * name of the 'jcr:baseVersion' property
- */
+ /** name of the 'jcr:baseVersion' property */
public static final QName PROPNAME_BASE_VERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "baseVersion");
/**
* Creates a new Version node. This is only called by the ItemManager when
* creating new node instances.
- *
* @see org.apache.slide.jcr.core.ItemManager#createNodeInstance(org.apache.slide.jcr.core.state.NodeState, javax.jcr.nodetype.NodeDef)
*/
public VersionImpl(ItemManager itemMgr, TicketImpl ticket, NodeId id,
- NodeState state, NodeDef definition,
- ItemLifeCycleListener[] listeners)
+ NodeState state, NodeDef definition,
+ ItemLifeCycleListener[] listeners)
throws RepositoryException {
super(itemMgr, ticket, id, state, definition, listeners);
}
@@ -114,9 +85,9 @@
public String[] getVersionLabels() throws RepositoryException {
if (hasProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver()))) {
Value[] values = getProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver())).getValues();
- if (values != null) {
+ if (values!=null) {
String[] labels = new String[values.length];
- for (int i = 0; i < values.length; i++) {
+ for (int i=0; i<values.length; i++) {
labels[i] = values[i].getString();
}
return labels;
@@ -129,17 +100,7 @@
* @see Version#hasVersionLabel()
*/
public boolean hasVersionLabel(String label) throws RepositoryException {
- if (hasProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver()))) {
- Value[] values = getProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver())).getValues();
- if (values != null) {
- for (int i = 0; i < values.length; i++) {
- if (values[i].getString().equals(label)) {
- return true;
- }
- }
- }
- }
- return false;
+ return getHistory().getVersionByLabel(label) == this;
}
/**
@@ -151,21 +112,21 @@
return;
}
- Value[] oldValues = null;
- Value[] newValues = null;
- if (hasProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver()))) {
- oldValues = getProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver())).getValues();
- }
- if (oldValues != null) {
- newValues = new Value[oldValues.length + 1];
- for (int i = 0; i < oldValues.length; i++) {
- newValues[i] = oldValues[i];
+ Value[] oldValues=null;
+ InternalValue[] newValues=null;
+ if (hasProperty(PROPNAME_VERSION_LABELS)) {
+ oldValues = getProperty(PROPNAME_VERSION_LABELS).getValues();
+ }
+ if (oldValues!=null) {
+ newValues = new InternalValue[oldValues.length+1];
+ for (int i=0; i<oldValues.length; i++) {
+ newValues[i] = InternalValue.create(oldValues[i].getString());
}
- newValues[oldValues.length] = new StringValue(label);
+ newValues[oldValues.length] = InternalValue.create(label);
} else {
- newValues = new Value[]{new StringValue(label)};
+ newValues = new InternalValue[]{InternalValue.create(label)};
}
- setProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver()), newValues);
+ internalSetProperty(PROPNAME_VERSION_LABELS, newValues);
save();
}
@@ -176,23 +137,23 @@
// check history first
getHistory().removeVersionLabel(label);
- Value[] oldValues = getProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver())).getValues();
- Value[] newValues = new Value[oldValues.length - 1];
- int j = 0;
- for (int i = 0; i < oldValues.length; i++) {
+ Value[] oldValues=getProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver())).getValues();
+ InternalValue[] newValues=new InternalValue[oldValues.length-1];
+ int j=0;
+ for (int i=0; i<oldValues.length; i++) {
if (!oldValues[i].getString().equals(label)) {
- if (j < newValues.length) {
- newValues[j] = oldValues[i];
+ if (j<newValues.length) {
+ newValues[j] = InternalValue.create(oldValues[i].getString());
}
j++;
}
}
- if (j == 0) {
- setProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver()), (Value[]) null);
+ if (j==0) {
+ internalSetProperty(PROPNAME_VERSION_LABELS, (InternalValue[]) null);
save();
} else {
- setProperty(PROPNAME_VERSION_LABELS.toJCRName(ticket.getNamespaceResolver()), newValues);
+ internalSetProperty(PROPNAME_VERSION_LABELS, newValues);
save();
}
}
@@ -201,11 +162,11 @@
* @see Version#getSuccessors()
*/
public Version[] getSuccessors() throws RepositoryException {
- if (hasProperty(PROPNAME_SUCCESSORS.toJCRName(ticket.getNamespaceResolver()))) {
- Value[] values = getProperty(PROPNAME_SUCCESSORS.toJCRName(ticket.getNamespaceResolver())).getValues();
- if (values != null) {
+ if (hasProperty(PROPNAME_SUCCESSORS)) {
+ Value[] values = getProperty(PROPNAME_SUCCESSORS).getValues();
+ if (values!=null) {
Version[] preds = new Version[values.length];
- for (int i = 0; i < values.length; i++) {
+ for (int i=0; i<values.length; i++) {
preds[i] = (Version) ticket.getNodeByUUID(values[i].getString());
}
return preds;
@@ -215,14 +176,47 @@
}
/**
+ * Adds a successor to the jcr:successor list
+ * @param succ
+ */
+ void internalAddSuccessor(VersionImpl succ) throws RepositoryException {
+ Version[] successors = getSuccessors();
+ InternalValue[] values = new InternalValue[successors.length+1];
+ values[0] = InternalValue.create(succ.getUUID());
+ for (int i=0; i<successors.length; i++) {
+ values[i+1] = InternalValue.create(new UUID(successors[i].getUUID()));
+ }
+ Property prop = internalSetProperty(PROPNAME_SUCCESSORS, values);
+ prop.save();
+ }
+
+ /**
+ * @see NodeImpl#internalSetProperty(org.apache.slide.jcr.core.QName, org.apache.slide.jcr.core.InternalValue)
+ */
+ public Property internalSetProperty(QName name,
+ InternalValue value)
+ throws ValueFormatException, RepositoryException {
+ return super.internalSetProperty(name, value);
+ }
+
+ /**
+ * @see NodeImpl#internalSetProperty(org.apache.slide.jcr.core.QName, org.apache.slide.jcr.core.InternalValue[])
+ */
+ protected Property internalSetProperty(QName name,
+ InternalValue[] value)
+ throws ValueFormatException, RepositoryException {
+ return super.internalSetProperty(name, value);
+ }
+
+ /**
* @see Version#getPredecessors()
*/
public Version[] getPredecessors() throws RepositoryException {
if (hasProperty(PROPNAME_PREDESESSORS.toJCRName(ticket.getNamespaceResolver()))) {
Value[] values = getProperty(PROPNAME_PREDESESSORS.toJCRName(ticket.getNamespaceResolver())).getValues();
- if (values != null) {
+ if (values!=null) {
Version[] succs = new Version[values.length];
- for (int i = 0; i < values.length; i++) {
+ for (int i=0; i<values.length; i++) {
succs[i] = (Version) ticket.getNodeByUUID(values[i].getString());
}
return succs;
@@ -233,31 +227,11 @@
/**
* Returns the version history of this version and not the extended node.
- *
* @return the version history of this version graph
* @throws RepositoryException
*/
private VersionHistoryImpl getHistory() throws RepositoryException {
return (VersionHistoryImpl) getParent();
- }
-
- /**
- * Initializes the frozen state of a version. i.e. copies the uuid,
- * primary types etc.
- *
- * @param node
- */
- void initFrozenState(NodeImpl node)
- throws RepositoryException {
- internalSetProperty(VersionImpl.PROPNAME_FROZEN_UUID,
- InternalValue.create(node.getProperty(VersionImpl.PROPNAME_UUID).getString()));
- internalSetProperty(VersionImpl.PROPNAME_FROZEN_PRIMARY_TYPE,
- InternalValue.create(node.getProperty(VersionImpl.PROPNAME_PRIMARYTYPE).getString()));
-
- if (node.hasProperty(VersionImpl.PROPNAME_MIXINTYPES)) {
- internalSetProperty(VersionImpl.PROPNAME_FROZEN_MIXIN_TYPES,
- InternalValue.create(node.getProperty(VersionImpl.PROPNAME_MIXINTYPES).getString()));
- }
}
1.3 +129 -19 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/version/VersionManager.java
Index: VersionManager.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/version/VersionManager.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- VersionManager.java 20 Jul 2004 08:28:37 -0000 1.2
+++ VersionManager.java 21 Jul 2004 16:58:04 -0000 1.3
@@ -23,13 +23,16 @@
*/
package org.apache.slide.jcr.core.version;
-import org.apache.slide.jcr.core.*;
import org.apache.slide.jcr.core.nodetype.NodeTypeRegistry;
+import org.apache.slide.jcr.core.*;
+import org.apache.slide.jcr.util.UUID;
+import org.apache.log4j.Logger;
-import javax.jcr.Node;
import javax.jcr.RepositoryException;
-import javax.jcr.version.Version;
+import javax.jcr.Node;
+import javax.jcr.Value;
import javax.jcr.version.VersionHistory;
+import javax.jcr.version.Version;
/**
* This Class implements...
@@ -39,6 +42,8 @@
*/
public class VersionManager {
+ private static Logger log = Logger.getLogger(VersionManager.class);
+
// root path for version storage
public static final QName VERSION_HISTORY_ROOT_NAME =
new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionStorage");
@@ -46,14 +51,11 @@
// the system ticket for the versioning
private final TicketImpl ticket;
- /**
- * the root node of the version histories
- */
+ /** the root node of the version histories */
private final Node historyRoot;
/**
* Creates a new VersionManager.
- *
* @param ticket
* @throws RepositoryException
*/
@@ -64,15 +66,19 @@
Node systemRoot = ((RepositoryImpl) ticket.getRepository()).getSystemRootNode(ticket);
if (!systemRoot.hasNode(VERSION_HISTORY_ROOT_NAME.toJCRName(ticket.getNamespaceResolver()))) {
// if not exist, create
- systemRoot.addNode(VERSION_HISTORY_ROOT_NAME.toJCRName(ticket.getNamespaceResolver()), NodeTypeRegistry.NT_UNSTRUCTURED.toJCRName(ticket.getNamespaceResolver()));
+ systemRoot.addNode(VERSION_HISTORY_ROOT_NAME.toJCRName(
+ ticket.getNamespaceResolver()),
+ NodeTypeRegistry.NT_UNSTRUCTURED.toJCRName(ticket.getNamespaceResolver())
+ );
systemRoot.save();
}
- historyRoot = systemRoot.getNode(VERSION_HISTORY_ROOT_NAME.toJCRName(ticket.getNamespaceResolver()));
+ historyRoot = systemRoot.getNode(
+ VERSION_HISTORY_ROOT_NAME.toJCRName(ticket.getNamespaceResolver())
+ );
}
/**
* Creates a new Version History and returns the UUID of it.
- *
* @param node the node for which the version history is to be initialized
* @return the UUID of the new version history node
* @throws RepositoryException
@@ -88,8 +94,12 @@
}
// create new history node
- VersionHistoryImpl vh = VersionHistoryImpl.create((NodeImpl) historyRoot.addNode(relPath,
- NodeTypeRegistry.NT_VERSION_HISTORY.toJCRName(ticket.getNamespaceResolver())));
+ VersionHistoryImpl vh = VersionHistoryImpl.create(
+ (NodeImpl) historyRoot.addNode(
+ relPath,
+ NodeTypeRegistry.NT_VERSION_HISTORY.toJCRName(ticket.getNamespaceResolver())
+ )
+ );
// and initialize the root version
((VersionImpl) vh.getRootVersion()).initFrozenState(node);
@@ -103,24 +113,124 @@
/**
* Returns the base version of the given node. assuming mix:versionable
- *
* @param node
* @return
* @throws RepositoryException
*/
public Version getBaseVersion(NodeImpl node) throws RepositoryException {
- return (Version) node.getProperty(VersionImpl.PROPNAME_BASE_VERSION).getItem();
+ return (Version) node.getTicket().getNodeByUUID(
+ node.getProperty(
+ VersionImpl.PROPNAME_BASE_VERSION
+ ).getString()
+ );
}
/**
* 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 {
- return VersionHistoryImpl.create((NodeImpl) node.getTicket().getNodeByUUID(node.getProperty(VersionImpl.PROPNAME_VERSION_HISTORY).getString()));
+ public VersionHistoryImpl getVersionHistory(NodeImpl node) throws RepositoryException {
+ return VersionHistoryImpl.create(
+ (NodeImpl) node.getTicket().getNodeByUUID(
+ node.getProperty(
+ VersionImpl.PROPNAME_VERSION_HISTORY
+ ).getString()
+ )
+ );
+ }
+
+ /**
+ * Checks in a node
+ * @see Node#checkin()
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ public Version 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:
+
+ // 0. collect some values
+ // todo: simplyfy, as soon as mandatroy mv cannot return null
+ Value[] values = node.hasProperty(VersionImpl.PROPNAME_PREDESESSORS)
+ ? node.getProperty(VersionImpl.PROPNAME_PREDESESSORS).getValues()
+ : null;
+ VersionImpl[] preds = values==null
+ ? new VersionImpl[]{(VersionImpl) node.getBaseVersion()}
+ : new VersionImpl[values.length];
+ if (values!=null) {
+ for (int i=0; i<values.length; i++) {
+ preds[i] = (VersionImpl) node.getTicket().getNodeByUUID(values[i].getString());
+ }
+ }
+
+ // 0.1 search a predecessor, suitable for generating the new name
+ String versionName=null;
+ 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();
+ int pos = versionName.lastIndexOf('.');
+ 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()+".1";
+ }
+
+ VersionHistoryImpl vh = getVersionHistory(node);
+ try {
+ // 1. A new nt:version node V is created and added as a child node to VH,
+ // the nt:versionHistory pointed to by N�s jcr:versionHistory property.
+ VersionImpl v = (VersionImpl) vh.addNode(
+ versionName,
+ NodeTypeRegistry.NT_VERSION.toJCRName(ticket.getNamespaceResolver())
+ );
+
+ // 3. N�s base version is changed to V by altering N�s jcr:baseVersion
+ // property to point to V.
+ // (will be done in the nodeimpl)
+
+ // 4. N�s checked-in/checked-out status is changed to checked-in by
+ // changing its jcr:isCheckedOut property to false.
+ // (will be done in NodeImpl)
+
+ // 5. The state of N is recorded in V by storing information about
+ // N�s child items (properties or child nodes) to V, as prescribed by
+ // the OnParentVersion attribute of each of N�s child items.
+ // See 7.2.8, below, for the details. The jcr:primaryType,
+ // jcr:mixinTypes and jcr:uuid properties of N are copied over to V
+ // but renamed to jcr:frozenPrimaryType, jcr:frozenMixinTypes and
+ // jcr:frozenUUID to avoid conflict with V's own properties with these names.
+ v.createFrozenState(node);
+
+ // 2. N�s current jcr:predecessors property is copied to V, and N�s
+ // jcr:predecessors property is then set to null. A reference to V
+ // is then added to the jcr:successors property of each of the versions
+ // identified in V�s jcr:predecessors property.
+ InternalValue[] ivPreds = new InternalValue[preds.length];
+ for (int i=0; i<preds.length; i++) {
+ ivPreds[i] = InternalValue.create(new UUID(preds[i].getUUID()));
+ preds[i].internalAddSuccessor(v);
+ }
+ v.internalSetProperty(VersionImpl.PROPNAME_PREDESESSORS, ivPreds);
+
+ // 6. V is given a name, sometimes based upon the name of V�s predecessor.
+ // For example, an increment from �1.5� to �1.6�.
+ // (is done before)
+ vh.save();
+ return v;
+
+ } catch (RepositoryException e) {
+ log.error("Aborting checkin. Error while creating version: " + e.toString());
+ vh.refresh(false);
+ throw e;
+ }
}
}
1.6 +18 -2 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/util/ValueHelper.java
Index: ValueHelper.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/util/ValueHelper.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ValueHelper.java 20 Jul 2004 08:28:38 -0000 1.5
+++ ValueHelper.java 21 Jul 2004 16:58:04 -0000 1.6
@@ -264,4 +264,20 @@
}
return newVal;
}
+
+ /**
+ * @param srcVal
+ * @return
+ * @throws IllegalStateException
+ */
+ public static Value[] copy(Value[] srcVal) throws IllegalStateException {
+ if (srcVal == null) {
+ return null;
+ }
+ Value[] newVal = new Value[srcVal.length];
+ for (int i = 0; i < srcVal.length; i++) {
+ newVal[i] = copy(srcVal[i]);
+ }
+ return newVal;
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org