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.impl;
017:
018: import java.util.HashSet;
019: import java.util.Iterator;
020: import java.util.Map;
021: import java.util.Set;
022:
023: import org.apache.commons.beanutils.DynaClass;
024: import org.apache.commons.jelly.DynaBeanTagSupport;
025: import org.apache.commons.jelly.JellyTagException;
026: import org.apache.commons.jelly.MissingAttributeException;
027: import org.apache.commons.jelly.XMLOutput;
028: import org.apache.commons.jelly.expression.Expression;
029:
030: /**
031: * This tag is bound onto a {@link DynaClass} instance.
032: * When the tag is invoked a {@link DynaBean will be created using the tags attributes.
033: * So this class is like a {@link DynaBean} implemenation of {@link DynamicBeanTag}
034: *
035: * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
036: * @version $Revision: 155420 $
037: */
038: public class DynamicDynaBeanTag extends DynaBeanTagSupport implements
039: BeanSource {
040:
041: /** the bean class */
042: private DynaClass beanClass;
043:
044: /**
045: * the tag attribute name that is used to declare the name
046: * of the variable to export after running this tag
047: */
048: private String variableNameAttribute;
049:
050: /** the current variable name that the bean should be exported as */
051: private String var;
052:
053: /** the set of attribute names we've already set */
054: private Set setAttributesSet = new HashSet();
055:
056: /** the attribute definitions */
057: private Map attributes;
058:
059: public DynamicDynaBeanTag(DynaClass beanClass, Map attributes,
060: String variableNameAttribute) {
061: this .beanClass = beanClass;
062: this .attributes = attributes;
063: this .variableNameAttribute = variableNameAttribute;
064: }
065:
066: public void beforeSetAttributes() throws JellyTagException {
067: // create a new dynabean before the attributes are set
068: try {
069: setDynaBean(beanClass.newInstance());
070: } catch (IllegalAccessException e) {
071: throw new JellyTagException(
072: "Could not instantiate dynabean", e);
073: } catch (InstantiationException e) {
074: throw new JellyTagException(
075: "Could not instantiate dynabean", e);
076: }
077:
078: setAttributesSet.clear();
079: }
080:
081: public void setAttribute(String name, Object value)
082: throws JellyTagException {
083: boolean isVariableName = false;
084: if (variableNameAttribute != null) {
085: if (variableNameAttribute.equals(name)) {
086: if (value == null) {
087: var = null;
088: } else {
089: var = value.toString();
090: }
091: isVariableName = true;
092: }
093: }
094: if (!isVariableName) {
095:
096: // #### strictly speaking we could
097: // know what attributes are specified at compile time
098: // so this dynamic set is unnecessary
099: setAttributesSet.add(name);
100:
101: // we could maybe implement attribute specific validation here
102:
103: super .setAttribute(name, value);
104: }
105: }
106:
107: // Tag interface
108: //-------------------------------------------------------------------------
109: public void doTag(XMLOutput output) throws JellyTagException {
110:
111: // lets find any attributes that are not set and
112: for (Iterator iter = attributes.values().iterator(); iter
113: .hasNext();) {
114: Attribute attribute = (Attribute) iter.next();
115: String name = attribute.getName();
116: if (!setAttributesSet.contains(name)) {
117: if (attribute.isRequired()) {
118: throw new MissingAttributeException(name);
119: }
120: // lets get the default value
121: Object value = null;
122: Expression expression = attribute.getDefaultValue();
123: if (expression != null) {
124: value = expression.evaluate(context);
125: }
126:
127: // only set non-null values?
128: if (value != null) {
129: super .setAttribute(name, value);
130: }
131: }
132: }
133:
134: invokeBody(output);
135:
136: // export the bean if required
137: if (var != null) {
138: context.setVariable(var, getDynaBean());
139: }
140: }
141:
142: // Properties
143: //-------------------------------------------------------------------------
144: /**
145: * @return the bean that has just been created
146: */
147: public Object getBean() {
148: return getDynaBean();
149: }
150: }
|