You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by cr...@apache.org on 2005/07/02 05:13:45 UTC

svn commit: r208818 - in /struts/shale/trunk/use-cases: ./ src/java/org/apache/shale/usecases/rolodex/ src/java/org/apache/shale/usecases/view/ src/web/ src/web/WEB-INF/ src/web/rolodex/

Author: craigmcc
Date: Fri Jul  1 20:13:42 2005
New Revision: 208818

URL: http://svn.apache.org/viewcvs?rev=208818&view=rev
Log:
Add the Clay use cases example from Bugzilla ticket 35408

PR:  Bugzilla #35408
Submitted by: Gary VanMatre <gvanmatre AT comcast.net>

Added:
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Address.java
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Contact.java
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/GenericComparator.java
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Rolodex.java
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/RolodexDao.java
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/State.java
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/dex.xml
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/states.xml
    struts/shale/trunk/use-cases/src/web/WEB-INF/clay-config.xml
    struts/shale/trunk/use-cases/src/web/rolodex/
    struts/shale/trunk/use-cases/src/web/rolodex/rolodex.jsp
Modified:
    struts/shale/trunk/use-cases/build.xml
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/view/Bundle.properties
    struts/shale/trunk/use-cases/src/web/WEB-INF/faces-config.xml
    struts/shale/trunk/use-cases/src/web/WEB-INF/web.xml
    struts/shale/trunk/use-cases/src/web/usecases.jsp

Modified: struts/shale/trunk/use-cases/build.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/build.xml?rev=208818&r1=208817&r2=208818&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/build.xml (original)
+++ struts/shale/trunk/use-cases/build.xml Fri Jul  1 20:13:42 2005
@@ -62,6 +62,7 @@
   <property name="junit.jar"        value="${junit.home}/junit.jar"/>
   <property name="servlet-api.jar"  value="${server.home}/common/lib/servlet-api.jar"/>
   <property name="shale-core.jar"   value="${basedir}/../core-library/target/lib/shale-core.jar"/>
+  <property name="shale-clay.jar"   value="${basedir}/../clay-plugin/target/lib/shale-clay.jar"/>
   <property name="shale-spring.jar" value="${basedir}/../core-library/target/lib/shale-spring.jar"/>
   <property name="shale-test.jar"   value="${basedir}/../test-framework/target/lib/shale-test.jar"/>
   <property name="spring-beans.jar" value="${spring.home}/dist/spring-beans.jar"/>
@@ -115,6 +116,7 @@
     <pathelement location="${jstl.jar}"/>
     <pathelement location="${servlet-api.jar}"/>
     <pathelement location="${shale-core.jar}"/>
+    <pathelement location="${shale-clay.jar}"/>
     <pathelement location="${spring-beans.jar}"/>
     <pathelement location="${spring-context.jar}"/>
     <pathelement location="${spring-core.jar}"/>
@@ -136,6 +138,7 @@
     <pathelement location="${junit.jar}"/>
     <pathelement location="${servlet-api.jar}"/>
     <pathelement location="${shale-core.jar}"/>
+    <pathelement location="${shale-clay.jar}"/>
     <pathelement location="${shale-test.jar}"/>
     <pathelement location="${spring-beans.jar}"/>
     <pathelement location="${spring-context.jar}"/>
@@ -195,6 +198,7 @@
     <echo  message="jsf-api.jar =      ${jsf-api.jar}"/>
     <echo  message="jsf-impl.jar =     ${jsf-impl.jar}"/>
     <echo  message="shale-core.jar =   ${shale-core.jar}"/>
+    <echo  message="shale-clay.jar =   ${shale-clay.jar}"/>
     <echo  message="spring-core.jar =  ${spring-core.jar}"/>
     <echo  message="commons-validator.jar =  ${commons-validator.jar}"/>
     <echo  message="jsfri.present =    ${jsfri.present}"/>
@@ -239,6 +243,8 @@
                   file="${commons-validator.jar}"/>
     <copy        todir="${build.home}/${context.path}/WEB-INF/lib"
                   file="${shale-core.jar}"/>
+    <copy        todir="${build.home}/${context.path}/WEB-INF/lib"
+                  file="${shale-clay.jar}"/>
     <copy        todir="${build.home}/${context.path}/WEB-INF/lib"
                   file="${shale-spring.jar}"/>
     <copy        todir="${build.home}/${context.path}/WEB-INF/lib"

Added: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Address.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Address.java?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Address.java (added)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Address.java Fri Jul  1 20:13:42 2005
@@ -0,0 +1,150 @@
+package org.apache.shale.usecases.rolodex;
+
+/**
+ * <p>Holds an addres for a {@link Contact}.</p>
+ */
+public class Address {
+    String street1 = null;
+
+    String street2 = null;
+
+    String city = null;
+
+    String state = null;
+
+    int zip = 0;
+
+    String province = null;
+
+    String country = null;
+    
+
+    /**
+     * <p>
+     * Returns the City.
+     * </p>
+     */
+    public String getCity() {
+        return city;
+    }
+
+    /**
+     * <p>
+     * Sets the City.
+     * </p>
+     */
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    /**
+     * <p>
+     * Gets the Country.
+     * </p>
+     */
+    public String getCountry() {
+        return country;
+    }
+
+    /**
+     * <p>
+     * Sets the Country.
+     * </p>
+     */
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+    /**
+     * <p>
+     * Gets the Province.
+     * </p>
+     */
+    public String getProvince() {
+        return province;
+    }
+
+    /**
+     * <p>
+     * Sets the Province.
+     * </p>
+     */
+    public void setProvince(String province) {
+        this.province = province;
+    }
+
+    /**
+     * <p>
+     * Gets the State
+     * </p>
+     */
+    public String getState() {
+        return state;
+    }
+
+    /**
+     * <p>
+     * Sets the State.
+     * </p>
+     */
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    /**
+     * <p>
+     * Gets the Street1.
+     * </p>
+     */
+    public String getStreet1() {
+        return street1;
+    }
+
+    /**
+     * <p>
+     * Sets the Street1.
+     * </p>
+     */
+    public void setStreet1(String street1) {
+        this.street1 = street1;
+    }
+
+    /**
+     * <p>
+     * Gets the Street2.
+     * </p>
+     */
+    public String getStreet2() {
+        return street2;
+    }
+
+    /**
+     * <p>
+     * Sets the Street2.
+     * </p>
+     */
+    public void setStreet2(String street2) {
+        this.street2 = street2;
+    }
+
+    /**
+     * <p>
+     * Gets the Zip Code.
+     * </p>
+     * 
+     * @return
+     */
+    public int getZip() {
+        return zip;
+    }
+
+    /**
+     * <p>
+     * Sets the Zip Code.
+     * </p>
+     */
+    public void setZip(int zip) {
+        this.zip = zip;
+    }
+
+}

Added: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Contact.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Contact.java?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Contact.java (added)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Contact.java Fri Jul  1 20:13:42 2005
@@ -0,0 +1,155 @@
+package org.apache.shale.usecases.rolodex;
+
+/**
+ * <p>
+ * Represents an entity in the rolodex.
+ * </p>
+ */
+public class Contact {
+    String name = null;
+
+    String email = null;
+
+    String residentialPhone = null;
+
+    Address residentialAddress = null;
+
+    String businessPhone = null;
+
+    Address businessAddress = null;
+
+    /**
+     * <p>
+     * Returns the first char of the name use by the rolodex index.
+     * </p>
+     */
+    public char getTabIndex() {
+        return getSortName().charAt(0);
+    }
+
+    /**
+     * <p>
+     * Returns the business {@link Address}.
+     * </p>
+     */
+    public Address getBusinessAddress() {
+        if (businessAddress == null)
+            businessAddress = new Address();
+
+        return businessAddress;
+    }
+
+    /**
+     * <p>
+     * Sets the business {@link Address}.
+     * </p>
+     */
+    public void setBusinessAddress(Address businessAddress) {
+        this.businessAddress = businessAddress;
+    }
+
+    /**
+     * <p>
+     * Returns the business phone number.
+     * </p>
+     */
+    public String getBusinessPhone() {
+        return businessPhone;
+    }
+
+    /**
+     * <p>
+     * Sets the business phone number
+     * </p>
+     */
+    public void setBusinessPhone(String businessPhone) {
+        this.businessPhone = businessPhone;
+    }
+
+    /**
+     * <p>
+     * Returns the email address.
+     * </p>
+     */
+    public String getEmail() {
+        return email;
+    }
+
+    /**
+     * <p>
+     * Sets the email address.
+     * </p>
+     */
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    /**
+     * <p>
+     * Gets the entity name.
+     * </p>
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * <p>
+     * Sets the entity name.
+     * </p>
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * <p>
+     * Gets the residential {@link Address}.
+     * </p>
+     */
+    public Address getResidentialAddress() {
+        if (residentialAddress == null) {
+            residentialAddress = new Address();
+        }
+        return residentialAddress;
+    }
+
+    /**
+     * <p>
+     * Sets the residential {@link Address}.
+     * </p>
+     */
+    public void setResidentialAddress(Address residentialAddress) {
+        this.residentialAddress = residentialAddress;
+    }
+
+    /**
+     * <p>
+     * Gets the residential phone number.
+     * </p>
+     */
+    public String getResidentialPhone() {
+        return residentialPhone;
+    }
+
+    /**
+     * <p>
+     * Sets the residential phone number.
+     * </p>
+     */
+    public void setResidentialPhone(String residentialPhone) {
+        this.residentialPhone = residentialPhone;
+    }
+
+    /**
+     * <p>Returns the <code>name</code> in upper case.</p>
+     * @return
+     */
+    public String getSortName() {
+       if (name != null)
+          return name.toUpperCase();
+       
+       return null;
+    }
+    
+}

Added: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/GenericComparator.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/GenericComparator.java?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/GenericComparator.java (added)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/GenericComparator.java Fri Jul  1 20:13:42 2005
@@ -0,0 +1,149 @@
+package org.apache.shale.usecases.rolodex;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * <p>Generic comparator that uses a list of property names to compare
+ * the state of two objects using the reflection API.  The property names 
+ * are passed via a comma delimited.  The collating sequence is determined 
+ * by the <code>sortAcending</code> attribute.</p>
+ */
+public class GenericComparator implements Comparator {
+    
+    /**
+     * <p>Common logger utility</p>
+     */
+    public static Log log;
+    static {
+        log = LogFactory.getLog(GenericComparator.class);
+    }   
+
+    /**
+     * <p>Determines the collating sequence.  A <code>true</code> value
+     * will sort acending; otherwise, the list will be sorted in descending
+     * order.</p>
+     */
+    private boolean sortAscending = true;
+   
+    /**
+     * <p>Holds an array of property names in the target object that
+     * will be use to compare the two objects.
+     * </p>
+     */
+    protected List sortBy;
+    
+    /**
+     * <p>Returns <code>true</code> if the collection should be sorted ascending by
+     * the <code>sortBy</code> properties list.<p>
+     */
+    public boolean getSortAscending() {
+        return sortAscending;
+    }
+
+    /**
+     * <p>Sets the sequence the collection should be sorted.  A <code>true</code>
+     * will result in sort ascending.</p>
+     */
+    public void setSortAscending(boolean value) {
+        sortAscending = value;
+    }
+   
+    /**
+     * <p>Passed a comma delimited list of property names to compare two object by.<p>
+     */
+    public void setSortBy(String properties) {
+       StringTokenizer tokenizer = new StringTokenizer(properties, ",");
+       sortBy = new ArrayList();
+       while (tokenizer.hasMoreTokens()) {
+          String token = (String) tokenizer.nextToken().trim();
+          sortBy.add(token);
+       }
+       
+    }
+    
+    /**
+     * <p>Returns a comma delimited list of property names used to compare 
+     * two objects.</p>
+     */
+    public String getSortBy() {
+        StringBuffer tmp = new StringBuffer();
+        if (sortBy != null) {
+           Iterator li = sortBy.iterator();
+           while (li.hasNext()) {
+              if (tmp.length() > 0) {
+                 tmp.append(", ");
+              }
+              tmp.append(li.next());
+           }
+        }
+        
+        return tmp.toString();
+    }
+    
+    /**
+     * <p>Compares the property names in the <code>sortBy</code> list with
+     * the target sortable objects.  The collating sequence is determined 
+     * by the <code>sortAcending</code> attribute.
+     * </p>
+     * 
+     * @param o1 -
+     *            target object 1
+     * @param o2 -
+     *            target object 2
+     * @return - integer value representing the comparison of the two objects
+     *         key properties.
+     */
+    public int compare(Object o1, Object o2) {
+        Iterator it = sortBy.iterator();
+        int result = 0;
+        while (result == 0 && it.hasNext()) {
+            String nextProperty = (String) it.next();
+
+            Object col1 = null;
+            Object col2 = null;
+
+            try {
+                col1 = BeanUtils.getProperty(o1, nextProperty);
+            } catch (Exception e) {
+                log.error("Error finding property " + nextProperty
+                        + "to sort on in the target object", e);
+            }
+
+            try {
+                col2 = BeanUtils.getProperty(o2, nextProperty);
+            } catch (Exception e) {
+                log.error("Error finding property " + nextProperty
+                        + "to sort on in the target object", e);
+            }
+
+            if ((col1 == null) && (col2 == null))
+                result = 0;
+            else if ((col1 == null) && (col2 != null))
+                result = -1;
+            else if ((col2 == null) && (col1 != null))
+                result = 1;
+            else if ((col1 instanceof Comparable)
+                    && (col2 instanceof Comparable))
+                result = ((Comparable) col1).compareTo(col2);
+            else {
+
+                result = ((Comparable) col1.toString()).compareTo(col2
+                        .toString());
+            }
+
+            col1 = null;
+            col2 = null;
+
+        }
+        return  (sortAscending ? 1 : -1) * result;
+    }
+
+}

Added: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Rolodex.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Rolodex.java?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Rolodex.java (added)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/Rolodex.java Fri Jul  1 20:13:42 2005
@@ -0,0 +1,410 @@
+package org.apache.shale.usecases.rolodex;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.shale.clay.component.Clay;
+import org.apache.shale.clay.config.beans.AttributeBean;
+import org.apache.shale.clay.config.beans.ComponentBean;
+import org.apache.shale.clay.config.beans.ElementBean;
+import org.apache.shale.clay.parser.builder.Builder;
+import org.apache.shale.usecases.view.BaseViewController;
+
+/**
+ * <p>
+ * The ViewController for the rolodex use case. This is a contacts list that is
+ * to demonstrate the reuse ability for the Clay component.
+ * </p>
+ * 
+ */
+public class Rolodex extends BaseViewController {
+
+    /**
+     * <p>
+     * Commons logging utility object static instance.
+     * </p>
+     */
+    private static Log log;
+    static {
+        log = LogFactory.getLog(Rolodex.class);
+    }
+
+    /**
+     * <p>
+     * The the selected tab index.
+     * </p>
+     */
+    private int selectedTab = 0;
+
+    /**
+     * <p>
+     * Returns the current tab index.
+     * </p>
+     */
+    public int getSelectedTab() {
+        return selectedTab;
+    }
+
+    /**
+     * <p>
+     * The contact that is selected for edit.
+     * </p>
+     */
+    private Contact selectedContact = null;
+
+    /**
+     * <p>
+     * Returns the selected contact for edit.
+     * </p>
+     */
+    public Contact getSelectedContact() {
+        return selectedContact;
+    }
+
+    /**
+     * <p>
+     * Sets the selected contact for edit.
+     * </p>
+     */
+    public void setSelectedContact(Contact contact) {
+        selectedContact = contact;
+    }
+
+    /**
+     * <p>
+     * Records a change in tab index.
+     * </p>
+     */
+    public void setSelectedTab(int index) {
+        if (log.isInfoEnabled())
+            log.info("Switching from tab " + selectedTab + " to tab " + index);
+
+        selectedTab = index;
+    }
+
+    /**
+     * <p>
+     * Creates an object graph uses to build the rolodex folder tabs dynamically
+     * </p>
+     * 
+     * @param item -
+     *            SelectItem holding the information to create the tab link
+     * @param context -
+     *            FacesContext
+     * @return returns a top level clay meta component bean
+     */
+    protected ElementBean createCommandLinkMetadata(SelectItem item,
+            FacesContext context) {
+
+        // create a command link attribute
+        ElementBean link = new ElementBean();
+        link.setRenderId(generateId());
+        link.setJsfid("commandLink");
+        link.setComponentType("javax.faces.HtmlCommandLink");
+
+        // add a value attribute
+        AttributeBean attr = new AttributeBean();
+        attr.setName("value");
+        attr.setValue(item.getLabel());
+        link.addAttribute(attr);
+
+        // turn on the the immediate attribute so the validation
+        // logic is not invoked when switching tabs
+        attr = new AttributeBean();
+        attr.setName("immediate");
+        attr.setValue("true");
+        link.addAttribute(attr);
+
+        // add a action method binding event when the link is clicked
+        attr = new AttributeBean();
+        attr.setName("action");
+        attr.setValue("#{managed-bean-name.changeTab}");
+        link.addAttribute(attr);
+
+        // create a parameter
+        ElementBean param = new ElementBean();
+        param.setJsfid("param");
+        param.setComponentType("javax.faces.Parameter");
+
+        // add a query param for the selected tab index
+        attr = new AttributeBean();
+        attr.setName("name");
+        attr.setValue("tabIndex");
+        param.addAttribute(attr);
+
+        // add a query parameter for the tab index
+        attr = new AttributeBean();
+        attr.setName("value");
+        attr.setValue(((Integer) item.getValue()).toString());
+        param.addAttribute(attr);
+
+        // add a parameter to the commandLink
+        link.addChild(param);
+
+        return link;
+    }
+
+    /**
+     * <p>
+     * A sequential counter to generate a unique renderId.
+     * </p>
+     */
+    int renderId = 0;
+
+    /**
+     * <p>
+     * Returns the next sequential renderId. Because the logic builds the list
+     * in a linear fashion, a sequential unintelligent counter works.
+     * </p>
+     */
+    private int generateId() {
+        return renderId++;
+    }
+
+    /**
+     * <p>
+     * This method builds a verbatim meta tag. It is passed a "rendered"
+     * expression that will be evaluated to determine if the component is
+     * visible.
+     * </p>
+     * 
+     * @param html
+     *            The HTML tag to write to the document
+     * @param renderExp
+     *            A value binding EL for the "rendered" attribute.
+     * @param context
+     *            faces context
+     * @return A clay element bean used to construct a faces outputText
+     *         component.
+     */
+    protected ElementBean createVerbatimMetadata(String html, String renderExp,
+            FacesContext context) {
+        ElementBean text = createVerbatimMetadata(html, context);
+
+        // add a rendered attribute
+        AttributeBean attr = new AttributeBean();
+        attr.setName("rendered");
+        attr.setValue(renderExp);
+        attr.setUseValueLateBinding(Boolean.TRUE.toString());
+        text.addAttribute(attr);
+
+        return text;
+
+    }
+
+    /**
+     * <p>
+     * This mehtod builds a simple verbatim meta tag. The value will not be
+     * escaped.
+     * <p>
+     * 
+     * @param html
+     *            HTML tag to write to the document
+     * @param context -
+     *            faces context
+     * @return A clay element bean used to construct a faces outputText
+     *         component.
+     */
+    protected ElementBean createVerbatimMetadata(String html,
+            FacesContext context) {
+
+        // create an output Text
+        ElementBean text = new ElementBean();
+        text.setRenderId(generateId());
+        text.setJsfid("outputText");
+        text.setComponentType("javax.faces.HtmlOutputText");
+
+        // add a value attribute
+        AttributeBean attr = new AttributeBean();
+        attr.setName("value");
+        attr.setValue(html);
+        text.addAttribute(attr);
+
+        // add a escape attribute
+        attr = new AttributeBean();
+        attr.setName("escape");
+        attr.setValue(Boolean.FALSE.toString());
+        text.addAttribute(attr);
+
+        return text;
+    }
+
+    /**
+     * <p>
+     * This action event is fired when clicking on a tab link. The
+     * <code>selectedTab</code> is set with the value of the
+     * <code>tabIndex</code> request parameter.
+     * </p>
+     */
+    public String changeTab() {
+        if (log.isInfoEnabled())
+            log.info("changeTab()");
+
+        FacesContext context = FacesContext.getCurrentInstance();
+        Map requestMap = context.getExternalContext().getRequestParameterMap();
+        String tabIndex = (String) requestMap.get("tabIndex");
+        if (tabIndex != null) {
+            setSelectedTab(Integer.parseInt(tabIndex));
+
+            // clear out the selected contact
+            setSelectedContact(null);
+        }
+
+        return "rolodex$test";
+    }
+
+    /**
+     * <p>
+     * This is a method binding event fired from the <strong>Clay</strong>
+     * component before building the component tree. The method signature is a
+     * "Validator" event signature and the binding attribute is
+     * <code>shapeValidator</code>.
+     * </p>
+     * 
+     * @param context
+     *            facesContext
+     * @param component
+     * @param displayElementRoot
+     */
+    public void createTabs(javax.faces.context.FacesContext context,
+            javax.faces.component.UIComponent component,
+            java.lang.Object displayElementRoot) {
+
+        if (log.isInfoEnabled())
+            log.info("createTabs()");
+
+        // cast to the clay component, the one triggering the event
+        Clay clayComponent = (Clay) component;
+
+        // find the dao cached in application scope
+        RolodexDao dao = (RolodexDao) getBean("rolodexDao");
+
+        // return a list of tabs
+        List tabs = dao.getTabs();
+
+        ComponentBean root = (ComponentBean) displayElementRoot;
+        root.setComponentType("javax.faces.HtmlPanelGroup");
+        root.addChild(createVerbatimMetadata("<ul id=\"menu\">", context));
+
+        for (int i = 0; i < tabs.size(); i++) {
+            SelectItem item = (SelectItem) tabs.get(i);
+
+            root.addChild(createVerbatimMetadata("<li id=\"", context));
+
+            root.addChild(createVerbatimMetadata("nav-sel",
+                    "#{managed-bean-name.selectedTab == " + i + "}", context));
+            root.addChild(createVerbatimMetadata("nav",
+                    "#{managed-bean-name.selectedTab != " + i + "}", context));
+
+            root.addChild(createVerbatimMetadata("\">", context));
+            root.addChild(createCommandLinkMetadata(item, context));
+            root.addChild(createVerbatimMetadata("</li>", context));
+        }
+
+        root.addChild(createVerbatimMetadata("</ul>", context));
+
+    }
+
+    /**
+     * <p>
+     * This is called by the data table component to return a list of
+     * {@link Contact}s that belong within the selected index.
+     * </p>
+     */
+    public List getContactsForTab() {
+        if (log.isInfoEnabled())
+            log.info("getContactsForTab()");
+
+        // find the dao cached in application scope
+        RolodexDao dao = (RolodexDao) getBean("rolodexDao");
+
+        // gets a list of contacts matching the selected tab index
+        List contacts = dao.findContactsForTab(getSelectedTab());
+
+        return contacts;
+    }
+
+    /**
+     * <p>
+     * This is an action event fired from clicking on a contact in the data
+     * grid. The latest contact is located using the data access object and is
+     * set as the "select" contact.
+     * </p>
+     */
+    public String selectContact() {
+        if (log.isInfoEnabled())
+            log.info("selectContact()");
+
+        FacesContext context = FacesContext.getCurrentInstance();
+
+        // look for the commandLink query parameter
+        Map requestMap = context.getExternalContext().getRequestParameterMap();
+        String name = (String) requestMap.get("selectedName");
+        if (name != null) {
+            // find the dao cached in application scope
+            RolodexDao dao = (RolodexDao) getBean("rolodexDao");
+
+            // finds the selected contact by name
+            setSelectedContact(dao.findContact(name));
+        }
+
+        return "rolodex$test";
+    }
+
+    /**
+     * <p>
+     * Saves a {@link Contact} to the mock data store.
+     * </p>
+     */
+    public String saveContact() {
+        if (log.isInfoEnabled())
+            log.info("saveContact()");
+
+        if (getSelectedContact() != null) {
+            RolodexDao dao = (RolodexDao) getBean("rolodexDao");
+            // the saveContact method will return the page the 
+            // new contact will appear
+            setSelectedTab(dao.saveContact(getSelectedContact()));
+        }
+
+        return "rolodex$test";
+    }
+
+    /**
+     * <p>
+     * Removes a {@link Contact} from the mock data store.
+     * </p>
+     */
+    public String deleteContact() {
+        if (log.isInfoEnabled())
+            log.info("deleteContact()");
+
+        if (getSelectedContact() != null) {
+            RolodexDao dao = (RolodexDao) getBean("rolodexDao");
+            dao.deleteContact(getSelectedContact());
+            setSelectedContact(null);
+        }
+
+        return "rolodex$test";
+    }
+
+    /**
+     * <p>
+     * Creates a new {@link Contact} instance to be entered and saved.
+     * </p>
+     */
+    public String newContact() {
+       if (log.isInfoEnabled())
+           log.info("newContact()");
+               
+        setSelectedContact(new Contact());
+        
+        return "rolodex$test";
+    }
+
+}

Added: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/RolodexDao.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/RolodexDao.java?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/RolodexDao.java (added)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/RolodexDao.java Fri Jul  1 20:13:42 2005
@@ -0,0 +1,320 @@
+package org.apache.shale.usecases.rolodex;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.faces.model.SelectItem;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>
+ * Data Access Object for the roledex use case.
+ * </p>
+ */
+public class RolodexDao {
+
+    /**
+     * <p>
+     * Commons logging utility object static instance.
+     * </p>
+     */
+    private static Log log;
+    static {
+        log = LogFactory.getLog(RolodexDao.class);
+    }
+
+    /**
+     * <p>
+     * Mock datastore.
+     * </p>
+     */
+    private Collection entityDataStore = null;
+
+    private Collection stateDataStore = null;
+
+    private Collection countryDataStore = null;
+
+    /**
+     * <p>
+     * The constructor loads some default data.
+     * </p>
+     */
+    public RolodexDao() {
+        GenericComparator comparator = new GenericComparator();
+        comparator.setSortBy("sortName, name");
+
+        entityDataStore = new TreeSet(comparator);
+
+        comparator = new GenericComparator();
+        comparator.setSortBy("value");
+
+        stateDataStore = new TreeSet(comparator);
+        countryDataStore = new TreeSet(comparator);
+        loadStates();
+    }
+
+    /**
+     * <p>
+     * Tab indexes for the rolodex. Each sub array represents the starting and
+     * ending character index.
+     * </p>
+     */
+    public final static char[][] TAB_INDEX = { { 'A', 'B' }, { 'C', 'D' },
+            { 'E', 'F' }, { 'G', 'H' }, { 'I', 'J' }, { 'K', 'L' },
+            { 'M', 'N' }, { 'O', 'P' }, { 'Q', 'Z' } };
+
+    /**
+     * <p>
+     * Returns a list of <code>SelectItem</code> that will be used to build
+     * the links
+     * </p>
+     */
+    public List getTabs() {
+        List tabs = new ArrayList();
+        SelectItem tab = null;
+
+        for (int i = 0; i < TAB_INDEX.length; i++) {
+            tab = new SelectItem();
+            tab.setLabel(TAB_INDEX[i][0] + "-" + TAB_INDEX[i][1]);
+            tab.setValue(new Integer(i));
+            tabs.add(tab);
+        }
+
+        return tabs;
+    }
+
+    /**
+     * <p>
+     * Saves a {@link Contact} to the mock data store
+     * </p>
+     */
+    public int saveContact(Contact entity) {
+        entityDataStore.add(entity);
+        return findTabForContact(entity);
+    }
+
+    /**
+     * <p>This function will find the tabIndex that the {@link Contact}
+     * will be located on.  It will default to the first page.</p>
+     */
+    public int findTabForContact(Contact contact) {
+        for (int i = 0; i < TAB_INDEX.length; i++) {
+           if ((contact.getTabIndex() >= TAB_INDEX[i][0]) && 
+               (contact.getTabIndex() <= TAB_INDEX[i][1]))  
+              return i;    
+        }
+        
+        return 0;
+    }
+    
+    
+    /**
+     * <p>
+     * Retuns a subset of contacts within the <code>index</code> of a a tab
+     * defined by <code>TAB_INDEX</code> from the mock data store. If this was
+     * a RDBMS data store, the contacts returned might be a "ghost" object
+     * meaning that maybe only the <code>name</code> attribute would be
+     * populated.
+     * </p>
+     */
+    public List findContactsForTab(int index) {
+        List contacts = new ArrayList();
+
+        Contact low = new Contact();
+        Contact high = new Contact();
+
+        StringBuffer key = new StringBuffer();
+        
+        key.append(TAB_INDEX[index][0]);
+        low.setName(key.toString());
+
+        key.setLength(0);
+        key.append(TAB_INDEX[index][1]);
+        for (int i = 0; i < 50; i++)
+           key.append('z');
+
+        high.setName(key.toString());
+
+        SortedSet subSet = ((SortedSet) entityDataStore).subSet(low, high);
+        Iterator si = subSet.iterator();
+        while (si.hasNext())
+            contacts.add(si.next());
+
+        return contacts;
+    }
+
+    /**
+     * <p>
+     * Removes the contact from the mock data store.
+     * </p>
+     */
+    public void deleteContact(Contact entity) {
+        entityDataStore.remove(entity);
+    }
+
+    /**
+     * <p>
+     * Loads the {@link State} codes and contacts from an XML data source. The
+     * <code>stateDataStore</code> set will hold the states where the
+     * <code>countryDataStore</code> set will hold the countries. The target type of
+     * these collections will be SelectItem.  The contacts are held in the 
+     * <code>entityDataStore</code> set.
+     * </p>
+     */
+    public void loadStates() {
+
+        Object config = new Object() {
+            public void addState(State state) {
+                SelectItem item = new SelectItem();
+                item.setLabel(state.getState());
+                item.setValue(state.getAbbrState());
+                stateDataStore.add(item);
+
+                item = new SelectItem();
+                item.setLabel(state.getCountry());
+                item.setValue(state.getAbbrCountry());
+                countryDataStore.add(item);
+            }
+
+            public void addContact(Contact contact) {
+                saveContact(contact);
+            }
+        };
+
+        Digester digester = new Digester();
+        digester.setValidating(false);
+        digester.setUseContextClassLoader(true);
+
+        digester.addObjectCreate("dex/states/state",
+                org.apache.shale.usecases.rolodex.State.class);
+        digester.addSetProperties("dex/states/state");
+        digester.addSetNext("dex/states/state", "addState",
+                "org.apache.shale.usecases.rolodex.State");
+
+        digester.addObjectCreate("dex/contacts/contact/residentialAddress",
+                org.apache.shale.usecases.rolodex.Address.class);
+        digester.addCallMethod(
+                "dex/contacts/contact/residentialAddress/street1",
+                "setStreet1", 0);
+        digester.addCallMethod(
+                "dex/contacts/contact/residentialAddress/street2",
+                "setStreet2", 0);
+        digester.addCallMethod("dex/contacts/contact/residentialAddress/city",
+                "setCity", 0);
+        digester.addCallMethod("dex/contacts/contact/residentialAddress/state",
+                "setState", 0);
+        //digester.addCallMethod("dex/contacts/contact/residentialAddress/zip",
+        //        "setZip", 0);
+        digester.addCallMethod(
+                "dex/contacts/contact/residentialAddress/province",
+                "setProvince", 0);
+        digester.addCallMethod(
+                "dex/contacts/contact/residentialAddress/country",
+                "setCountry", 0);
+        digester.addSetNext("dex/contacts/contact/residentialAddress",
+                "setResidentialAddress",
+                "org.apache.shale.usecases.rolodex.Address");
+
+        digester.addObjectCreate("dex/contacts/contact/businessAddress",
+                org.apache.shale.usecases.rolodex.Address.class);
+        digester.addCallMethod("dex/contacts/contact/businessAddress/street1",
+                "setStreet1", 0);
+        digester.addCallMethod("dex/contacts/contact/businessAddress/street2",
+                "setStreet2", 0);
+        digester.addCallMethod("dex/contacts/contact/businessAddress/city",
+                "setCity", 0);
+        digester.addCallMethod("dex/contacts/contact/businessAddress/state",
+                "setState", 0);
+        //digester.addCallMethod("dex/contacts/contact/businessAddress/zip",
+        //        "setZip", 0);
+        digester.addCallMethod("dex/contacts/contact/businessAddress/province",
+                "setProvince", 0);
+        digester.addCallMethod("dex/contacts/contact/businessAddress/country",
+                "setCountry", 0);
+        digester.addSetNext("dex/contacts/contact/businessAddress",
+                "setBusinessAddress",
+                "org.apache.shale.usecases.rolodex.Address");
+
+        digester.addObjectCreate("dex/contacts/contact",
+                org.apache.shale.usecases.rolodex.Contact.class);
+        digester.addCallMethod("dex/contacts/contact/name", "setName", 0);
+        digester.addCallMethod("dex/contacts/contact/email", "setEmail", 0);
+        digester.addCallMethod("dex/contacts/contact/residentialPhone",
+                "setResidentialPhone", 0);
+        digester.addCallMethod("dex/contacts/contact/businessPhone",
+                "setBusinessPhone", 0);
+        digester.addSetNext("dex/contacts/contact", "addContact",
+                "org.apache.shale.usecases.rolodex.Contact");
+
+        digester.push(config);
+
+        ClassLoader classloader = Thread.currentThread()
+                .getContextClassLoader();
+        if (classloader == null)
+            classloader = config.getClass().getClassLoader();
+
+        InputSource in = new InputSource(
+                classloader
+                        .getResourceAsStream("org/apache/shale/usecases/rolodex/dex.xml"));
+
+        try {
+            digester.parse(in);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (SAXException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     * <p>
+     * Returns an array of states used to populate a select list. The target
+     * type is an array of SelectItem.
+     * </p>
+     */
+    public SelectItem[] getStates() {
+        SelectItem[] states = new SelectItem[stateDataStore.size()];
+        stateDataStore.toArray(states);
+        return states;
+    }
+
+    /**
+     * <p>
+     * Returns an array of countries used to populate a select list. The target
+     * type is an array of SelectItem.
+     * </p>
+     */
+    public SelectItem[] getCountries() {
+        SelectItem[] countries = new SelectItem[countryDataStore.size()];
+        countryDataStore.toArray(countries);
+        return countries;
+    }
+
+    /**
+     * <p>
+     * Returns the latest copy of the {@link Contact} by primary key.
+     * </p>
+     * 
+     * @param name
+     *            contact name that uniquely identifies a Contact.
+     * @return the target, fully populated {@link Contact}
+     */
+    public Contact findContact(String name) {
+        Contact sarg = new Contact();
+        sarg.setName(name);
+        SortedSet subSet = ((TreeSet) entityDataStore).tailSet(sarg);
+        return (Contact) subSet.first();
+    }
+
+}

Added: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/State.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/State.java?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/State.java (added)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/State.java Fri Jul  1 20:13:42 2005
@@ -0,0 +1,76 @@
+package org.apache.shale.usecases.rolodex;
+
+/**
+ * <p>Represents a State domain object.</p>
+ */
+public class State {
+    private String abbrState = null;
+
+    private String state = null;
+
+    private String country = null;
+    
+    private String abbrCountry = null;
+
+    /**
+     * @return Returns the abbrCountry.
+     */
+    public String getAbbrCountry() {
+        return abbrCountry;
+    }
+    
+
+    /**
+     * @param abbrCountry The abbrCountry to set.
+     */
+    public void setAbbrCountry(String abbrCountry) {
+        this.abbrCountry = abbrCountry;
+    }
+    
+
+    /**
+     * @return Returns the abbrState.
+     */
+    public String getAbbrState() {
+        return abbrState;
+    }
+
+    /**
+     * @param abbrState
+     *            The abbrState to set.
+     */
+    public void setAbbrState(String abbrState) {
+        this.abbrState = abbrState;
+    }
+
+    /**
+     * @return Returns the country.
+     */
+    public String getCountry() {
+        return country;
+    }
+
+    /**
+     * @param country
+     *            The country to set.
+     */
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+    /**
+     * @return Returns the state.
+     */
+    public String getState() {
+        return state;
+    }
+
+    /**
+     * @param state
+     *            The state to set.
+     */
+    public void setState(String state) {
+        this.state = state;
+    }
+
+}

Added: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/dex.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/dex.xml?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/dex.xml (added)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/dex.xml Fri Jul  1 20:13:42 2005
@@ -0,0 +1,187 @@
+<dex>
+<states>
+	<state abbrState="AL" state="Alabama" country="United States" abbrCountry="US"/>
+	<state abbrState="AK" state="Alaska" country="United States" abbrCountry="US"/>
+	<state abbrState="AZ" state="Arizona" country="United States" abbrCountry="US"/>
+	<state abbrState="AR" state="Arkansas" country="United States" abbrCountry="US"/>
+	<state abbrState="CA" state="California" country="United States" abbrCountry="US"/>
+	<state abbrState="CO" state="Colorado" country="United States" abbrCountry="US"/>
+	<state abbrState="CT" state="Connecticut" country="United States" abbrCountry="US"/>
+	<state abbrState="DE" state="Delaware" country="United States" abbrCountry="US"/>
+	<state abbrState="FL" state="Florida" country="United States" abbrCountry="US"/>
+	<state abbrState="GA" state="Georgia" country="United States" abbrCountry="US"/>
+	<state abbrState="HI" state="Hawaii" country="United States" abbrCountry="US"/>
+	<state abbrState="ID" state="Idaho" country="United States" abbrCountry="US"/>
+	<state abbrState="IL" state="Illinois" country="United States" abbrCountry="US"/>
+	<state abbrState="IN" state="Indiana" country="United States" abbrCountry="US"/>
+	<state abbrState="IA" state="Iowa" country="United States" abbrCountry="US"/>
+	<state abbrState="KS" state="Kansas" country="United States" abbrCountry="US"/>
+	<state abbrState="KY" state="Kentucky" country="United States" abbrCountry="US"/>
+	<state abbrState="LA" state="Louisiana" country="United States" abbrCountry="US"/>
+	<state abbrState="ME" state="Maine" country="United States" abbrCountry="US"/>
+	<state abbrState="MD" state="Maryland" country="United States" abbrCountry="US"/>
+	<state abbrState="MA" state="Massachusetts" country="United States" abbrCountry="US"/>
+	<state abbrState="MI" state="Michigan" country="United States" abbrCountry="US"/>
+	<state abbrState="MN" state="Minnesota" country="United States" abbrCountry="US"/>
+	<state abbrState="MS" state="Mississippi" country="United States" abbrCountry="US"/>
+	<state abbrState="MO" state="Missouri" country="United States" abbrCountry="US"/>
+	<state abbrState="MT" state="Montana" country="United States" abbrCountry="US"/>
+	<state abbrState="NE" state="Nebraska" country="United States" abbrCountry="US"/>
+	<state abbrState="NV" state="Nevada" country="United States" abbrCountry="US"/>
+	<state abbrState="NH" state="New Hampshire" country="United States" abbrCountry="US"/>
+	<state abbrState="NJ" state="New Jersey" country="United States" abbrCountry="US"/>
+	<state abbrState="NM" state="New Mexico" country="United States" abbrCountry="US"/>
+	<state abbrState="NY" state="New York" country="United States" abbrCountry="US"/>
+	<state abbrState="NC" state="North Carolina"
+		country="United States" abbrCountry="US"/>
+	<state abbrState="ND" state="North Dakota" country="United States" abbrCountry="US"/>
+	<state abbrState="OH" state="Ohio" country="United States" abbrCountry="US"/>
+	<state abbrState="OK" state="Oklahoma" country="United States" abbrCountry="US"/>
+	<state abbrState="OR" state="Oregon" country="United States" abbrCountry="US"/>
+	<state abbrState="PA" state="Pennsylvania" country="United States" abbrCountry="US"/>
+	<state abbrState="RI" state="Rhode Island" country="United States" abbrCountry="US"/>
+	<state abbrState="SC" state="South Carolina"
+		country="United States" abbrCountry="US"/>
+	<state abbrState="SD" state="South Dakota" country="United States" abbrCountry="US"/>
+	<state abbrState="TN" state="Tennessee" country="United States" abbrCountry="US"/>
+	<state abbrState="TX" state="Texas" country="United States" abbrCountry="US"/>
+	<state abbrState="UT" state="Utah" country="United States" abbrCountry="US"/>
+	<state abbrState="VT" state="Vermont" country="United States" abbrCountry="US"/>
+	<state abbrState="VA" state="Virginia" country="United States" abbrCountry="US"/>
+	<state abbrState="WA" state="Washington" country="United States" abbrCountry="US"/>
+	<state abbrState="WV" state="West Virginia" country="United States" abbrCountry="US"/>
+	<state abbrState="WI" state="Wisconsin" country="United States" abbrCountry="US"/>
+	<state abbrState="WY" state="Wyoming" country="United States" abbrCountry="US"/>
+	<state abbrState="AB" state="Alberta" country="Canada" abbrCountry="CA"/>
+	<state abbrState="BC" state="British Columbia" country="Canada" abbrCountry="CA"/>
+	<state abbrState="MB" state="Manitoba" country="Canada" abbrCountry="CA"/>
+	<state abbrState="NB" state="New Brunswick" country="Canada" abbrCountry="CA"/>
+	<state abbrState="NT" state="Northwest Territories"
+		country="Canada" abbrCountry="CA"/>
+	<state abbrState="NS" state="Nova Scotia" country="Canada" abbrCountry="CA"/>
+	<state abbrState="NU" state="Nunavut" country="Canada" abbrCountry="CA"/>
+	<state abbrState="ON" state="Ontario" country="Canada" abbrCountry="CA"/>
+	<state abbrState="PE" state="Prince Edward Island" country="Canada" abbrCountry="CA"/>
+	<state abbrState="QC" state="Quebec" country="Canada" abbrCountry="CA"/>
+	<state abbrState="SK" state="Saskatchewan" country="Canada" abbrCountry="CA"/>
+	<state abbrState="YT" state="Yukon" country="Canada" abbrCountry="CA"/>
+</states>
+
+<contacts>
+   <contact>
+      <name>Allen, Frank</name>
+      <email>frank.allen@xys.net</email>
+      <residentialPhone>(303) 792-0774</residentialPhone>
+      <businessPhone>(303) 792-0775</businessPhone>
+      <residentialAddress>
+         <street1>1215 E Briarwood Av</street1>
+         <street2></street2>
+         <city>Englewood</city>
+         <state>CO</state>
+         <zip>80111</zip>
+      </residentialAddress>     
+      <businessAddress>
+         <street1>5664 S Delaware Dr</street1>
+         <street2></street2>
+         <city>Littleton</city>
+         <state>CO</state>
+         <zip>80212</zip>
+         <province></province>
+         <country>US</country>
+      </businessAddress>           
+   </contact>
+   
+   <contact>
+      <name>Barker, Russell R and Associates PC</name>
+      <email>russell@comcast.net</email>
+      <residentialPhone></residentialPhone>
+      <businessPhone>(303) 771-0608</businessPhone>
+      <residentialAddress>
+         <street1>9567 E Costilla Ave</street1>
+         <street2></street2>
+         <city>Greenwood Village</city>
+         <state>CO</state>
+         <zip>80131</zip>
+      </residentialAddress>     
+      <businessAddress>
+         <street1>43 Inverness Drive East</street1>
+         <street2></street2>
+         <city>Aurora</city>
+         <state>CO</state>
+         <zip>80412</zip>
+         <province></province>
+         <country>US</country>
+      </businessAddress>           
+   </contact>
+
+   <contact>
+      <name>Black Bear Construction Svc Inc</name>
+      <email>black.bear@hotmail.com</email>
+      <residentialPhone></residentialPhone>
+      <businessPhone>(303) 971-8608</businessPhone>
+      <residentialAddress>
+         <street1>345 S Platte River Dr</street1>
+         <street2>PO 899</street2>
+         <city>Denver</city>
+         <state>CO</state>
+         <zip>80161</zip>
+      </residentialAddress>     
+      <businessAddress>
+         <street1>71003 W Oxford Av Sheridan</street1>
+         <street2></street2>
+         <city>Lakewood</city>
+         <state>CO</state>
+         <zip>80512</zip>
+         <province></province>
+         <country>US</country>
+      </businessAddress>           
+   </contact>
+
+   <contact>
+      <name>Banister's Custom Wrough Iron</name>
+      <email>iron@banister.com</email>
+      <residentialPhone></residentialPhone>
+      <businessPhone>(720) 791-1977</businessPhone>
+      <residentialAddress>
+         <street1>3421 Fox</street1>
+         <street2></street2>
+         <city>Parker</city>
+         <state>CO</state>
+         <zip>80166</zip>
+      </residentialAddress>     
+      <businessAddress>
+         <street1>8977 Brandon Dr.</street1>
+         <street2></street2>
+         <city>Lakewood</city>
+         <state>CO</state>
+         <zip>80512</zip>
+         <province></province>
+         <country>US</country>
+      </businessAddress>           
+   </contact>
+
+   <contact>
+      <name>Dogwatch affordable Fence Co.</name>
+      <email>dogwatch@banister.com</email>
+      <residentialPhone></residentialPhone>
+      <businessPhone>(303) 345-3355</businessPhone>
+      <residentialAddress>
+         <street1>10032 W. Remington Ave.</street1>
+         <street2>#400</street2>
+         <city>Centennial</city>
+         <state>CO</state>
+         <zip>80134</zip>
+      </residentialAddress>     
+      <businessAddress>
+         <street1>8977 Brandon Dr.</street1>
+         <street2></street2>
+         <city>Lakewood</city>
+         <state>CO</state>
+         <zip>80512</zip>
+         <province></province>
+         <country>US</country>
+      </businessAddress>           
+   </contact>
+
+</contacts>
+</dex>
\ No newline at end of file

Added: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/states.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/states.xml?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/states.xml (added)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/rolodex/states.xml Fri Jul  1 20:13:42 2005
@@ -0,0 +1,67 @@
+<states>
+	<state abbrState="AL" state="Alabama" country="United States" abbrCountry="US"/>
+	<state abbrState="AK" state="Alaska" country="United States" abbrCountry="US"/>
+	<state abbrState="AZ" state="Arizona" country="United States" abbrCountry="US"/>
+	<state abbrState="AR" state="Arkansas" country="United States" abbrCountry="US"/>
+	<state abbrState="CA" state="California" country="United States" abbrCountry="US"/>
+	<state abbrState="CO" state="Colorado" country="United States" abbrCountry="US"/>
+	<state abbrState="CT" state="Connecticut" country="United States" abbrCountry="US"/>
+	<state abbrState="DE" state="Delaware" country="United States" abbrCountry="US"/>
+	<state abbrState="FL" state="Florida" country="United States" abbrCountry="US"/>
+	<state abbrState="GA" state="Georgia" country="United States" abbrCountry="US"/>
+	<state abbrState="HI" state="Hawaii" country="United States" abbrCountry="US"/>
+	<state abbrState="ID" state="Idaho" country="United States" abbrCountry="US"/>
+	<state abbrState="IL" state="Illinois" country="United States" abbrCountry="US"/>
+	<state abbrState="IN" state="Indiana" country="United States" abbrCountry="US"/>
+	<state abbrState="IA" state="Iowa" country="United States" abbrCountry="US"/>
+	<state abbrState="KS" state="Kansas" country="United States" abbrCountry="US"/>
+	<state abbrState="KY" state="Kentucky" country="United States" abbrCountry="US"/>
+	<state abbrState="LA" state="Louisiana" country="United States" abbrCountry="US"/>
+	<state abbrState="ME" state="Maine" country="United States" abbrCountry="US"/>
+	<state abbrState="MD" state="Maryland" country="United States" abbrCountry="US"/>
+	<state abbrState="MA" state="Massachusetts" country="United States" abbrCountry="US"/>
+	<state abbrState="MI" state="Michigan" country="United States" abbrCountry="US"/>
+	<state abbrState="MN" state="Minnesota" country="United States" abbrCountry="US"/>
+	<state abbrState="MS" state="Mississippi" country="United States" abbrCountry="US"/>
+	<state abbrState="MO" state="Missouri" country="United States" abbrCountry="US"/>
+	<state abbrState="MT" state="Montana" country="United States" abbrCountry="US"/>
+	<state abbrState="NE" state="Nebraska" country="United States" abbrCountry="US"/>
+	<state abbrState="NV" state="Nevada" country="United States" abbrCountry="US"/>
+	<state abbrState="NH" state="New Hampshire" country="United States" abbrCountry="US"/>
+	<state abbrState="NJ" state="New Jersey" country="United States" abbrCountry="US"/>
+	<state abbrState="NM" state="New Mexico" country="United States" abbrCountry="US"/>
+	<state abbrState="NY" state="New York" country="United States" abbrCountry="US"/>
+	<state abbrState="NC" state="North Carolina"
+		country="United States" abbrCountry="US"/>
+	<state abbrState="ND" state="North Dakota" country="United States" abbrCountry="US"/>
+	<state abbrState="OH" state="Ohio" country="United States" abbrCountry="US"/>
+	<state abbrState="OK" state="Oklahoma" country="United States" abbrCountry="US"/>
+	<state abbrState="OR" state="Oregon" country="United States" abbrCountry="US"/>
+	<state abbrState="PA" state="Pennsylvania" country="United States" abbrCountry="US"/>
+	<state abbrState="RI" state="Rhode Island" country="United States" abbrCountry="US"/>
+	<state abbrState="SC" state="South Carolina"
+		country="United States" abbrCountry="US"/>
+	<state abbrState="SD" state="South Dakota" country="United States" abbrCountry="US"/>
+	<state abbrState="TN" state="Tennessee" country="United States" abbrCountry="US"/>
+	<state abbrState="TX" state="Texas" country="United States" abbrCountry="US"/>
+	<state abbrState="UT" state="Utah" country="United States" abbrCountry="US"/>
+	<state abbrState="VT" state="Vermont" country="United States" abbrCountry="US"/>
+	<state abbrState="VA" state="Virginia" country="United States" abbrCountry="US"/>
+	<state abbrState="WA" state="Washington" country="United States" abbrCountry="US"/>
+	<state abbrState="WV" state="West Virginia" country="United States" abbrCountry="US"/>
+	<state abbrState="WI" state="Wisconsin" country="United States" abbrCountry="US"/>
+	<state abbrState="WY" state="Wyoming" country="United States" abbrCountry="US"/>
+	<state abbrState="AB" state="Alberta" country="Canada" abbrCountry="CA"/>
+	<state abbrState="BC" state="British Columbia" country="Canada" abbrCountry="CA"/>
+	<state abbrState="MB" state="Manitoba" country="Canada" abbrCountry="CA"/>
+	<state abbrState="NB" state="New Brunswick" country="Canada" abbrCountry="CA"/>
+	<state abbrState="NT" state="Northwest Territories"
+		country="Canada" abbrCountry="CA"/>
+	<state abbrState="NS" state="Nova Scotia" country="Canada" abbrCountry="CA"/>
+	<state abbrState="NU" state="Nunavut" country="Canada" abbrCountry="CA"/>
+	<state abbrState="ON" state="Ontario" country="Canada" abbrCountry="CA"/>
+	<state abbrState="PE" state="Prince Edward Island" country="Canada" abbrCountry="CA"/>
+	<state abbrState="QC" state="Quebec" country="Canada" abbrCountry="CA"/>
+	<state abbrState="SK" state="Saskatchewan" country="Canada" abbrCountry="CA"/>
+	<state abbrState="YT" state="Yukon" country="Canada" abbrCountry="CA"/>
+</states>
\ No newline at end of file

Modified: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/view/Bundle.properties
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/view/Bundle.properties?rev=208818&r1=208817&r2=208818&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/view/Bundle.properties (original)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/view/Bundle.properties Fri Jul  1 20:13:42 2005
@@ -127,6 +127,8 @@
 usecases.validate=Validation (client- and server-side)
 usecases.tiles=Tiles
 usecases.tiles.simple=A Simple Tiles Example
+usecases.clay=Clay View Use Cases
+usecases.rolodex=Rolodex Example
 
 # Validation
 validate.test.title=Shale Validation using Commons Validator

Added: struts/shale/trunk/use-cases/src/web/WEB-INF/clay-config.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/web/WEB-INF/clay-config.xml?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/web/WEB-INF/clay-config.xml (added)
+++ struts/shale/trunk/use-cases/src/web/WEB-INF/clay-config.xml Fri Jul  1 20:13:42 2005
@@ -0,0 +1,439 @@
+<!DOCTYPE view PUBLIC "-//Apache Software Foundation//DTD Shale Clay View//EN" "http://jakarta.apache.org/struts/dtds/clay-config_1_1.dtd">
+<view>
+	
+  <component jsfid="nameColumn" extends="column" id="name">
+    <element renderId="1" jsfid="outputText" facetName="header">
+      <attributes>
+        <set name="value" value="Contacts" />
+      </attributes>
+    </element> 
+       
+    <element renderId="2" jsfid="commandLink">
+      <attributes>
+        <set name="value" useValueLateBinding="true" value="#{e.name}" />
+        <set name="action" value="#{managed-bean-name.selectContact}" />
+        <set name="immediate" value="true"/>
+      </attributes>
+
+      <element renderId="1" jsfid="param">
+         <attributes>
+             <set name="name" value="selectedName"/>
+             <set name="value" useValueLateBinding="true" value="#{e.name}"/>
+         </attributes>    
+      </element>
+
+    </element>      
+  </component>	
+
+  <component jsfid="contactTable" extends="dataTable">
+    <attributes>
+      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.contactsForTab}"/>
+      <set name="var"   value="e"/>
+      <set name="rows"  value="100"/> 
+      <set name="first"  value="0"/> 
+      <set name="styleClass" value="contacts"/>
+      <set name="headerClass" value="contactsHeader"/>
+      <set name="rowClasses" value="contactsRow1, contactsRow2"/>
+      
+    </attributes>
+    <element renderId="1" jsfid="nameColumn"/>
+  </component>
+
+
+	<component jsfid="baseLabel" extends="outputLabel" allowBody="false">
+	   <attributes>
+	       <set name="style" value="color:#99CC66"/>
+	   </attributes>
+	</component>
+
+	<component jsfid="baseMessage" extends="message" allowBody="false">
+	   <attributes>
+	       <set name="style" value="color:red"/>
+	   </attributes>
+	</component>
+	
+	<component jsfid="cityLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="City:" />		
+			  <set name="for"   value="city" />
+		   </attributes>
+	</component>				
+	<component jsfid="city" extends="inputText" id="city"> 
+		   <attributes>
+		      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.city}" />		
+			  <set name="size" value="20" />
+			  <set name="maxlength" value="30" />
+			  <set name="required" value="true" />
+		   </attributes>
+	</component>
+	<component jsfid="cityMessage" extends="baseMessage" > 
+		   <attributes>
+		      <set name="for" value="city" />		
+		   </attributes>
+	</component>
+
+	<!-- province label, input field and message -->	
+	<component jsfid="provinceLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Province:" />		
+			  <set name="for"   value="province" />
+		   </attributes>
+	</component>				
+	<component jsfid="province" extends="inputText" id="province"> 
+		   <attributes>
+		      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.province}" />		
+			  <set name="size" value="20" />
+			  <set name="maxlength" value="30" />
+			  <set name="required" value="false" />
+		   </attributes>
+	</component>
+	<component jsfid="provinceMessage" extends="baseMessage" > 
+		   <attributes>
+		      <set name="for" value="province" />		
+		   </attributes>
+	</component>
+
+	<!-- state label, input field and message -->	
+	<component jsfid="stateLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="State:" />		
+			  <set name="for"   value="state" />
+		   </attributes>
+	</component>				
+	<component jsfid="state" extends="selectOneMenu" id="state"> 
+       <attributes>
+	      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.state}" />
+		  <set name="required" value="true" />	      
+ 	   </attributes>
+ 
+	   <element renderId="0" jsfid="selectItems"> 
+		   <attributes>
+		      <set name="value" useValueLateBinding="true" value="#{rolodexDao.states}" />
+ 	       </attributes>
+	   </element>
+
+	</component>
+	<component jsfid="stateMessage" extends="baseMessage"> 
+		   <attributes>
+		      <set name="for" value="state" />		
+		   </attributes>
+	</component>
+
+
+	<!-- country label, input field and message -->	
+	<component jsfid="countryLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Country:" />		
+			  <set name="for"   value="country" />
+		   </attributes>
+	</component>				
+	<component jsfid="country" extends="selectOneMenu" id="country"> 
+       <attributes>
+	      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.country}" />
+		  <set name="required" value="true" />	      
+ 	   </attributes>
+ 
+	   <element renderId="0" jsfid="selectItems"> 
+		   <attributes>
+		      <set name="value" useValueLateBinding="true" value="#{rolodexDao.countries}" />
+ 	       </attributes>
+	   </element>
+	</component>
+	<component jsfid="countryMessage" extends="baseMessage"> 
+		   <attributes>
+		      <set name="for" value="country" />		
+		   </attributes>
+	</component>
+
+
+
+	<!-- zip code label, input field and message -->
+	<component jsfid="zipLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Zip:" />		
+			  <set name="for"   value="zip" />
+		   </attributes>
+	</component>					
+	<component jsfid="zip" id="zip" extends="inputText"> 
+       <attributes>
+	      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.zip}" />
+		  <set name="maxlength" value="9" />
+		  <set name="size" value="5"/>
+		</attributes>	
+		<converter jsfid="integerConverter" />
+	</component> 
+	<component jsfid="zipMessage" extends="baseMessage"> 
+		   <attributes>
+		      <set name="for" value="zip" />		
+		   </attributes>
+	</component>
+
+    <!-- defines a field template type def for street address -->
+	<component jsfid="streetInput" extends="inputText">
+		<attributes>
+			<set name="size" value="35" />
+			<set name="maxlength" value="50" />
+			<set name="value" useValueLateBinding="true"/>
+		</attributes>
+    </component>
+
+	<!-- street 1 label, input field and message -->
+	<component jsfid="street1Label" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Street 1:" />		
+			  <set name="for"   value="street1" />
+		   </attributes>
+	</component>				
+	<component jsfid="street1" extends="streetInput" id="street1"> 
+        <attributes>
+		   <set name="value" value="#{managed-bean-name.street1}" />		
+		   <set name="required" value="false"  />		
+		</attributes>
+	</component>
+	<component jsfid="street1Message" extends="baseMessage"> 
+		   <attributes>
+		      <set name="for" value="street1" />		
+		   </attributes>
+	</component>
+	
+	<!-- street 2 label, input field and message -->
+	<component jsfid="street2Label" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Street 2:" />		
+			  <set name="for"   value="street2" />
+		   </attributes>
+	</component>				
+	<component jsfid="street2" extends="streetInput" id="street2"> 
+        <attributes>
+		   <set name="value" value="#{managed-bean-name.street2}" />		
+		   <set name="required" value="false"  />		
+		</attributes>
+	</component>
+	<component jsfid="street2Message" extends="baseMessage"> 
+		   <attributes>
+		      <set name="for" value="street2" />		
+		   </attributes>
+	</component>
+
+    <!-- base command button defining a common style class -->
+    <component jsfid="baseCommand" extends="commandButton">
+	   <attributes>
+	      <set name="styleClass" value="button" />		
+	   </attributes>
+    </component>
+
+    <!-- submit button to save a contact -->
+    <component jsfid="saveCommand" extends="baseCommand"> 
+	   <attributes>
+	      <set name="value" value="Save Contact" />		
+		  <set name="action" value="#{managed-bean-name.saveContact}"  />	
+	   </attributes>
+    </component>
+
+    <!-- submit button to delete a contact -->
+    <component jsfid="deleteCommand" extends="baseCommand"> 
+	   <attributes>
+	      <set name="value" value="Delete Contact" />		
+		  <set name="action" value="#{managed-bean-name.deleteContact}"  />	
+	   </attributes>
+    </component>
+
+
+
+    <!-- Concat Name -->
+	<component jsfid="nameLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Name:" />		
+			  <set name="for"   value="name" />
+		   </attributes>
+	</component>				
+	<component jsfid="name" extends="inputText" id="name"> 
+		   <attributes>
+		      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.name}" />		
+			  <set name="size" value="40" />
+			  <set name="maxlength" value="50" />
+			  <set name="required" value="true" />
+		   </attributes>
+	</component>
+	<component jsfid="nameMessage" extends="baseMessage" > 
+		   <attributes>
+		      <set name="for" value="name" />		
+		   </attributes>
+	</component>
+
+    <!-- Contact email address -->
+	<component jsfid="emailLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Email:" />		
+			  <set name="for"   value="email" />
+		   </attributes>
+	</component>				
+	<component jsfid="email" extends="inputText" id="email"> 
+		   <attributes>
+		      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.email}" />		
+			  <set name="size" value="30" />
+			  <set name="maxlength" value="50" />
+			  <set name="required" value="false" />
+		   </attributes>
+	</component>
+	<component jsfid="emailMessage" extends="baseMessage" > 
+		   <attributes>
+		      <set name="for" value="email" />		
+		   </attributes>
+	</component>
+
+    <!-- Contact residential Phone -->
+	<component jsfid="residentialPhoneLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Phone:" />		
+			  <set name="for"   value="residentialPhone" />
+		   </attributes>
+	</component>				
+	<component jsfid="residentialPhone" extends="inputText" id="residentialPhone"> 
+		   <attributes>
+		      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.residentialPhone}" />		
+			  <set name="size" value="20" />
+			  <set name="maxlength" value="50" />
+			  <set name="required" value="false" />
+		   </attributes>
+	</component>
+	<component jsfid="residentialPhoneMessage" extends="baseMessage" > 
+		   <attributes>
+		      <set name="for" value="residentialPhone" />		
+		   </attributes>
+	</component>
+
+    <!-- Contact business Phone -->
+	<component jsfid="businessPhoneLabel" extends="baseLabel"> 
+		   <attributes>
+			  <set name="value" value="Phone:" />		
+			  <set name="for"   value="businessPhone" />
+		   </attributes>
+	</component>				
+	<component jsfid="businessPhone" extends="inputText" id="businessPhone"> 
+		   <attributes>
+		      <set name="value" useValueLateBinding="true" value="#{managed-bean-name.businessPhone}" />		
+			  <set name="size" value="20" />
+			  <set name="maxlength" value="50" />
+			  <set name="required" value="false" />
+		   </attributes>
+	</component>
+	<component jsfid="businessPhoneMessage" extends="baseMessage" > 
+		   <attributes>
+		      <set name="for" value="businessPhone" />		
+		   </attributes>
+	</component>
+
+
+    <!-- address table contains 5 rows of three columns -->    
+	<component jsfid="addressPanel" extends="panelGrid">
+		<attributes>
+			<set name="columns" value="3" />
+		</attributes>
+
+		<element renderId="1" jsfid="street1Label"/>
+		<element renderId="2" jsfid="street1" />
+		<element renderId="3" jsfid="street1Message"/>
+
+		<element renderId="11" jsfid="street2Label"/>
+		<element renderId="12" jsfid="street2"/>
+		<element renderId="13" jsfid="street2Message"/>
+
+		<element renderId="21" jsfid="cityLabel"/>
+		<element renderId="22" jsfid="city"/>
+		<element renderId="23" jsfid="cityMessage"/>
+		 
+		<element renderId="31" jsfid="stateLabel"/>
+		<element renderId="32" jsfid="state"/>
+		<element renderId="33" jsfid="stateMessage"/>
+
+		<element renderId="41" jsfid="zipLabel"/>
+		<element renderId="42" jsfid="zip"/>
+		<element renderId="43" jsfid="zipMessage"/>
+		
+    </component>
+
+    <!-- foreign address panel adds province and country --> 
+	<component jsfid="foreignAddressPanel" extends="addressPanel"> 
+		<element renderId="34" jsfid="provinceLabel"/>
+		<element renderId="35" jsfid="province"/>
+		<element renderId="36" jsfid="provinceMessage"/>
+
+		<element renderId="51" jsfid="countryLabel"/>
+		<element renderId="52" jsfid="country"/>
+		<element renderId="53" jsfid="countryMessage"/>
+
+    </component>
+
+				
+
+    <!-- contact name and email panel-->    
+	<component jsfid="namePanel" extends="panelGrid">
+		<attributes>
+			<set name="columns" value="3" />
+		</attributes>
+
+		<element renderId="1" jsfid="nameLabel"/>
+		<element renderId="2" jsfid="name" />
+		<element renderId="3" jsfid="nameMessage"/>
+
+		<element renderId="4" jsfid="emailLabel"/>
+		<element renderId="5" jsfid="email" />
+		<element renderId="6" jsfid="emailMessage"/>
+
+    </component>
+
+    <!-- contact residential phone panel -->    
+	<component jsfid="residentialPhonePanel" extends="panelGrid">
+		<attributes>
+			<set name="columns" value="3" />
+		</attributes>
+
+		<element renderId="1" jsfid="residentialPhoneLabel"/>
+		<element renderId="2" jsfid="residentialPhone" />
+		<element renderId="3" jsfid="residentialPhoneMessage"/>
+
+    </component>
+
+    <!-- contact business phone panel -->    
+	<component jsfid="businessPhonePanel" extends="panelGrid">
+		<attributes>
+			<set name="columns" value="3" />
+		</attributes>
+
+		<element renderId="1" jsfid="businessPhoneLabel"/>
+		<element renderId="2" jsfid="businessPhone" />
+		<element renderId="3" jsfid="businessPhoneMessage"/>
+
+    </component>
+
+    <!-- command panel -->    
+	<component jsfid="commandPanel" extends="panelGrid">
+		<attributes>
+			<set name="columns" value="2" />
+		</attributes>
+
+		<element renderId="0" jsfid="baseCommand"> 
+	      <attributes>
+	         <set name="value" value="New Contact" />		
+		     <set name="action" value="#{managed-bean-name.newContact}"  />	
+             <set name="immediate" value="true"/>    
+	      </attributes>
+        </element>
+
+		<element renderId="1" jsfid="saveCommand">
+		   <attributes>
+              <set name="rendered" useValueLateBinding="true" value="#{!empty managed-bean-name.selectedContact}"/>
+		   </attributes>
+        </element>  
+
+		<element renderId="2" jsfid="deleteCommand">
+		   <attributes>
+              <set name="rendered" useValueLateBinding="true" value="#{!empty managed-bean-name.selectedContact}"/>
+		   </attributes>
+        </element>
+
+    </component>
+
+		
+</view>

Modified: struts/shale/trunk/use-cases/src/web/WEB-INF/faces-config.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/web/WEB-INF/faces-config.xml?rev=208818&r1=208817&r2=208818&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/src/web/WEB-INF/faces-config.xml (original)
+++ struts/shale/trunk/use-cases/src/web/WEB-INF/faces-config.xml Fri Jul  1 20:13:42 2005
@@ -267,6 +267,16 @@
       <from-outcome>usecases$toplevel</from-outcome>
       <to-view-id>/usecases.jsp</to-view-id>
     </navigation-case>
+
+    <navigation-case>
+      <from-outcome>rolodex$test</from-outcome>
+      <to-view-id>/rolodex/rolodex.jsp</to-view-id>
+    </navigation-case>
+    <navigation-case>
+      <from-outcome>rolodex$test</from-outcome>
+      <to-view-id>/rolodex/rolodex.jsp</to-view-id>
+    </navigation-case>
+     
   </navigation-rule>
 
   <navigation-rule>
@@ -478,6 +488,29 @@
       org.apache.shale.usecases.view.Domains
     </managed-bean-class>
     <managed-bean-scope>application</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <description>
+      This class simulates persistence storage loading 
+          domain data from the "dex.xml" file. 
+    </description>
+    <managed-bean-name>rolodexDao</managed-bean-name>
+    <managed-bean-class>
+      org.apache.shale.usecases.rolodex.RolodexDao
+    </managed-bean-class>
+    <managed-bean-scope>application</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <description>
+       View controller for the rolodex usecase
+    </description>
+    <managed-bean-name>rolodex</managed-bean-name>
+    <managed-bean-class>
+      org.apache.shale.usecases.rolodex.Rolodex
+    </managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
   </managed-bean>
 
 

Modified: struts/shale/trunk/use-cases/src/web/WEB-INF/web.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/web/WEB-INF/web.xml?rev=208818&r1=208817&r2=208818&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/src/web/WEB-INF/web.xml (original)
+++ struts/shale/trunk/use-cases/src/web/WEB-INF/web.xml Fri Jul  1 20:13:42 2005
@@ -43,6 +43,18 @@
     <param-name>contextConfigLocation</param-name>
     <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
   </context-param>
+  
+   <!-- Clay Configuration Resources -->
+   <context-param>
+      <param-name>clay-config-files</param-name>
+      <param-value>/WEB-INF/clay-config.xml</param-value>
+   </context-param>
+  
+   <!-- Clay template suffix override, default is .clay -->
+   <context-param>
+      <param-name>clay-template-suffix</param-name>
+      <param-value>.html</param-value>
+   </context-param>
 
   <!-- Shale Application Controller Filter -->
   <filter>
@@ -65,6 +77,11 @@
     </listener-class>
   </listener>
 MYFACES_END
+
+  <!-- Clay Configuration Listener -->
+  <listener>
+     <listener-class>org.apache.shale.clay.config.ClayConfigureListener</listener-class>
+  </listener>
 
   <!-- Commons Chain Configuration Listener -->
   <listener>

Added: struts/shale/trunk/use-cases/src/web/rolodex/rolodex.jsp
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/web/rolodex/rolodex.jsp?rev=208818&view=auto
==============================================================================
--- struts/shale/trunk/use-cases/src/web/rolodex/rolodex.jsp (added)
+++ struts/shale/trunk/use-cases/src/web/rolodex/rolodex.jsp Fri Jul  1 20:13:42 2005
@@ -0,0 +1,157 @@
+<%@page contentType="text/html;charset=UTF-8"%>
+<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
+<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
+<%@ taglib prefix="s" uri="http://struts.apache.org/shale/core"%>
+<%@ taglib prefix="clay"
+	uri="http://struts.apache.org/shale/clay-plugin"%>
+<html>
+<head>
+<title>Rolodex Example Using Clay</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<style type="text/css" media="screen">
+body {
+	margin : 10px;
+	font: Verdana, Helvetica, Arial;
+	padding: 0px;
+	background: #fff;
+}
+
+#menu {
+	border-bottom : 1px solid #ccc;
+	margin : 0;
+	padding-bottom : 19px;
+	padding-left : 10px;
+}
+
+#menu ul, #menu li	{
+	display : inline;
+	list-style-type : none;
+	margin : 0;
+	padding : 0;
+}
+
+	
+#menu a:link, #menu a:visited	{
+	background : #E8EBF0;
+	border : 1px solid #ccc;
+	color : #666;
+	float : left;
+	font-size : small;
+	font-weight : normal;
+	line-height : 14px;
+	margin-right : 8px;
+	padding : 2px 10px 2px 10px;
+	text-decoration : none;
+}
+
+#menu a:link.active, #menu a:visited.active	{
+	background : #fff;
+	border-bottom : 1px solid #fff;
+	color : #000;
+}
+
+#menu a:hover	{
+	color : #f00;
+}
+
+.contacts {
+   border: 1px solid #fff;
+}
+
+.contactsHeader {
+   text-align: center;
+   color: #99CC66;
+   background: #E5F2D9;   
+}
+
+.contactsRow2 {
+   text-align: left;
+   color: #99CC66;
+   background: #D9EEF2;   
+}
+
+.contactsRow1 {
+   text-align: left;
+   color: #99CC66;
+   background: #F1F7D4;   
+}
+	
+body.section-1 #menu li#nav-sel a {
+	background : #fff;
+	border-bottom : 1px solid #fff;
+	color : #000;
+}
+
+li#nav {
+	background : #red;
+	border-bottom : 1px solid #000;
+	color : #000;
+}
+
+#menu ul a:hover {
+	color : #f00 !important;
+}
+
+#contents {
+	background : #fff;
+	border : 1px solid #ccc;
+	border-top : none;
+	clear : both;
+	margin : 0px;
+	padding : 15px;
+}
+
+input.button {
+    width: 1in; 
+    text-align: center; 
+    color: #99CC66; 
+    font-size: 12px; 
+    font-style: normal; 
+    font-weight: bold
+}
+
+</style>
+
+
+</head>
+
+<f:view>
+	<body class="section-1">
+
+	<h:form>
+		<!-- Example of the runtime option.  The createTabs method binding event builds the tab links 
+            dynamically in the view controller -->
+
+		<clay:clay id="tabs" jsfid="RUNTIME"
+			shapeValidator="#{rolodex.createTabs}" managedBeanName="rolodex" />
+
+		<!-- Example of the xml composition option. -->
+		<div id="contents"><h:panelGrid columns="2">
+
+			<!-- A list of contacts to select from -->
+			<clay:clay id="contacts" jsfid="contactTable"
+				managedBeanName="rolodex" />
+
+			<h:panelGrid columns="2">
+				<clay:clay id="namePanel" jsfid="namePanel"
+					managedBeanName="rolodex.selectedContact" />
+				<clay:clay id="commandPanel" jsfid="commandPanel"
+					managedBeanName="rolodex" />
+				<h:outputText value="Residential Address:" style="color:#66B9CC"/>
+				<h:outputText value="Business Address:" style="color:#66B9CC"/>
+				<clay:clay id="address1" jsfid="addressPanel"
+					managedBeanName="rolodex.selectedContact.residentialAddress" />
+				<clay:clay id="address2" jsfid="foreignAddressPanel"
+					managedBeanName="rolodex.selectedContact.businessAddress" />
+				<clay:clay id="phone1" jsfid="residentialPhonePanel"
+					managedBeanName="rolodex.selectedContact" />
+				<clay:clay id="phone2" jsfid="businessPhonePanel"
+					managedBeanName="rolodex.selectedContact" />
+			</h:panelGrid>
+		</h:panelGrid></div>
+	</h:form>
+	</body>
+</f:view>
+</html>
+

Modified: struts/shale/trunk/use-cases/src/web/usecases.jsp
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/web/usecases.jsp?rev=208818&r1=208817&r2=208818&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/src/web/usecases.jsp (original)
+++ struts/shale/trunk/use-cases/src/web/usecases.jsp Fri Jul  1 20:13:42 2005
@@ -172,6 +172,18 @@
 
   </h:panelGrid>
 
+  <h1><h:outputText     value="#{messages['usecases.clay']}"/></h1>
+  <h:panelGrid        columns="1">
+
+    <h:commandLink         id="rolodex"
+                       action="rolodex$test">
+      <h:outputText     value="#{messages['usecases.rolodex']}"/>
+    
+    </h:commandLink>
+
+  </h:panelGrid>
+
+
  </h:form>
 
 </body>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org