001: /*
002: * Copyright 2002,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: package org.apache.commons.jelly.tags.core;
017:
018: import java.lang.reflect.InvocationTargetException;
019: import java.util.Map;
020:
021: import org.apache.commons.beanutils.BeanUtils;
022: import org.apache.commons.jelly.JellyTagException;
023: import org.apache.commons.jelly.TagSupport;
024: import org.apache.commons.jelly.XMLOutput;
025: import org.apache.commons.jelly.expression.Expression;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028:
029: /** A tag which sets a variable from the result of an expression
030: *
031: * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
032: * @version $Revision: 155420 $
033: */
034: public class SetTag extends TagSupport {
035:
036: /** The Log to which logging calls will be made. */
037: private static final Log log = LogFactory.getLog(SetTag.class);
038:
039: /** The variable name to export. */
040: private String var;
041:
042: /** The variable scope to export */
043: private String scope;
044:
045: /** The expression to evaluate. */
046: private Expression value;
047:
048: /** The default value */
049: private Expression defaultValue;
050:
051: /** The target object on which to set a property. */
052: private Object target;
053:
054: /** The name of the property to set on the target object. */
055: private String property;
056:
057: /** Should we XML encode the body of this tag as text? */
058: private boolean encode = true;
059:
060: public SetTag() {
061: }
062:
063: // Tag interface
064: //-------------------------------------------------------------------------
065: public void doTag(XMLOutput output) throws JellyTagException {
066: // perform validation up front to fail fast
067: if (var != null) {
068: if (target != null || property != null) {
069: throw new JellyTagException(
070: "The 'target' and 'property' attributes cannot be used in combination with the 'var' attribute");
071: }
072: } else {
073: if (target == null) {
074: throw new JellyTagException(
075: "Either a 'var' or a 'target' attribute must be defined for this tag");
076: }
077: if (property == null) {
078: throw new JellyTagException(
079: "The 'target' attribute requires the 'property' attribute");
080: }
081: }
082:
083: Object answer = null;
084: if (value != null) {
085: answer = value.evaluate(context);
086: if (defaultValue != null && isEmpty(answer)) {
087: answer = defaultValue.evaluate(context);
088: }
089: } else {
090: answer = getBodyText(isEncode());
091: }
092:
093: if (var != null) {
094: if (scope != null) {
095: context.setVariable(var, scope, answer);
096: } else {
097: context.setVariable(var, answer);
098: }
099: } else {
100: setPropertyValue(target, property, answer);
101: }
102: }
103:
104: // Properties
105: //-------------------------------------------------------------------------
106: /** Sets the variable name to define for this expression
107: */
108: public void setVar(String var) {
109: this .var = var;
110: }
111:
112: /**
113: * Sets the variable scope for this variable. For example setting this value to 'parent' will
114: * set this value in the parent scope. When Jelly is run from inside a Servlet environment
115: * then other scopes will be available such as 'request', 'session' or 'application'.
116: *
117: * Other applications may implement their own custom scopes.
118: */
119: public void setScope(String scope) {
120: this .scope = scope;
121: }
122:
123: /** Sets the expression to evaluate. */
124: public void setValue(Expression value) {
125: this .value = value;
126: }
127:
128: /**
129: * Sets the default value to be used if the value exprsesion results
130: * in a null value or blank String
131: */
132: public void setDefaultValue(Expression defaultValue) {
133: this .defaultValue = defaultValue;
134: }
135:
136: /** Sets the target object on which to set a property. */
137: public void setTarget(Object target) {
138: this .target = target;
139: }
140:
141: /** Sets the name of the property to set on the target object. */
142: public void setProperty(String property) {
143: this .property = property;
144: }
145:
146: /**
147: * Returns whether the body of this tag will be XML encoded or not.
148: */
149: public boolean isEncode() {
150: return encode;
151: }
152:
153: /**
154: * Sets whether the body of the tag should be XML encoded as text (so that < and > are
155: * encoded as &lt; and &gt;) or leave the text as XML which is the default.
156: * This is only used if this tag is specified with no value so that the text body of this
157: * tag is used as the body.
158: */
159: public void setEncode(boolean encode) {
160: this .encode = encode;
161: }
162:
163: // Implementation methods
164: //-------------------------------------------------------------------------
165: protected void setPropertyValue(Object target, String property,
166: Object value) {
167: try {
168: if (target instanceof Map) {
169: Map map = (Map) target;
170: map.put(property, value);
171: } else {
172: BeanUtils.setProperty(target, property, value);
173: }
174: } catch (InvocationTargetException e) {
175: log.error("Failed to set the property: " + property
176: + " on bean: " + target + " to value: " + value
177: + " due to exception: " + e, e);
178: } catch (IllegalAccessException e) {
179: log.error("Failed to set the property: " + property
180: + " on bean: " + target + " to value: " + value
181: + " due to exception: " + e, e);
182: }
183: }
184:
185: /**
186: * @param value
187: * @return true if the given value is null or an empty String
188: */
189: protected boolean isEmpty(Object value) {
190: if (value == null) {
191: return true;
192: }
193: if (value instanceof String) {
194: String s = (String) value;
195: return s.length() == 0;
196: }
197: return false;
198: }
199:
200: }
|