svn commit: r568271 - in /lenya/trunk/src: java/org/apache/lenya/cms/repository/ modules-core/usecase/ modules-core/usecase/java/src/org/apache/lenya/cms/usecase/ modules/sitetree/java/src/org/apache/lenya/cms/site/tree/ modules/sitetree/java/src/org/a...

[email protected]
Newsgroups gmane.comp.cms.lenya.cvs
Message-ID <[email protected]>
Author: andreas
Date: Tue Aug 21 13:49:18 2007
New Revision: 568271

URL: http://svn.apache.org/viewvc?rev=568271&view=rev
Log:
Introduce Persistable interface. This allows to save complex objects (meta data, site tree) only once before the session is committed. Optimistic usecases lock their nodes before the usecase is executed (see bug 43136).

Added:
    lenya/trunk/src/java/org/apache/lenya/cms/repository/Persistable.java
Modified:
    lenya/trunk/src/java/org/apache/lenya/cms/repository/Node.java
    lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java
    lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java
    lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/Usecase.java
    lenya/trunk/src/modules-core/usecase/usecases.js
    lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/DefaultSiteTree.java
    lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/SiteTreeNodeImpl.java
    lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/TreeSiteManager.java
    lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/DelegatingSiteTree.java
    lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/SiteTreeImpl.java
    lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java
    lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java
    lenya/trunk/src/modules/sitetree/java/test/org/apache/lenya/cms/site/tree/DefaultSiteTreeTest.java
    lenya/trunk/src/modules/sitetree/xslt/navigation/sitetree2nav.xsl
    lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/ModifiableMetaDataHandler.java
    lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java
    lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java

Modified: lenya/trunk/src/java/org/apache/lenya/cms/repository/Node.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/cms/repository/Node.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/repository/Node.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/repository/Node.java Tue Aug 21 13:49:18 2007
@@ -21,7 +21,7 @@
 import java.util.Collection;
 
 /**
- * Repository node.
+ * A repository node is used to persist a {@link Persistable}.
  * 
  * @version $Id$
  */
@@ -167,5 +167,17 @@
      * @throws RepositoryException if an error occurs.
      */
     void delete() throws RepositoryException;
+    
+    /**
+     * @param persistable The object which is persisted using the node.
+     * @throws RepositoryException if the node already has an item.
+     */
+    void setPersistable(Persistable persistable) throws RepositoryException;
+    
+    /**
+     * @return The object which is persisted using this node or <code>null</code>
+     * if no object is registered.
+     */
+    Persistable getPersistable();
 
 }

Added: lenya/trunk/src/java/org/apache/lenya/cms/repository/Persistable.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/cms/repository/Persistable.java?rev=568271&view=auto
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/repository/Persistable.java (added)
+++ lenya/trunk/src/java/org/apache/lenya/cms/repository/Persistable.java Tue Aug 21 13:49:18 2007
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.lenya.cms.repository;
+
+/**
+ * An object which can be persisted to a node.
+ */
+public interface Persistable {
+
+    /**
+     * Save the content of the persistable object to the node. This method is called by the node
+     * before the session is committed.
+     * @throws RepositoryException if the object couldn't be saved.
+     */
+    void save() throws RepositoryException;
+
+}

Modified: lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java (original)
+++ lenya/trunk/src/java/org/apache/lenya/cms/repository/SessionImpl.java Tue Aug 21 13:49:18 2007
@@ -132,8 +132,11 @@
      */
     public void commit() throws RepositoryException, ConcurrentModificationException {
 
+        savePersistables();
+        
         try {
             synchronized (TransactionLock.LOCK) {
+                
                 getUnitOfWork().commit();
                 getSharedItemStore().clear();
             }
@@ -153,6 +156,22 @@
             }
         }
         this.events.clear();
+    }
+
+    /**
+     * Save all persistable objects to their nodes.
+     * @throws RepositoryException if an error occurs.
+     */
+    protected void savePersistables() throws RepositoryException {
+        Object[] objects = getIdentityMap().getObjects();
+        for (int i = 0; i < objects.length; i++) {
+            if (objects[i] instanceof Node) {
+                Node node = (Node) objects[i];
+                if (node.getPersistable() != null) {
+                    node.getPersistable().save();
+                }
+            }
+        }
     }
 
     /**

Modified: lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java (original)
+++ lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/AbstractUsecase.java Tue Aug 21 13:49:18 2007
@@ -69,11 +69,14 @@
 
     protected static final StateMachine.Transition[] TRANSITIONS = {
             new StateMachine.Transition("start", "preChecked", EVENT_CHECK_PRECONDITIONS),
+            new StateMachine.Transition("preChecked", "preChecked", EVENT_CHECK_PRECONDITIONS),
             new StateMachine.Transition("preChecked", "nodesLocked", "lockInvolvedObjects"),
             new StateMachine.Transition("nodesLocked", "execChecked",
                     EVENT_CHECK_EXECUTION_CONDITIONS),
             new StateMachine.Transition("execChecked", "execChecked",
                     EVENT_CHECK_EXECUTION_CONDITIONS),
+            new StateMachine.Transition("execChecked", "preChecked",
+                            EVENT_CHECK_PRECONDITIONS),
             new StateMachine.Transition("execChecked", "executed", EVENT_EXECUTE),
             new StateMachine.Transition("executed", "postChecked", EVENT_CHECK_POSTCONDITIONS) };
 
@@ -688,7 +691,7 @@
      * @return <code>true</code> if the transaction policy is optimistic offline lock,
      *         <code>false</code> if it is pessimistic offline lock.
      */
-    protected boolean isOptimistic() {
+    public boolean isOptimistic() {
         return this.isOptimistic;
     }
 

Modified: lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/Usecase.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/Usecase.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/Usecase.java (original)
+++ lenya/trunk/src/modules-core/usecase/java/src/org/apache/lenya/cms/usecase/Usecase.java Tue Aug 21 13:49:18 2007
@@ -211,4 +211,8 @@
      */
     void setTestSession(Session session);
     
+    /**
+     * @return if the usecase uses optimistic offline lock.
+     */
+    boolean isOptimistic();
 }

Modified: lenya/trunk/src/modules-core/usecase/usecases.js
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules-core/usecase/usecases.js?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules-core/usecase/usecases.js (original)
+++ lenya/trunk/src/modules-core/usecase/usecases.js Tue Aug 21 13:49:18 2007
@@ -243,10 +243,20 @@
  * @see submitFlow
  */
 function defaultSubmitFlow(usecase) {
+    var preconditionsOk = true;
     if (cocoon.request.getParameter("submit")||cocoon.request.getParameter("lenya.submit")=="ok") {
-        usecase.checkExecutionConditions();
-        if (! usecase.hasErrors()) {
-            return executeFlow(usecase);
+        if (usecase.isOptimistic()) {
+            usecase.checkPreconditions();
+            preconditionsOk = !usecase.hasErrors();
+        }
+        if (preconditionsOk) {
+            if (usecase.isOptimistic()) {
+                usecase.lockInvolvedObjects();
+            }
+            usecase.checkExecutionConditions();
+            if (! usecase.hasErrors()) {
+                return executeFlow(usecase);
+            }
         }
     } else if (cocoon.request.getParameter("cancel")) {
         usecase.cancel();
@@ -318,7 +328,7 @@
         passRequestParameters(usecase);
         usecase.checkPreconditions();
         preconditionsOK = !usecase.hasErrors();
-        if (preconditionsOK) {
+        if (preconditionsOK && !usecase.isOptimistic()) {
             usecase.lockInvolvedObjects();
         }
         // create proxy object to save usecase state
@@ -370,11 +380,22 @@
         usecase = getUsecase(usecaseName);
         proxy.setup(usecase);
         passRequestParameters(usecase);
-        usecase.checkExecutionConditions();
-        var hasErrors = usecase.hasErrors();
-        if (!hasErrors) {
-            state = executeFlow(usecase);
-            hasErrors = usecase.hasErrors();
+        
+        if (usecase.isOptimistic()) {
+            usecase.checkPreconditions();
+            preconditionsOK = !usecase.hasErrors();
+        }
+        
+        if (preconditionsOK) {
+            usecase.checkExecutionConditions();
+            if (usecase.isOptimistic()) {
+                usecase.lockInvolvedObjects();
+            }
+            var hasErrors = usecase.hasErrors();
+            if (!hasErrors) {
+                state = executeFlow(usecase);
+                hasErrors = usecase.hasErrors();
+            }
         }
         releaseUsecase(usecase);
         if (hasErrors) {

Modified: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/DefaultSiteTree.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/DefaultSiteTree.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/DefaultSiteTree.java (original)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/DefaultSiteTree.java Tue Aug 21 13:49:18 2007
@@ -32,6 +32,7 @@
 import org.apache.lenya.cms.publication.DocumentFactory;
 import org.apache.lenya.cms.publication.Publication;
 import org.apache.lenya.cms.repository.NodeFactory;
+import org.apache.lenya.cms.repository.RepositoryException;
 import org.apache.lenya.cms.repository.Session;
 import org.apache.lenya.cms.site.Link;
 import org.apache.lenya.cms.site.SiteException;
@@ -74,6 +75,8 @@
 
     private org.apache.lenya.cms.repository.Node repositoryNode;
 
+    private boolean changed;
+
     /**
      * Create a DefaultSiteTree
      * @param factory The document factory.
@@ -499,8 +502,12 @@
         return this.repositoryNode;
     }
 
-    protected void save() throws SiteException {
-        saveDocument();
+    public void save() throws RepositoryException {
+        try {
+            saveDocument();
+        } catch (SiteException e) {
+            throw new RepositoryException(e);
+        }
     }
 
     public String getArea() {
@@ -649,6 +656,10 @@
     public SiteNode[] preOrder() {
         List preOrder = getRootNode().preOrder();
         return (SiteNode[]) preOrder.toArray(new SiteNode[preOrder.size()]);
+    }
+
+    public void changed() {
+        this.changed = true;
     }
 
 }

Modified: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/SiteTreeNodeImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/SiteTreeNodeImpl.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/SiteTreeNodeImpl.java (original)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/SiteTreeNodeImpl.java Tue Aug 21 13:49:18 2007
@@ -191,7 +191,7 @@
         Element labelElem = helper.createElement(SiteTreeNodeImpl.LABEL_NAME, label);
         labelElem.setAttribute(SiteTreeNodeImpl.LANGUAGE_ATTRIBUTE_NAME, language);
         node.insertBefore(labelElem, node.getFirstChild());
-        getTree().save();
+        getTree().changed();
     }
 
     public void removeLabel(String language) {
@@ -215,7 +215,7 @@
                         if (languageAttribute != null
                                 && languageAttribute.getNodeValue().equals(language)) {
                             this.node.removeChild(child);
-                            getTree().save();
+                            getTree().changed();
                             break;
                         }
                     }

Modified: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/TreeSiteManager.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/TreeSiteManager.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/TreeSiteManager.java (original)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree/TreeSiteManager.java Tue Aug 21 13:49:18 2007
@@ -341,7 +341,7 @@
         DefaultSiteTree tree = getTree(document);
         SiteTreeNodeImpl node = (SiteTreeNodeImpl) tree.getNode(path);
         node.setUUID(document.getUUID());
-        tree.save();
+        tree.changed();
     }
 
     /**

Modified: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/DelegatingSiteTree.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/DelegatingSiteTree.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/DelegatingSiteTree.java (original)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/DelegatingSiteTree.java Tue Aug 21 13:49:18 2007
@@ -200,4 +200,8 @@
         return (SiteNode[]) this.preOrder.toArray(new SiteNode[this.preOrder.size()]);
     }
 
+    public void save() throws RepositoryException {
+        throw new UnsupportedOperationException();
+    }
+
 }

Modified: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/SiteTreeImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/SiteTreeImpl.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/SiteTreeImpl.java (original)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/SiteTreeImpl.java Tue Aug 21 13:49:18 2007
@@ -32,6 +32,7 @@
 import org.apache.lenya.cms.publication.Publication;
 import org.apache.lenya.cms.repository.Node;
 import org.apache.lenya.cms.repository.NodeFactory;
+import org.apache.lenya.cms.repository.Persistable;
 import org.apache.lenya.cms.repository.RepositoryException;
 import org.apache.lenya.cms.repository.Session;
 import org.apache.lenya.cms.site.Link;
@@ -47,7 +48,7 @@
 /**
  * Simple site tree implementation.
  */
-public class SiteTreeImpl extends AbstractLogEnabled implements SiteStructure, SiteTree {
+public class SiteTreeImpl extends AbstractLogEnabled implements SiteStructure, SiteTree, Persistable {
 
     private Area area;
     protected ServiceManager manager;
@@ -98,6 +99,8 @@
         Node repoNode = getRepositoryNode();
 
         try {
+            repoNode.setPersistable(this);
+            
             // lastModified check is necessary for clustering, but can cause 404s
             // because of the 1s file system last modification granularity
             if (repoNode.exists() /* && repoNode.getLastModified() > this.lastModified */) {
@@ -166,8 +169,8 @@
         }
     }
 
-    protected void save() {
-        if (loading) {
+    public void save() throws RepositoryException {
+        if (loading || !changed) {
             return;
         }
         try {
@@ -184,7 +187,7 @@
         } catch (RuntimeException e) {
             throw e;
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            throw new RepositoryException(e);
         }
 
     }
@@ -412,6 +415,7 @@
     }
     
     private NodeFactory nodeFactory;
+    private boolean changed = false;
     
     protected NodeFactory getNodeFactory() {
         if (this.nodeFactory == null) {
@@ -494,5 +498,9 @@
             return node.hasLink(language);
         }
         return false;
+    }
+
+    protected void changed() {
+        this.changed = true;
     }
 }

Modified: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java (original)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeNodeImpl.java Tue Aug 21 13:49:18 2007
@@ -164,7 +164,7 @@
     }
 
     protected void changed() {
-        getTree().save();
+        getTree().changed();
     }
 
     public SiteTreeNode[] getPrecedingSiblings() {
@@ -293,7 +293,7 @@
         this.children.add(pos, node);
         this.name2child.put(name, node);
         getTree().nodeAdded(node);
-        getTree().save();
+        getTree().changed();
         return node;
     }
 

Modified: lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java (original)
+++ lenya/trunk/src/modules/sitetree/java/src/org/apache/lenya/cms/site/tree2/TreeSiteManager.java Tue Aug 21 13:49:18 2007
@@ -274,7 +274,7 @@
         SiteTreeImpl tree = (SiteTreeImpl) getTree(document.area());
         TreeNodeImpl node = (TreeNodeImpl) tree.getNode(path);
         node.setUuid(document.getUUID());
-        tree.save();
+        tree.changed();
     }
 
     public void setVisibleInNav(Document document, boolean visibleInNav) throws SiteException {

Modified: lenya/trunk/src/modules/sitetree/java/test/org/apache/lenya/cms/site/tree/DefaultSiteTreeTest.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/java/test/org/apache/lenya/cms/site/tree/DefaultSiteTreeTest.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/java/test/org/apache/lenya/cms/site/tree/DefaultSiteTreeTest.java (original)
+++ lenya/trunk/src/modules/sitetree/java/test/org/apache/lenya/cms/site/tree/DefaultSiteTreeTest.java Tue Aug 21 13:49:18 2007
@@ -207,9 +207,9 @@
 
     /**
      * Test moving a node up
-     * @throws SiteException if an error occurs
+     * @throws RepositoryException 
      */
-    final public void testMoveUp() throws SiteException {
+    final public void testMoveUp() throws RepositoryException {
         this.siteTree.moveUp("/foo/lala");
         this.siteTree.save();
         assertNotNull(this.siteTree.getNode("/foo/lala"));
@@ -217,9 +217,9 @@
 
     /**
      * Test moving a node down
-     * @throws SiteException if an error occurs
+     * @throws RepositoryException 
      */
-    final public void testMoveDown() throws SiteException {
+    final public void testMoveDown() throws RepositoryException {
         this.siteTree.moveDown("/foo");
         this.siteTree.save();
         assertNotNull(this.siteTree.getNode("/foo"));

Modified: lenya/trunk/src/modules/sitetree/xslt/navigation/sitetree2nav.xsl
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sitetree/xslt/navigation/sitetree2nav.xsl?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sitetree/xslt/navigation/sitetree2nav.xsl (original)
+++ lenya/trunk/src/modules/sitetree/xslt/navigation/sitetree2nav.xsl Tue Aug 21 13:49:18 2007
@@ -30,8 +30,11 @@
   <xsl:param name="defaultlanguage"/>
   <xsl:param name="currentPath"/>
   
-  <!-- force a specific extension for node URLs -->
-  <xsl:param name="extension"/>
+  <!--
+    Force a specific extension for node URLs. This bypasses resolving the actual extension.
+    We're setting this to 'html' by default because resolving the actual extension is quite expensive.
+  -->
+  <xsl:param name="extension" select="html"/>
 
 
   <xsl:template match="tree:fragment">

Modified: lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/ModifiableMetaDataHandler.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/ModifiableMetaDataHandler.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/ModifiableMetaDataHandler.java (original)
+++ lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/ModifiableMetaDataHandler.java Tue Aug 21 13:49:18 2007
@@ -32,21 +32,30 @@
 /**
  * Modifiable meta data handler.
  */
-public class ModifiableMetaDataHandler extends SourceNodeMetaDataHandler {
+public class ModifiableMetaDataHandler extends SourceNodeMetaDataHandler implements Persistable {
     
     private MetaSourceWrapper sourceWrapper;
+    private boolean changed = false;
     
     /**
      * @param manager The service manager.
-     * @param sourceWrapper The soure wrapper.
+     * @param sourceWrapper The source wrapper.
      */
     public ModifiableMetaDataHandler(ServiceManager manager, MetaSourceWrapper sourceWrapper) {
         super(manager, sourceWrapper.getRealSourceUri());
         this.sourceWrapper = sourceWrapper;
+        try {
+            this.sourceWrapper.getNode().setPersistable(this);
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
     }
     
 
-    protected void saveMetaData() throws MetaDataException {
+    public void save() throws RepositoryException {
+        if (!changed) {
+            return;
+        }
         try {
             NamespaceHelper helper = new NamespaceHelper(META_DATA_NAMESPACE, "", ELEMENT_METADATA);
             Collection namespaces = this.namespace2metamap.keySet();
@@ -89,20 +98,20 @@
                 }
             }
         } catch (Exception e) {
-            throw new MetaDataException(e);
+            throw new RepositoryException(e);
         }
     }
 
     protected void addValue(String namespaceUri, String key, String value) throws MetaDataException {
         List values = getValueList(namespaceUri, key);
         values.add(value);
-        saveMetaData();
+        changed();
     }
 
     protected void removeAllValues(String namespaceUri, String key) throws MetaDataException {
         List values = getValueList(namespaceUri, key);
         values.clear();
-        saveMetaData();
+        changed();
     }
 
 
@@ -110,7 +119,12 @@
         List values = getValueList(namespaceUri, key);
         values.clear();
         values.add(value);
-        saveMetaData();
+        changed();
+    }
+
+
+    private void changed() {
+        this.changed = true;
     }
 
 }

Modified: lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java (original)
+++ lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNode.java Tue Aug 21 13:49:18 2007
@@ -369,6 +369,7 @@
     }
 
     private RCML rcml;
+    private Persistable persistable;
 
     protected synchronized RCML getRcml() {
         if (this.rcml == null) {
@@ -473,6 +474,14 @@
 
     public boolean isCheckedOutBySession() throws TransactionException {
         return isCheckedOutBySession(getSession());
+    }
+
+    public void setPersistable(Persistable item) throws RepositoryException {
+        this.persistable = item;
+    }
+
+    public Persistable getPersistable() {
+        return this.persistable;
     }
     
 }

Modified: lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java?rev=568271&r1=568270&r2=568271&view=diff
==============================================================================
--- lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java (original)
+++ lenya/trunk/src/modules/sourcerepository/java/src/org/apache/lenya/cms/repository/SourceNodeRCML.java Tue Aug 21 13:49:18 2007
@@ -191,7 +191,6 @@
 
         entries.add(0, entry);
         setDirty();
-        write();
     }
 
     protected Element saveToXml(NamespaceHelper helper, RCMLEntry entry)
@@ -613,6 +612,7 @@
     public synchronized void checkOut(Node node, boolean restrictedToSession)
             throws RevisionControlException {
         checkOutIn(node, RCML.co, new Date().getTime(), false, false, restrictedToSession);
+        write();
     }
 
     public boolean isCheckedOutBySession(Session session) throws RevisionControlException {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.