001    /*
002     * Copyright 1999-2001,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */ 
016    
017    package org.apache.commons.workflow.base;
018    
019    
020    import java.util.EmptyStackException;
021    import org.apache.commons.jxpath.JXPathContext;
022    import org.apache.commons.workflow.Context;
023    import org.apache.commons.workflow.Descriptor;
024    
025    
026    /**
027     * <p>Basic implementation of the <strong>Descriptor</strong> interface.</p>
028     *
029     * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $
030     * @author Craig R. McClanahan
031     */
032    
033    public class BaseDescriptor implements Descriptor {
034    
035    
036        // ----------------------------------------------------------- Constructors
037    
038    
039        /**
040         * Create an instance with default values.
041         */
042        public BaseDescriptor() {
043    
044            super();
045    
046        }
047    
048    
049        /**
050         * Create an instance with the specified values.
051         *
052         * @param xpath The XPath reference expression
053         */
054        public BaseDescriptor(String xpath) {
055    
056            this(null, null, xpath, null);
057    
058        }
059    
060    
061        /**
062         * Create an instance with the specified values.
063         *
064         * @param xpath The XPath reference expression
065         * @param type The expected class of this object
066         */
067        public BaseDescriptor(String xpath, Class type) {
068    
069            this(null, null, xpath, type);
070    
071        }
072    
073    
074        /**
075         * Create an instance with the specified values.
076         *
077         * @param name The object name
078         * @param scope The object scope
079         */
080        public BaseDescriptor(String name, String scope) {
081    
082            this(name, scope, null, null);
083    
084        }
085    
086    
087        /**
088         * Create an instance with the specified values.
089         *
090         * @param name The object name
091         * @param scope The object scope
092         * @param type The expected class of this object
093         */
094        public BaseDescriptor(String name, String scope, Class type) {
095    
096            this(name, scope, null, type);
097    
098        }
099    
100    
101        /**
102         * Create an instance with the specified values.
103         *
104         * @param name The object name
105         * @param scope The object scope
106         * @param xpath The XPath reference expression
107         * @param type The expected class
108         */
109        public BaseDescriptor(String name, String scope,
110                              String xpath, Class type) {
111    
112            super();
113            setName(name);
114            setScope(scope);
115            setXpath(xpath);
116            setType(type);
117    
118        }
119    
120    
121        // ----------------------------------------------------- Instance Variables
122    
123    
124        /**
125         * The name of the Java object (in some scope).
126         */
127        protected String name = null;
128    
129    
130        /**
131         * The scope of the Java object.
132         */
133        protected String scope = null;
134    
135    
136        /**
137         * The optional Java class expected by this Descriptor.
138         */
139        protected Class type = null;
140    
141    
142        /**
143         * The XPath expression used to access the Java object.
144         */
145        protected String xpath = null;
146    
147    
148        // ------------------------------------------------------------- Properties
149    
150    
151        /**
152         * Return the name of the Java object (in some scope) referenced by
153         * this Descriptor.
154         */
155        public String getName() {
156    
157            return (this.name);
158    
159        }
160    
161    
162        /**
163         * Set the name of the Java object (in some scope) referenced by
164         * this Descriptor.
165         *
166         * @param name The new object name
167         */
168        public void setName(String name) {
169    
170            this.name = name;
171    
172        }
173    
174    
175        /**
176         * Return the scope of the Java object referenced by this Descriptor.
177         */
178        public String getScope() {
179    
180            return (this.scope);
181    
182        }
183    
184    
185        /**
186         * Set the scope of the Java object referenced by this Descriptor.
187         *
188         * @param scope The new scope name
189         */
190        public void setScope(String scope) {
191    
192            this.scope = scope;
193    
194        }
195    
196    
197        /**
198         * Return the optional Java class expected by this Descriptor.
199         */
200        public Class getType() {
201    
202            return (this.type);
203    
204        }
205    
206    
207        /**
208         * Set the optional Java class expected by this Descriptor.
209         *
210         * @param type The new expected type
211         */
212        public void setType(Class type) {
213    
214            this.type = type;
215    
216        }
217    
218    
219        /**
220         * Return the XPath expression used to access the Java object
221         * referenced by this Descriptor.
222         */
223        public String getXpath() {
224    
225            return (this.xpath);
226    
227        }
228    
229    
230        /**
231         * Set the XPath expression used to access the Java object
232         * referenced by this Descriptor.
233         *
234         * @param xpath The new XPath expression
235         */
236        public void setXpath(String xpath) {
237    
238            this.xpath = xpath;
239    
240        }
241    
242    
243        // --------------------------------------------------------- Public Methods
244    
245    
246        /**
247         * Return the value specified by this Descriptor from the specified
248         * Context.  If there is no such value, return <code>null</code>.
249         *
250         * @param context Context from which to retrieve this value
251         */
252        public Object get(Context context) {
253    
254            if (xpath != null) {
255                JXPathContext jpc = context.getJXPathContext();
256                jpc.setLenient(true);
257                return (jpc.getValue("local/" + xpath));
258            } else if (name != null) {
259                if (scope == null)
260                    return (context.get(name));
261                else {
262                    int scopeId = context.getScopeId(scope);
263                    return (context.get(name, scopeId));
264                }
265            } else {
266                try {
267                    return (context.pop());
268                } catch (EmptyStackException e) {
269                    return (null);
270                }
271            }
272    
273        }
274    
275    
276        /**
277         * <p>Call <code>get()</code> to retrieve the value specified by this
278         * Descriptor, and then return <code>true</code> if this value represents
279         * a positive result; otherwise return <code>false</code>.  A positive
280         * result depends on the data type of the retrieved value:</p>
281         * <ul>
282         * <li>Value returned is a <code>String</code> of length greater than 0.
283         *     </li>
284         * <li>Value is a Boolean "true"</code>.</li>
285         * <li>Value is a numeric primitive (byte, char, float, double, int,
286         *     long, short), or an Object wrapper for one of these types, and
287         *     the corresponding value is non-zero.</li>
288         * <li>Value returned is a non-null Object.</li>
289         * </ul>
290         *
291         * @param context Context from which to retrieve this value
292         */
293        public boolean positive(Context context) {
294    
295            Object value = get(context);
296            if (value == null)
297                return (false);
298            else if (value instanceof Boolean)
299                return (((Boolean) value).booleanValue());
300            else if (value instanceof Byte)
301                return (((Byte) value).byteValue() != (byte) 0);
302            else if (value instanceof Character)
303                return (((Character) value).charValue() != (char) 0);
304            else if (value instanceof Double)
305                return (((Double) value).doubleValue() != (double) 0.0);
306            else if (value instanceof Float)
307                return (((Double) value).floatValue() != (float) 0.0);
308            else if (value instanceof Integer)
309                return (((Integer) value).intValue() != (int) 0);
310            else if (value instanceof Long)
311                return (((Long) value).longValue() != (long) 0);
312            else if (value instanceof Short)
313                return (((Short) value).shortValue() != (short) 0);
314            else if (value instanceof String)
315                return (((String) value).length() > 0);
316            else
317                return (true); // Non-null object
318    
319    
320        }
321    
322    
323        /**
324         * Store the value into the destination specified by this Descriptor
325         * in the specified Context, replacing any existing value.
326         *
327         * @param context Context into which to store this value
328         * @param value Object value to be stored
329         */
330        public void put(Context context, Object value) {
331    
332            if (xpath != null) {
333                JXPathContext jpc = context.getJXPathContext();
334                jpc.setValue("local/" + xpath, value);
335            } else {
336                if (scope == null)
337                    context.put(name, value);
338                else {
339                    int scopeId = context.getScopeId(scope);
340                    context.put(name, value, scopeId);
341                }
342            }
343    
344        }
345    
346    
347        /**
348         * Remove any existing value associated with this Descriptor from the
349         * specified Context.
350         *
351         * @param context Context from which to remove this value.
352         */
353        public void remove(Context context) {
354    
355            if (xpath != null) {
356                throw new IllegalStateException("Cannot 'remove' throw xpath");
357            } else {
358                if (scope == null)
359                    context.remove(name);
360                else {
361                    int scopeId = context.getScopeId(scope);
362                    context.remove(name, scopeId);
363                }
364            }
365    
366        }
367    
368    
369        /**
370         * Render a printable version of this object.
371         */
372        public String toString() {
373    
374            StringBuffer sb = new StringBuffer("<descriptor");
375            if (xpath != null) {
376                sb.append(" xpath=\"");
377                sb.append(xpath);
378                sb.append("\"");
379            }
380            if (name != null) {
381                sb.append(" name=\"");
382                sb.append(name);
383                sb.append("\"");
384            }
385            if (scope != null) {
386                sb.append(" scope=\"");
387                sb.append(scope);
388                sb.append("\"");
389            }
390            sb.append("/>");
391            return (sb.toString());
392    
393        }
394    
395    
396    }