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 03:48:57 UTC

svn commit: r208811 - in /struts/shale/trunk/core-library/src/java/org/apache/shale/remote: AbstractListCompletions.java AbstractSelectItems.java BasicListCompletions.java BasicSelectItems.java EvaluateExpression.java

Author: craigmcc
Date: Fri Jul  1 18:48:55 2005
New Revision: 208811

URL: http://svn.apache.org/viewcvs?rev=208811&view=rev
Log:
Add convenience base classes and command implementations for building the
server side business logic for remoting (especially Ajax-style) requests.
Three families of facility are provided:

* EvaluateExpression -- evaluate a specified value binding expression,
  and store the result in the chain context under a specified attribute key.
  NOTE:  This cannot be used yet, until the core code establishes a JSF
  FacesContext for remote requests (since they do not flow through the
  FacesServlet.

* AbstractListCompletions / BasicListCompletions -- code used to return
  a String[] as an XML document with an outer element of <values>, and
  an inner element (one per array element) of <value> containing the
  specified values.  Optional testing against a request parameter (default
  test is a case-insensitive prefix match) can be used to filter the
  returned values.

* AbstractSelectItems / BasicSelectItems -- code used to return
  a SelectItem[] as an XML document with an outer element of <items>,
  an inner element <item> per item in the array, and inner subelements of
  <value>, <label>, and <description> from the properties of the
  corresponding SelectItem element.  Optional testing against a request
  parameter (default test is a case-insensitive prefix match against the
  "label" property) can be used to filter the returned values.

The latter two facilities support the (very common in Ajax type apps) use
cases where a dynamically calculated set of Strings, or a dynamically
calculated set of name/value pairs (represented as a SelectItem) need to
be acquired asynchronously via an XmlHttpRequest retrieval.

In these facilities, the AbstractXxx class can be directly subclasses,
with a single abstract method to implement, for a one-command implementation
of the business logic for a particular remote request.  The BasicXxx version
is designed to be used in a chain, where a previous command (often an
instance of EvaluateExpression) has been used to stash the required data
in a particular context attribute.




Added:
    struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractListCompletions.java
    struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractSelectItems.java
    struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicListCompletions.java
    struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicSelectItems.java
    struts/shale/trunk/core-library/src/java/org/apache/shale/remote/EvaluateExpression.java

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractListCompletions.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractListCompletions.java?rev=208811&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractListCompletions.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractListCompletions.java Fri Jul  1 18:48:55 2005
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2004-2005 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.
+ */
+
+package org.apache.shale.remote;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.shale.remote.RemoteContext;
+import org.apache.shale.remote.ResponseWrapper;
+
+/**
+ * <p>Convenience base class for remote commands that perform "code completion"
+ * style matching against a specified domain of strings, based on a specified
+ * matching test value (typically extracted from a request parameter) being
+ * compared to a set of legal values, and causing the selection of those that
+ * match.</p>
+ *
+ * $Id$
+ */
+
+public abstract class AbstractListCompletions implements Command {
+    
+    
+    // -------------------------------------------------------- Static Variables
+
+
+    /**
+     * <p>Default request parameter name used by the <code>test()</code>
+     * method to extract the comparison string.</p>
+     */
+    protected static final String PARAMETER = "prefix";
+    
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    // -------------------------------------------------------------- Properties
+
+
+    /**
+     * <p>Return the name of the inner element with which our response is
+     * created.  The default implementation returns <code>value</code>.</p>
+     */
+    protected String getInnerElement() {
+        return "value";
+    }
+
+
+    /**
+     * <p>Return the name of the outer element with which our response is
+     * created.  The default implementation returns <code>values</code>.</p>
+     */
+    protected String getOuterElement() {
+        return "values";
+    }
+
+
+    // --------------------------------------------------------- Command Methods
+
+
+    /**
+     * <p>Perform the appropriate matches, and return an XML document containing them.
+     * The default implementation uses the following protected methods:</p>
+     * <ul>
+     * <li><code>test()</code> to retrieve the test value for this request.</li>
+     * <li><code>legal()</code> to retrieve the legal values to be compared
+     *     against the test value.</li>
+     * <li><code>match()</code> to return the legal values that match the
+     *     test value.</li>
+     * <li><code>render()</code> to render the result as an XML document.</li>
+     * </ul>
+     *
+     * @param context {@link RemoteContext} for this request
+     */
+    public boolean execute(Context context) throws Exception {
+
+        RemoteContext rcontext = (RemoteContext) context;
+        String test = test(rcontext);
+        String legal[] = legal(rcontext, test);
+        String matches[] = match(rcontext, test, legal);
+        render(rcontext, matches);
+        return true; // Response is now complete
+
+    }
+
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * <p>Return the (possibly empty) set of legal values that are currently
+     * available, based on the specified test string.  This method is used
+     * by the default implementation of <code>match()</code>, but may be
+     * made unnecessary by a custom implementation of that method.</p>
+     *
+     * @param context {@link RemoteContext} for this request
+     * @param test Test value optionally used to select legal values
+     */
+    protected abstract String[] legal(RemoteContext context, String test);
+
+
+    /**
+     * <p>Return the (possibly empty) set of matches of the specified test string
+     * against the specified set of legal values.  By default, a case insensitive comparison
+     * to the beginning of each value is performed.  If no matches are found, a zero length
+     * array is returned.  If the test string is null or zero length, all legal
+     * values are considered to be matches.</p>
+     *
+     * @param context {@link RemoteContext} for this request
+     * @param test Test string to compare to the possible legal values
+     * @param legal Legal values that might be matched by the specified prefix
+     */
+    protected String[] match(RemoteContext context, String test, String legal[]) {
+
+        if ((test == null) || (test.length() == 0)) {
+            return legal;
+        }
+        if (legal == null) {
+            return new String[0];
+        }
+        List list = new ArrayList();
+        String match = test.toLowerCase();
+        for (int i = 0; i < legal.length; i++) {
+            if (legal[i].toLowerCase().startsWith(match)) {
+                list.add(legal[i]);
+            }
+        }
+        return (String[]) list.toArray(new String[list.size()]);
+
+    }
+
+
+    /**
+     * <p>Render an XML document response containing the specified matching
+     * values, representing each as an element whose name is returned by the
+     * <code>getInnerElement()</code> method.  The overall response is contained
+     * in an element whose name is returned by the <code>getOuterElement()</code>
+     * method.</p>
+     *
+     * @param context <code>RemoteContext</code> for the current request
+     * @param matches String values to be rendered
+     *
+     * @exception IOException if an input/output error occurs while rendering
+     */
+    protected void render(RemoteContext context, String matches[]) throws IOException {
+
+        // Set up the response we will create
+        context.setResponseContentType("text/xml");
+        context.setResponseEncoding("UTF-8");
+        ResponseWrapper wrapper =
+          new ResponseWrapper(context.getResponseWriter(), "UTF-8");
+        String inner = getInnerElement();
+        String outer = getOuterElement();
+
+        // Generate the response content
+        wrapper.startDocument();
+        wrapper.startElement(outer);
+        wrapper.writeNewline();
+        for (int i = 0; i < matches.length; i++) {
+            wrapper.startElement(inner);
+            if (matches[i] != null) {
+                wrapper.writeText(matches[i]);
+            }
+            wrapper.endElement(inner);
+            wrapper.writeNewline();
+        }
+        wrapper.endElement(outer);
+        wrapper.endDocument();
+
+    }
+
+
+    /**
+     * <p>Return the test value from the current context.  The default
+     * implementation uses a request parameter named by symbolic constant
+     * PARAMETER.  The returned value may be <code>null</code> if no such
+     * request parameter was included on this request.</p>
+     *
+     * @param context {@link RemoteContext} for the current request
+     */
+    protected String test(RemoteContext context) {
+
+        String prefixes[] =
+          (String[]) context.getRequestParameters().get(PARAMETER);
+        if (prefixes == null) {
+            prefixes = new String[0];
+        }
+        return (prefixes.length > 0) ? prefixes[0] : null;
+
+    }
+
+}

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractSelectItems.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractSelectItems.java?rev=208811&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractSelectItems.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/remote/AbstractSelectItems.java Fri Jul  1 18:48:55 2005
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2004-2005 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.
+ */
+
+package org.apache.shale.remote;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.faces.model.SelectItem;
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.shale.remote.RemoteContext;
+import org.apache.shale.remote.ResponseWrapper;
+
+/**
+ * <p>Convenience base class for remote commands that retrieve arrays
+ * of <code>SelectItem</code> beans, optionally filtered by matching the
+ * label against a test String, and rendering the result as an XML document.</p>
+ *
+ * $Id$
+ */
+
+public abstract class AbstractSelectItems implements Command {
+    
+    
+    // -------------------------------------------------------- Static Variables
+
+
+    /**
+     * <p>Default request parameter name used by the <code>test()</code>
+     * method to extract the comparison string.</p>
+     */
+    protected static final String PARAMETER = "prefix";
+    
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    // -------------------------------------------------------------- Properties
+
+
+    /**
+     * <p>Return the name of the inner element for the "description" property
+     * with which our response is created.  The default implementation
+     * returns <code>description</code>.</p>
+     */
+    protected String getInnerDescriptionElement() {
+        return "description";
+    }
+
+
+    /**
+     * <p>Return the name of the inner element for the "label" property
+     * with which our response is created.  The default implementation
+     * returns <code>label</code>.</p>
+     */
+    protected String getInnerLabelElement() {
+        return "label";
+    }
+
+
+    /**
+     * <p>Return the name of the inner element for the "value" property
+     * with which our response is created.  The default implementation
+     * returns <code>value</code>.</p>
+     */
+    protected String getInnerValueElement() {
+        return "value";
+    }
+
+
+    /**
+     * <p>Return the name of the inner element for the overall item
+     * with which our response is created.  The default implementation
+     * returns <code>item</code>.</p>
+     */
+    protected String getInnerElement() {
+        return "item";
+    }
+
+
+    /**
+     * <p>Return the name of the outer element with which our response is
+     * created.  The default implementation returns <code>items</code>.</p>
+     */
+    protected String getOuterElement() {
+        return "items";
+    }
+
+
+    // --------------------------------------------------------- Command Methods
+
+
+    /**
+     * <p>Perform the appropriate matches, and return an XML document containing them.
+     * The default implementation uses the following protected methods:</p>
+     * <ul>
+     * <li><code>test()</code> to retrieve the test value for this request.</li>
+     * <li><code>legal()</code> to retrieve the legal items to be compared
+     *     against the test value.</li>
+     * <li><code>match()</code> to return the legal items that match the
+     *     test value.</li>
+     * <li><code>render()</code> to render the result as an XML document.</li>
+     * </ul>
+     *
+     * @param context {@link RemoteContext} for this request
+     */
+    public boolean execute(Context context) throws Exception {
+
+        RemoteContext rcontext = (RemoteContext) context;
+        String test = test(rcontext);
+        SelectItem legal[] = legal(rcontext, test);
+        SelectItem matches[] = match(rcontext, test, legal);
+        render(rcontext, matches);
+        return true; // Response is now complete
+
+    }
+
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * <p>Return the (possibly empty) set of legal items that are currently
+     * available, based on the specified test string.  This method is used
+     * by the default implementation of <code>match()</code>, but may be
+     * made unnecessary by a custom implementation of that method.</p>
+     *
+     * @param context {@link RemoteContext} for this request
+     * @param test Test value optionally used to select legal values
+     */
+    protected abstract SelectItem[] legal(RemoteContext context, String test);
+
+
+    /**
+     * <p>Return the (possibly empty) set of matching items based on
+     * filtering the specified test string against the specified set of legal
+     * items.  By default, a case insensitive comparison of the test String
+     * to the beginning of each item's <code>label</code> is performed.
+     * If no matches are found, a zero length array is returned.  If the
+     * test string is null or zero length, all legal items are considered
+     * to be matches, and are returned.</p>
+     *
+     * @param context {@link RemoteContext} for this request
+     * @param test Test string to compare to the possible legal values
+     * @param legal Legal values that might be matched by the specified prefix
+     */
+    protected SelectItem[] match(RemoteContext context, String test, SelectItem legal[]) {
+
+        if ((test == null) || (test.length() == 0)) {
+            return legal;
+        }
+        if (legal == null) {
+            return new SelectItem[0];
+        }
+        List list = new ArrayList();
+        String match = test.toLowerCase();
+        for (int i = 0; i < legal.length; i++) {
+            if (legal[i].getLabel().toLowerCase().startsWith(match)) {
+                list.add(legal[i]);
+            }
+        }
+        return (SelectItem[]) list.toArray(new SelectItem[list.size()]);
+
+    }
+
+
+    /**
+     * <p>Render an XML document response containing the specified matching
+     * values, representing each as an element whose name is returned by the
+     * <code>getInnerElement()</code> method.  The overall response is contained
+     * in an element whose name is returned by the <code>getOuterElement()</code>
+     * method.</p>
+     *
+     * @param context <code>RemoteContext</code> for the current request
+     * @param matches String values to be rendered
+     *
+     * @exception IOException if an input/output error occurs while rendering
+     */
+    protected void render(RemoteContext context, SelectItem matches[]) throws IOException {
+
+        // Set up the response we will create
+        context.setResponseContentType("text/xml");
+        context.setResponseEncoding("UTF-8");
+        ResponseWrapper wrapper =
+          new ResponseWrapper(context.getResponseWriter(), "UTF-8");
+        String inner = getInnerElement();
+        String innerDescription = getInnerDescriptionElement();
+        String innerLabel = getInnerLabelElement();
+        String innerValue = getInnerValueElement();
+        String outer = getOuterElement();
+
+        // Generate the response content
+        wrapper.startDocument();
+        wrapper.startElement(outer);
+        wrapper.writeNewline();
+        for (int i = 0; i < matches.length; i++) {
+            if (matches[i] == null) {
+                continue;
+            }
+            wrapper.startElement(inner);
+            wrapper.writeNewline();
+            Object value = matches[i].getValue();
+            if (value != null) {
+                wrapper.startElement(innerValue);
+                wrapper.writeText(value.toString());
+                wrapper.endElement(innerValue);
+                wrapper.writeNewline();
+            }
+            String label = matches[i].getLabel();
+            if (label != null) {
+                wrapper.startElement(innerLabel);
+                wrapper.writeText(label);
+                wrapper.endElement(innerLabel);
+                wrapper.writeNewline();
+            }
+            String description = matches[i].getDescription();
+            if (description != null) {
+                wrapper.startElement(innerDescription);
+                wrapper.writeText(description);
+                wrapper.endElement(innerDescription);
+                wrapper.writeNewline();
+            }
+            wrapper.endElement(inner);
+            wrapper.writeNewline();
+        }
+        wrapper.endElement(outer);
+        wrapper.endDocument();
+
+    }
+
+
+    /**
+     * <p>Return the test value from the current context.  The default
+     * implementation uses a request parameter named by symbolic constant
+     * PARAMETER.  The returned value may be <code>null</code> if no such
+     * request parameter was included on this request.</p>
+     *
+     * @param context {@link RemoteContext} for the current request
+     */
+    protected String test(RemoteContext context) {
+
+        String prefixes[] =
+          (String[]) context.getRequestParameters().get(PARAMETER);
+        if (prefixes == null) {
+            prefixes = new String[0];
+        }
+        return (prefixes.length > 0) ? prefixes[0] : null;
+
+    }
+
+}

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicListCompletions.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicListCompletions.java?rev=208811&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicListCompletions.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicListCompletions.java Fri Jul  1 18:48:55 2005
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2004-2005 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.
+ */
+
+package org.apache.shale.remote;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.shale.remote.RemoteContext;
+import org.apache.shale.remote.ResponseWrapper;
+
+/**
+ * <p>Simple concrete subclass of {@link AbstractListCompletions} that
+ * assumes the array of <code>String</code> instances to be used
+ * has been stored in a specified context key.  The value of the context
+ * key to be used may be configured by calling <code>setAttributeKey()</code>,
+ * and defaults to the value of the manifest constant <code>ATTRIBUTE_KEY</code>.</p>
+ *
+ * $Id$
+ */
+
+public class BasicListCompletions extends AbstractListCompletions {
+    
+    
+    // -------------------------------------------------------- Static Variables
+
+
+    /**
+     * <p>Default attribute key under which we will look for an array
+     * of <code>String</code> instances.</p>
+     */
+    public static final String ATTRIBUTE_KEY = "strings";
+    
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    // -------------------------------------------------------------- Properties
+
+
+    /**
+     * <p>The attribute key used to look up the <code>String</code>s array.</p>
+     */
+    private String attributeKey = ATTRIBUTE_KEY;
+
+
+    /**
+     * <p>Return the attribute key used to look up the <code>String</code>s
+     * array.</p>
+     */
+    public String getAttributeKey() {
+
+        return attributeKey;
+
+    }
+
+
+    /**
+     * <p>Set the attribute key used to look up the <code>String</code>s
+     * array.</p>
+     *
+     * @param attributeKey The new attribute key
+     */
+    public void setAttributeKey(String attributeKey) {
+
+        this.attributeKey = attributeKey;
+
+    }
+
+
+    // --------------------------------------------- AbstractSelectItems Methods
+
+
+    /**
+     * <p>Return the (possibly empty) set of legal values that are currently
+     * available, based on the specified test string.  This method is used
+     * by the default implementation of <code>match()</code>, but may be
+     * made unnecessary by a custom implementation of that method.</p>
+     *
+     * <p>The default implementation expects a context attribute named
+     * by the value returned by <code>getAttributeKey()</code> to contain
+     * an array of <code>String</code> instances.  If there is no such
+     * defined attribute (or if it is not of type <code>String[]</code>),
+     * a zero-length array will be returned.</p>
+     *
+     * @param context {@link RemoteContext} for this request
+     * @param test Test value optionally used to select legal values
+     */
+    protected String[] legal(RemoteContext context, String test) {
+
+        try {
+            String items[] = (String[]) context.get(getAttributeKey());
+            if (items == null) {
+                items = new String[0];
+            }
+            return items;
+        } catch (ClassCastException e) {
+            return new String[0];
+        }
+
+    }
+
+
+}

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicSelectItems.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicSelectItems.java?rev=208811&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicSelectItems.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/remote/BasicSelectItems.java Fri Jul  1 18:48:55 2005
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2004-2005 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.
+ */
+
+package org.apache.shale.remote;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.faces.model.SelectItem;
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+import org.apache.shale.remote.RemoteContext;
+import org.apache.shale.remote.ResponseWrapper;
+
+/**
+ * <p>Simple concrete subclass of {@link AbstractSelectItems} that
+ * assumes the array of <code>SelectItem</code> instances to be used
+ * has been stored in a specified context key.  The value of the context
+ * key to be used may be configured by calling <code>setAttributeKey()</code>,
+ * and defaults to the value of the manifest constant <code>ATTRIBUTE_KEY</code>.</p>
+ *
+ * $Id$
+ */
+
+public class BasicSelectItems extends AbstractSelectItems {
+    
+    
+    // -------------------------------------------------------- Static Variables
+
+
+    /**
+     * <p>Default attribute key under which we will look for an array
+     * of <code>SelectItem</code> instances.</p>
+     */
+    public static final String ATTRIBUTE_KEY = "selectItems";
+    
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    // -------------------------------------------------------------- Properties
+
+
+    /**
+     * <p>The attribute key used to look up the <code>SelectItem</code>s array.</p>
+     */
+    private String attributeKey = ATTRIBUTE_KEY;
+
+
+    /**
+     * <p>Return the attribute key used to look up the <code>SelectItem</code>s
+     * array.</p>
+     */
+    public String getAttributeKey() {
+
+        return attributeKey;
+
+    }
+
+
+    /**
+     * <p>Set the attribute key used to look up the <code>SelectItem</code>s
+     * array.</p>
+     *
+     * @param attributeKey The new attribute key
+     */
+    public void setAttributeKey(String attributeKey) {
+
+        this.attributeKey = attributeKey;
+
+    }
+
+
+    // --------------------------------------------- AbstractSelectItems Methods
+
+
+    /**
+     * <p>Return the (possibly empty) set of legal items that are currently
+     * available, based on the specified test string.  This method is used
+     * by the default implementation of <code>match()</code>, but may be
+     * made unnecessary by a custom implementation of that method.</p>
+     *
+     * <p>The default implementation expects a context attribute named
+     * by the value returned by <code>getAttributeKey()</code> to contain
+     * an array of <code>SelectItem</code> instances.  If there is no such
+     * defined attribute (or if it is not of type <code>SelectItem[]</code>),
+     * a zero-length array will be returned.</p>
+     *
+     * @param context {@link RemoteContext} for this request
+     * @param test Test value optionally used to select legal values
+     */
+    protected SelectItem[] legal(RemoteContext context, String test) {
+
+        try {
+            SelectItem items[] = (SelectItem[]) context.get(getAttributeKey());
+            if (items == null) {
+                items = new SelectItem[0];
+            }
+            return items;
+        } catch (ClassCastException e) {
+            return new SelectItem[0];
+        }
+
+    }
+
+
+}

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/remote/EvaluateExpression.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/remote/EvaluateExpression.java?rev=208811&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/remote/EvaluateExpression.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/remote/EvaluateExpression.java Fri Jul  1 18:48:55 2005
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2004-2005 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.
+ */
+
+package org.apache.shale.remote;
+
+import java.io.IOException;
+import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
+import org.apache.commons.chain.Command;
+import org.apache.commons.chain.Context;
+
+/**
+ * <p>Evaluate the specified value binding expression, and store the resulting
+ * value as a context attribute under the specified attribute key.</p>
+ *
+ * $Id$
+ */
+
+public class EvaluateExpression implements Command {
+    
+    
+    // -------------------------------------------------------------- Properties
+
+
+    /**
+     * <p>The attribute key used to store the evaluated expression value.</p.
+     */
+    private String attributeKey = null;
+
+
+    /**
+     * <p>Return the attribute key used to store the evaluated expression
+     * value.</p>
+     */
+    public String getAttributeKey() {
+
+        return attributeKey;
+
+    }
+
+
+    /**
+     * <p>Set the attribute key used to store the evaluated expression
+     * value.</p>
+     *
+     * @param attributeKey The new attribute key
+     */
+    public void setAttributeKey(String attributeKey) {
+
+        this.attributeKey = attributeKey;
+
+    }
+
+
+    /**
+     * <p>The value binding expression (including delimiters) to be evaluated.</p>
+     */
+    private String expression = null;
+
+
+    /**
+     * <p>Return the value binding expression (including delimiters) to be
+     * evaluated.</p>
+     */
+    public String getExpression() {
+
+        return this.expression;
+
+    }
+
+
+    /**
+     * <p>Set the value binding expression (including delimiters) to be
+     * evaluated.</p>
+     *
+     * @param expression The new value binding expression (including delimiters)
+     */
+    public void setExpression(String expression) {
+
+        this.expression = expression;
+
+    }
+
+
+    // --------------------------------------------------------- Command Methods
+
+
+    /**
+     * <p>Evaluate the specified expression, and store the result in the
+     * specified attribute.  Return <code>false</code> so that the
+     * current chain will continue.</p>
+     *
+     * @param context <code>Context</code> for the current request
+     *
+     * @exception Exception if an exception is thrown during execution
+     */
+    public boolean execute(Context context) throws Exception {
+
+        FacesContext fcontext = FacesContext.getCurrentInstance();
+        ValueBinding vb = fcontext.getApplication().createValueBinding(getExpression());
+        context.put(getAttributeKey(), vb.getValue(fcontext));
+        return false; // Let the current chain continue
+
+    }
+
+
+}



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