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 }