You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by an...@apache.org on 2007/09/23 12:35:12 UTC

svn commit: r578564 - in /lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase: part1.xml part2.xml

Author: andreas
Date: Sun Sep 23 03:35:07 2007
New Revision: 578564

URL: http://svn.apache.org/viewvc?rev=578564&view=rev
Log:
Continuing usecase tutorial

Added:
    lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part2.xml
Modified:
    lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part1.xml

Modified: lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part1.xml
URL: http://svn.apache.org/viewvc/lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part1.xml?rev=578564&r1=578563&r2=578564&view=diff
==============================================================================
--- lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part1.xml (original)
+++ lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part1.xml Sun Sep 23 03:35:07 2007
@@ -198,170 +198,10 @@
     ...
 
 }]]></source>
-    </section>
       
-    <section>
-      <title>Declaring the Usecase</title>
       <p>
-        Now we're ready to start working on the actual usecase. First, we tell Lenya about
-        the usecase. The usecase declaration is a patch file for <code>cocoon.xconf</code>.
-        It is located at <code>$MODULE_HOME/config/cocoon-xconf/usecase-addKnownPerson.xconf</code>.
-        It adds the <em>person.addKnownUsecase</em> usecase component instance if it doesn't
-        exist yet (determined by the <code>unless</code> attribute):
+        Now we can go on with the <a href="site:usecaseTutorialPart2">actual usecase</a>.
       </p>
-      <source xml:space="preserve"><![CDATA[<xconf xpath="/cocoon/usecases"
-  unless="/cocoon/usecases/component-instance[@name = 'person.addKnownPerson']">
-  
-  <component-instance name="person.addKnownPerson" logger="lenya.modules.person"
-      class="org.apache.lenya.modules.person.usecases.AddKnownPerson">
-    <view template="modules/person/usecases/addKnownPerson.jx"/>
-  </component-instance>
-  
-</xconf>
-]]></source>
-      <p>
-        This usecase declaration specifies the usecase handler class (in our case
-        <code>AddKnownPerson</code>) and the JX template which acts as the view for
-        the usecase (<code>addKnownPerson.jx</code>). For a complete list of the generic
-        usecase configuration options, refer to the <a href="site:abstractusecase">AbstractUsecase</a>
-        documentation.
-      </p>
-    </section>
-    
-    <section>
-      <title>Implementing the Usecase Handler Class</title>
-      <p>
-        The usecase handler object receives user input and manipulates the business objects,
-        in our case the <code>Person</code> objects, accordingly. It has the following
-        responsibilities:
-      </p>
-      <ul>
-        <li>Prepare data to be displayed on the view,</li>
-        <li>Validate user input and generate appropriate error messages, and</li>
-        <li>Manipulate the business objects.</li>
-      </ul>
-      <p>
-        If you want to follow a strictly object-oriented approach, the usecase handler class
-        itself shouldn't contain any knowledge about the business logic. It belongs to the
-        controller part of the <acronym title="Model-View-Controller">MVC</acronym> pattern
-        (the other parts of the controller are the usecase sitemap and the flowscript).
-      </p>
-      <p>
-        The following code snippet shows the usecase handler class.
-        At this point, we implement only the two most important methods:
-      </p>
-      <ul>
-        <li>
-          <code>initParameters()</code> initializes the usecase parameters which are
-          used to communicate between the usecase handler and the view. In our case, it
-          compiles a list of <code>Person</code> objects, one for each document with the resource type
-          <em>person</em>.
-        </li>
-        <li>
-          <code>doExecute()</code> gets the <em>uuid</em> parameter from the view and adds
-          the corresponding <code>Person</code> object to the list of known people.
-        </li>
-      </ul>
-      <source xml:space="preserve"><![CDATA[public class AddKnownPerson extends DocumentUsecase {
-
-    protected void initParameters() {
-        super.initParameters();
-
-        Document doc = getSourceDocument();
-        Document[] allDocs = doc.area().getDocuments();
-
-        try {
-            Set peopleDocs = new HashSet();
-            for (int i = 0; i < allDocs.length; i++) {
-                if (allDocs[i].getResourceType().getName().equals("person")) {
-                    Person person = new Person(allDocs[i]);
-                    peopleDocs.add(person);
-                }
-            }
-            setParameter("people", peopleDocs);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    protected void doExecute() throws Exception {
-        super.doExecute();
-
-        String uuid = getParameterAsString("uuid");
-        Document doc = getSourceDocument();
-        Person person = new Person(doc);
-
-        Document knownDoc = doc.area().getDocument(uuid, doc.getLanguage());
-        Person knownPerson = new Person(knownDoc);
-
-        person.addKnownPerson(knownPerson);
-    }
-
-}]]></source>
-    </section>
-    
-    <section>
-      <title>Implementing the View</title>
-      <p>
-        We're using a JX template to implement the view. It allows us to generate XHTML
-        code using properties of Java objects which are passed as parameters from the usecase
-        handler object.
-      </p>
-      <p>
-        The page contains a form, passing the <em>lenya.usecase</em> and <em>lenya.continuation</em>
-        parameters as hidden input fields. We choose POST as the form method because we want
-        to manipulate data on the server, avoiding that the user submits the form multiple times.
-        We generate a drop-down list containing an option for each person,
-        using the UUID as the <code>value</code> attribute of the <code>option</code> element.
-        Remember that the <em>people</em> parameter was set in the <code>initParameters()</code>
-        method of the usecase handler class.
-      </p>
-      <source xml:space="preserve"><![CDATA[<page:page xmlns:jx="http://apache.org/cocoon/templates/jx/1.0" 
-           xmlns:page="http://apache.org/cocoon/lenya/cms-page/1.0" 
-           xmlns="http://www.w3.org/1999/xhtml" 
-           xmlns:i18n="http://apache.org/cocoon/i18n/2.1" >
-
-  <page:title>
-    <i18n:text>Add Known Person</i18n:text>
-  </page:title>
-  <page:body>
-    
-    <jx:import uri="fallback://lenya/modules/usecase/templates/messages.jx"/>
-    
-    <form method="POST">
-      <input type="hidden" name="lenya.usecase" value="${usecase.getName()}"/>
-      <input type="hidden" name="lenya.continuation" value="${continuation.id}"/>
-      
-      <p>
-        <i18n:text>Select a person you know:</i18n:text>
-      </p>
-      <p>
-        <select name="uuid">
-          <jx:forEach var="person" items="${usecase.getParameter('people')}">
-            <option value="${person.getDocument().getUUID()}">
-              <jx:out value="${person.getName()}"/>
-            </option>
-          </jx:forEach>
-        </select>
-      </p>
-  
-      <p>
-        <input i18n:attr="value" name="submit" type="submit" value="Submit"/>
-        <i18n:text> </i18n:text>
-        <input i18n:attr="value" name="cancel" type="submit" value="Cancel"/>
-      </p>
-      
-    </form>
-  </page:body>
-</page:page>]]></source>
-    </section>
-    
-    <section>
-      <title>Adding the Menu Item</title>
-    </section>
-    
-    <section>
-      <title>What's Next?</title>
     </section>
     
   </body>

Added: lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part2.xml
URL: http://svn.apache.org/viewvc/lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part2.xml?rev=578564&view=auto
==============================================================================
--- lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part2.xml (added)
+++ lenya/docu/src/documentation/content/xdocs/docs/2_0_x/tutorials/usecase/part2.xml Sun Sep 23 03:35:07 2007
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright 1999-2006 The Apache Software Foundation
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id: metadata.xml 55543 2004-10-26 00:14:59Z gregor $ -->
+<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" 
+  "http://forrest.apache.org/dtd/document-v20.dtd">
+<document>
+  <header>
+    <title>Implementing a Usecase, Part 2: The Usecase</title>
+  </header>
+  <body>
+      
+    <section>
+      <title>Declaring the Usecase</title>
+      <p>
+        Now we're ready to start working on the actual usecase. First, we tell Lenya about
+        the usecase. The usecase declaration is a patch file for <code>cocoon.xconf</code>.
+        It is located at <code>$MODULE_HOME/config/cocoon-xconf/usecase-addKnownPerson.xconf</code>.
+        It adds the <em>person.addKnownUsecase</em> usecase component instance if it doesn't
+        exist yet (determined by the <code>unless</code> attribute):
+      </p>
+      <source xml:space="preserve"><![CDATA[<xconf xpath="/cocoon/usecases"
+  unless="/cocoon/usecases/component-instance[@name = 'person.addKnownPerson']">
+  
+  <component-instance name="person.addKnownPerson" logger="lenya.modules.person"
+      class="org.apache.lenya.modules.person.usecases.AddKnownPerson">
+    <view template="modules/person/usecases/addKnownPerson.jx"/>
+  </component-instance>
+  
+</xconf>
+]]></source>
+      <p>
+        This usecase declaration specifies the usecase handler class (in our case
+        <code>AddKnownPerson</code>) and the JX template which acts as the view for
+        the usecase (<code>addKnownPerson.jx</code>). For a complete list of the generic
+        usecase configuration options, refer to the <a href="site:abstractusecase">AbstractUsecase</a>
+        documentation.
+      </p>
+    </section>
+    
+    <section>
+      <title>Implementing the Usecase Handler Class</title>
+      <p>
+        The usecase handler object receives user input and manipulates the business objects,
+        in our case the <code>Person</code> objects, accordingly. It has the following
+        responsibilities:
+      </p>
+      <ul>
+        <li>Prepare data to be displayed on the view,</li>
+        <li>Validate user input and generate appropriate error messages, and</li>
+        <li>Manipulate the business objects.</li>
+      </ul>
+      <p>
+        If you want to follow a strictly object-oriented approach, the usecase handler class
+        itself shouldn't contain any knowledge about the business logic. It belongs to the
+        controller part of the <acronym title="Model-View-Controller">MVC</acronym> pattern
+        (the other parts of the controller are the usecase sitemap and the flowscript).
+      </p>
+      <p>
+        The following code snippet shows the usecase handler class.
+        At this point, we implement only the two most important methods:
+      </p>
+      <ul>
+        <li>
+          <code>initParameters()</code> initializes the usecase parameters which are
+          used to communicate between the usecase handler and the view. In our case, it
+          compiles a list of <code>Person</code> objects, one for each document with the resource type
+          <em>person</em>.
+        </li>
+        <li>
+          <code>doExecute()</code> gets the <em>uuid</em> parameter from the view and adds
+          the corresponding <code>Person</code> object to the list of known people.
+        </li>
+      </ul>
+      <source xml:space="preserve"><![CDATA[public class AddKnownPerson extends DocumentUsecase {
+
+    protected void initParameters() {
+        super.initParameters();
+
+        Document doc = getSourceDocument();
+        Document[] allDocs = doc.area().getDocuments();
+
+        try {
+            Set peopleDocs = new HashSet();
+            for (int i = 0; i < allDocs.length; i++) {
+                if (allDocs[i].getResourceType().getName().equals("person")) {
+                    Person person = new Person(allDocs[i]);
+                    peopleDocs.add(person);
+                }
+            }
+            setParameter("people", peopleDocs);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected void doExecute() throws Exception {
+        super.doExecute();
+
+        String uuid = getParameterAsString("uuid");
+        Document doc = getSourceDocument();
+        Person person = new Person(doc);
+
+        Document knownDoc = doc.area().getDocument(uuid, doc.getLanguage());
+        Person knownPerson = new Person(knownDoc);
+
+        person.addKnownPerson(knownPerson);
+    }
+
+}]]></source>
+    </section>
+    
+    <section>
+      <title>Implementing the View</title>
+      <p>
+        We're using a JX template to implement the view. It allows us to generate XHTML
+        code using properties of Java objects which are passed as parameters from the usecase
+        handler object.
+      </p>
+      <p>
+        The page contains a form, passing the <em>lenya.usecase</em> and <em>lenya.continuation</em>
+        parameters as hidden input fields. We choose POST as the form method because we want
+        to manipulate data on the server, avoiding that the user submits the form multiple times.
+        We generate a drop-down list containing an option for each person,
+        using the UUID as the <code>value</code> attribute of the <code>option</code> element.
+        Remember that the <em>people</em> parameter was set in the <code>initParameters()</code>
+        method of the usecase handler class.
+      </p>
+      <source xml:space="preserve"><![CDATA[<page:page xmlns:jx="http://apache.org/cocoon/templates/jx/1.0" 
+           xmlns:page="http://apache.org/cocoon/lenya/cms-page/1.0" 
+           xmlns="http://www.w3.org/1999/xhtml" 
+           xmlns:i18n="http://apache.org/cocoon/i18n/2.1" >
+
+  <page:title>
+    <i18n:text>Add Known Person</i18n:text>
+  </page:title>
+  <page:body>
+    
+    <jx:import uri="fallback://lenya/modules/usecase/templates/messages.jx"/>
+    
+    <form method="POST">
+      <input type="hidden" name="lenya.usecase" value="${usecase.getName()}"/>
+      <input type="hidden" name="lenya.continuation" value="${continuation.id}"/>
+      
+      <p>
+        <i18n:text>Select a person you know:</i18n:text>
+      </p>
+      <p>
+        <select name="uuid">
+          <jx:forEach var="person" items="${usecase.getParameter('people')}">
+            <option value="${person.getDocument().getUUID()}">
+              <jx:out value="${person.getName()}"/>
+            </option>
+          </jx:forEach>
+        </select>
+      </p>
+  
+      <p>
+        <input i18n:attr="value" name="submit" type="submit" value="Submit"/>
+        <i18n:text> </i18n:text>
+        <input i18n:attr="value" name="cancel" type="submit" value="Cancel"/>
+      </p>
+      
+    </form>
+  </page:body>
+</page:page>]]></source>
+    </section>
+    
+    <section>
+      <title>Adding the Menu Item</title>
+      <p>
+        To be able to trigger the usecase, we have to add the corresponding menu item
+        to the menu of the person module, which is located at
+        <code>$MODULE_HOME/config/menu.xsp</code>. We add a menu block which shall be
+        visible only in the authoring area, right below the block containing the
+        editor menu items. The value of the <code>uc:usecase</code> attribute of the
+        <code><![CDATA[<item/>]]></code> element is the name of the usecase as specified
+        in the usecase declaration.
+      </p>
+      <source xml:space="preserve"><![CDATA[<menu i18n:attr="name" name="Edit">
+  <xsp:logic>
+    try {
+        Object doc = <input:get-attribute module="page-envelope"
+            as="object" name="document"/>;
+        if (doc instanceof Document &amp;&amp; ((Document) doc).exists()) {
+            String doctype = <input:get-attribute module="page-envelope"
+                as="string" name="document-type"/>;
+            if ("person".equals(doctype)) {
+                <block areas="authoring">
+                  <item uc:usecase="bxe.edit" href="?">
+                    <i18n:text>With BXE</i18n:text>
+                  </item>
+                  <item uc:usecase="editors.oneform" href="?">
+                    <i18n:text>With one Form</i18n:text>
+                  </item>
+                </block>
+                <block areas="authoring">
+                  <item uc:usecase="person.addKnownPerson" href="?">
+                    <i18n:text>Add Known Person</i18n:text>
+                  </item>
+                </block>
+            }
+        }
+    }
+    catch (Exception e) {
+        throw new ProcessingException("Error during menu generation: ", e);
+    }
+  </xsp:logic>
+</menu>]]></source>
+    </section>
+    
+    <section>
+      <title>Setting the Usecase Permissions</title>
+      <p>
+        Finally we have to specify who shall be able to execute the usecase.
+        To accomplish this, we have to add an entry to the usecase policies file of the
+        publication(s) which will use the person module. The file is located at
+        <code>$PUB_HOME/config/access-control/usecase-policies.xml</code>.
+        We allow everyone with the <em>admin</em> or <em>editor</em> role to
+        execute the usecase:
+      </p>
+      <source xml:space="preserve"><![CDATA[<usecase id="person.addKnownPerson">
+  <role id="admin" method="grant"/>
+  <role id="edit" method="grant"/>
+</usecase>]]></source>
+      <p>
+        Now you can deploy the changes by running the build process and restarting the
+        servlet engine. After that you should be able to connect people using the
+        "knows" relation.
+      </p>
+    </section>
+    
+    <section>
+      <title>What's Next?</title>
+      <p>
+        There are some important steps which are missing from the example:
+      </p>
+      <ul>
+        <li>
+          In <code>initParameters()</code>, you should exclude the person itself and
+          all people which she or he already knows. 
+        </li>
+        <li>
+          If you set the relation from person A to person B, it probably makes sense
+          to set the relation from B to A at the same time.
+        </li>
+        <li>
+          To avoid sending stack traces to the user, you should validate the <em>uuid</em>
+          parameter: Is it provided? Does it refer to an existing person document?
+          You can do this kind of validation in the <code>doCheckExecutionConditions()</code>
+          method - just call <code>addErrorMessage()</code> for each validation error.
+        </li>
+      </ul>
+    </section>
+    
+  </body>
+</document>



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org