You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2008/03/03 11:06:56 UTC

svn commit: r633023 - in /incubator/sling/trunk: launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/ sling/ujax/src/main/java/org/apache/sling/ujax/

Author: bdelacretaz
Date: Mon Mar  3 02:06:56 2008
New Revision: 633023

URL: http://svn.apache.org/viewvc?rev=633023&view=rev
Log:
SLING-280 - UjaxPostServlet supports first/last/before/after ordering of created nodes

Modified:
    incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletOrderTest.java
    incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java
    incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java

Modified: incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletOrderTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletOrderTest.java?rev=633023&r1=633022&r2=633023&view=diff
==============================================================================
--- incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletOrderTest.java (original)
+++ incubator/sling/trunk/launchpad/launchpad-webapp/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/ujax/PostServletOrderTest.java Mon Mar  3 02:06:56 2008
@@ -20,75 +20,190 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.servlet.http.HttpServletResponse;
-
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
 import org.apache.sling.launchpad.webapp.integrationtest.HttpTestBase;
-import org.apache.sling.ujax.UjaxPostServlet;
 
 /** Test the order option for node creation via the MicrojaxPostServlet */
 public class PostServletOrderTest extends HttpTestBase {
-    public static final String TEST_BASE_PATH = "/ujax-tests";
-    private String postUrl;
-    
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+
+    public static final String TEST_BASE_PATH = "/ujax-tests-order";
+
+    private static final String[] DEFAULT_ORDER = new String[]{"a","b","c","d"};
+
+    /*
+        does not work (yet) since rhino does not preserve order of
+        object elements.
+
+    private static final String TEST_SCRIPT =
+            "var s=''; " +
+            "for (var a in data) {" +
+            "   var n = data[a];" +
+            "   if (typeof(n) == 'object') s += a + ',';" +
+            "}" +
+            "out.println(s);";
+     */
+
+    /**
+     * Create nodes and check if they are in default order
+     */
+    public void testStandardOrder() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
+        verifyOrder(postUrl, DEFAULT_ORDER);
     }
     
-   public void testPostPathIsUnique() throws IOException {
-        assertHttpStatus(postUrl, HttpServletResponse.SC_NOT_FOUND,
-                "Path must not exist before test: " + postUrl);
+    /**
+     * Create nodes and check if they are in correct order after a
+     * ujax:order="first" request
+     */
+    public void testOrderFirst() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
+
+        final Map <String, String> props = new HashMap <String, String> ();
+        props.put("ujax:order","first");
+        testClient.createNode(postUrl + "/c", props);
+        verifyOrder(postUrl, new String[]{"c", "a", "b", "d"});
     }
 
-    /** Create several nodes without the order option, and check ordering */
-    public void testStandardOrder() throws IOException {
-        final String [] nodeUrl = new String[4];
-        nodeUrl[0] = testClient.createNode(postUrl + UjaxPostServlet.DEFAULT_CREATE_SUFFIX, null);
-        nodeUrl[1] = testClient.createNode(postUrl + UjaxPostServlet.DEFAULT_CREATE_SUFFIX, null);
-        nodeUrl[2] = testClient.createNode(postUrl + UjaxPostServlet.DEFAULT_CREATE_SUFFIX, null);
-        nodeUrl[3] = testClient.createNode(postUrl + UjaxPostServlet.DEFAULT_CREATE_SUFFIX, null);
-        
-        final String [] nodeName = new String[nodeUrl.length];
-        for(int i = 0;  i < nodeUrl.length; i++) {
-            nodeName[i] = nodeUrl[i].substring(nodeUrl[i].lastIndexOf('/') + 1);
-        }
+    /**
+     * Create nodes and check if they are in correct order after a
+     * ujax:order="last" request
+     */
+    public void testOrderLast() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
 
-        // check that nodes appear in creation order in their parent's list of children
-        final String json = getContent(postUrl + ".1.json", CONTENT_TYPE_JSON);
-        for(int i = 0;  i < nodeUrl.length - 1; i++) {
-            final int posA = json.indexOf(nodeName[i]);
-            final int posB = json.indexOf(nodeName[i + 1]);
-            if(posB <= posA) {
-                fail("Expected '" + nodeName[i] + "' to come before '" + nodeName[i + 1] + "' in JSON data '" + json + "'");
-            }
-        }
+        final Map <String, String> props = new HashMap <String, String> ();
+        props.put("ujax:order","last");
+        testClient.createNode(postUrl + "/c", props);
+        verifyOrder(postUrl, new String[]{"a", "b", "d", "c"});
+    }
+
+    /**
+     * Create nodes and check if they are in correct order after a
+     * ujax:order="before" request
+     */
+    public void testOrderBefore() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
+
+        final Map <String, String> props = new HashMap <String, String> ();
+        props.put("ujax:order","before b");
+        testClient.createNode(postUrl + "/c", props);
+        verifyOrder(postUrl, new String[]{"a", "c", "b", "d"});
+    }
+
+    /**
+     * Create nodes and check if they are in correct order after a
+     * ujax:order="after" request
+     */
+    public void testOrderAfter() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
+
+        final Map <String, String> props = new HashMap <String, String> ();
+        props.put("ujax:order","after c");
+        testClient.createNode(postUrl + "/b", props);
+        verifyOrder(postUrl, new String[]{"a", "c", "b", "d"});
+    }
+
+    /**
+     * Create nodes and check if they are in correct order after a
+     * ujax:order="N" request, where new position is greater than old one.
+     */
+    public void testOrderIntToBack() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
+
+        final Map <String, String> props = new HashMap <String, String> ();
+        props.put("ujax:order","2");
+        testClient.createNode(postUrl + "/a", props);
+        verifyOrder(postUrl, new String[]{"b", "c", "a", "d"});
     }
     
-    /** Create several nodes with the order option, and check ordering */
-    public void testZeroOrder() throws IOException {
+    /**
+     * Create nodes and check if they are in correct order after a
+     * ujax:order="N" request, where new position is less than old one.
+     */
+    public void testOrderIntToFront() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
+
+        final Map <String, String> props = new HashMap <String, String> ();
+        props.put("ujax:order","1");
+        testClient.createNode(postUrl + "/d", props);
+        verifyOrder(postUrl, new String[]{"a", "d", "b", "c"});
+    }
+
+    /**
+     * Create nodes and check if they are in correct order after a
+     * ujax:order="0" request
+     */
+    public void testOrderIntZero() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
+
         final Map <String, String> props = new HashMap <String, String> ();
         props.put("ujax:order","0");
-        
-        final String [] nodeUrl = new String[4];
-        nodeUrl[0] = testClient.createNode(postUrl + UjaxPostServlet.DEFAULT_CREATE_SUFFIX, props);
-        nodeUrl[1] = testClient.createNode(postUrl + UjaxPostServlet.DEFAULT_CREATE_SUFFIX, props);
-        nodeUrl[2] = testClient.createNode(postUrl + UjaxPostServlet.DEFAULT_CREATE_SUFFIX, props);
-        nodeUrl[3] = testClient.createNode(postUrl + UjaxPostServlet.DEFAULT_CREATE_SUFFIX, props);
-        
-        final String [] nodeName = new String[nodeUrl.length];
-        for(int i = 0;  i < nodeUrl.length; i++) {
-            nodeName[i] = nodeUrl[i].substring(nodeUrl[i].lastIndexOf('/') + 1);
+        testClient.createNode(postUrl + "/d", props);
+        verifyOrder(postUrl, new String[]{"d", "a", "b", "c"});
+    }
+
+    /**
+     * Create nodes and check if they are in correct order after a
+     * ujax:order="N" request, where new position is out of bounds
+     */
+    public void testOrderIntOOB() throws IOException {
+        final String postUrl = HTTP_BASE_URL + TEST_BASE_PATH + "/" + System.currentTimeMillis();
+        createNodes(postUrl, DEFAULT_ORDER);
+
+        final Map <String, String> props = new HashMap <String, String> ();
+        props.put("ujax:order","100");
+        testClient.createNode(postUrl + "/a", props);
+        verifyOrder(postUrl, new String[]{"b", "c", "d", "a"});
+    }
+
+    /**
+     * Create test nodes
+     */
+    private String[] createNodes(String parentUrl, String[] names)
+            throws IOException {
+        String[] urls = new String[names.length];
+        for (int i=0; i<names.length; i++) {
+            urls[i] = testClient.createNode(parentUrl + "/" + names[i], null);
         }
+        return urls;
+    }
 
-        // check that nodes appear in reverse creation order in their parent's list of children
-        final String json = getContent(postUrl + ".1.json", CONTENT_TYPE_JSON);
-        for(int i = 0;  i < nodeUrl.length - 1; i++) {
-            final int posA = json.indexOf(nodeName[i]);
-            final int posB = json.indexOf(nodeName[i + 1]);
-            if(posA <= posB) {
-                fail("Expected '" + nodeName[i] + " to come after " + nodeName[i + 1] + " in JSON data '" + json + "'");
+    /**
+     * Verify node order
+     */
+    private void verifyOrder(String parentUrl, String[] names)
+            throws IOException {
+        // check that nodes appear in creation order in their parent's list of children
+        final String content = getContent(parentUrl + ".1.json", CONTENT_TYPE_JSON);
+        String expected = "";
+        for (String n: names) {
+            expected +=n + ",";
+        }
+        //assertJavascript(expected, content, TEST_SCRIPT);
+        try {
+            String actual = "";
+            JSONObject obj = new JSONObject(content);
+            JSONArray n = obj.names();
+            for (int i=0; i<n.length(); i++) {
+                String name = n.getString(i);
+                Object o = obj.get(name);
+                if (o instanceof JSONObject) {
+                    actual += name + ",";
+                }
             }
+            assertEquals(expected, actual);
+        } catch (JSONException e) {
+            throw new IOException(e.toString());
         }
     }
  }

Modified: incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java?rev=633023&r1=633022&r2=633023&view=diff
==============================================================================
--- incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java (original)
+++ incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostProcessor.java Mon Mar  3 02:06:56 2008
@@ -16,11 +16,12 @@
  */
 package org.apache.sling.ujax;
 
-import java.util.Map;
 import java.util.LinkedHashMap;
+import java.util.Map;
 
 import javax.jcr.NamespaceException;
 import javax.jcr.Node;
+import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.servlet.ServletContext;
@@ -44,6 +45,11 @@
      */
     private static final Logger log = LoggerFactory.getLogger(UjaxPostProcessor.class);
 
+    public static final String ORDER_FIRST = "first";
+    public static final String ORDER_BEFORE = "before ";
+    public static final String ORDER_AFTER = "after ";
+    public static final String ORDER_LAST = "last";    
+    
     /**
      * log that records the changes applied during the processing of the
      * post request.
@@ -670,32 +676,91 @@
         }
         return savePrefix;
     }
+    
+    private void processOrder() throws RepositoryException {
+        final String orderCode = request.getParameter(UjaxPostServlet.RP_ORDER);
+        if  (orderCode!=null) {
+            final Node n = deepGetOrCreateNode(currentPath);
+            orderNode(n, orderCode);
+        }
+    }
 
     /**
-     * If orderCode is ORDER_ZERO, move n so that it is the first child of its
-     * parent
-     * @throws RepositoryException if a repository error occurs
+     * Orders the given node according to the specified command.
+     *
+     * The following syntax is supported:
+     * <xmp>
+     * | first    | before all child nodes
+     * | before A | before child node A
+     * | after A  | after child node A
+     * | last     | after all nodes
+     * | N        | at a specific position, N being an integer
+     * </xmp>
+     *
+     * @param node node to order
+     * @param command spcifies the ordering type
+     * @throws RepositoryException if an error occurs
      */
-    private void processOrder()
+    private void orderNode(Node node, String command)
             throws RepositoryException {
-        // process the "order" command if any
-        final String orderCode = request.getParameter(UjaxPostServlet.RP_ORDER);
-        if  (orderCode!=null) {
-            if (UjaxPostServlet.ORDER_ZERO.equals(orderCode)) {
-                final Node n = deepGetOrCreateNode(currentPath);
-                final Node parent = n.getParent();
-                final String beforename=parent.getNodes().nextNode().getName();
-                parent.orderBefore(n.getName(), beforename);
-                if(log.isDebugEnabled()) {
-                    log.debug("Node {} moved to be first child of its parent, " +
-                            "due to orderCode=" + orderCode, n.getPath());
+        Node parent = node.getParent();
+        String next = null;
+        if (command.equals(ORDER_FIRST)) {
+            next =  parent.getNodes().nextNode().getName();
+        } else if (command.equals(ORDER_LAST)) {
+            next = "";
+        } else if (command.startsWith(ORDER_BEFORE)) {
+            next = command.substring(ORDER_BEFORE.length());
+        } else if (command.startsWith(ORDER_AFTER)) {
+            String name = command.substring(ORDER_AFTER.length());
+            NodeIterator iter = parent.getNodes();
+            while (iter.hasNext()) {
+                Node n = iter.nextNode();
+                if (n.getName().equals(name)) {
+                    if (iter.hasNext()) {
+                        next = iter.nextNode().getName();
+                    } else {
+                        next = "";
+                    }
                 }
-            } else {
-                if(log.isDebugEnabled()) {
-                    log.debug("orderCode '{}' invalid, ignored", orderCode);
+            }
+        } else {
+            // check for integer
+            try {
+                // 01234
+                // abcde  move a -> 2 (above 3)
+                // bcade  move a -> 1 (above 1)
+                // bacde
+                int newPos = Integer.parseInt(command);
+                next = "";
+                NodeIterator iter = parent.getNodes();
+                while (iter.hasNext() && newPos >= 0) {
+                    Node n = iter.nextNode();
+                    if (n.getName().equals(node.getName())) {
+                        // if old node is found before index, need to
+                        // inc index
+                        newPos++;
+                    }
+                    if (newPos == 0) {
+                        next = n.getName();
+                        break;
+                    }
+                    newPos--;
                 }
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("provided node ordering command is invalid: " + command);
+            }
+        }
+        if (next != null) {
+            if (next.equals("")) {
+                next = null;
             }
+            parent.orderBefore(node.getName(), next);
+            if(log.isDebugEnabled()) {
+                log.debug("Node {} moved '{}'", node.getPath(), command);
+            }
+        } else {
+            throw new IllegalArgumentException("provided node ordering command is invalid: " + command);
         }
     }
-
 }

Modified: incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java?rev=633023&r1=633022&r2=633023&view=diff
==============================================================================
--- incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java (original)
+++ incubator/sling/trunk/sling/ujax/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java Mon Mar  3 02:06:56 2008
@@ -119,11 +119,6 @@
     public static final String RP_ORDER = RP_PREFIX + "order";
 
     /**
-     * Code value for RP_ORDER
-     */
-    public static final String ORDER_ZERO = "0";
-
-    /**
      * Optional request parameter: redirect to the specified URL after POST
      */
     public static final String RP_REDIRECT_TO =  RP_PREFIX + "redirect";