View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.jelly.tags.swing;
17  
18  import java.awt.event.ActionEvent;
19  import java.lang.reflect.InvocationTargetException;
20  import java.util.Iterator;
21  import java.util.Map;
22  
23  import javax.swing.AbstractAction;
24  import javax.swing.Action;
25  
26  import org.apache.commons.beanutils.BeanUtils;
27  import org.apache.commons.jelly.JellyTagException;
28  import org.apache.commons.jelly.MissingAttributeException;
29  import org.apache.commons.jelly.XMLOutput;
30  import org.apache.commons.jelly.tags.core.UseBeanTag;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  /***
35   * Creates a Swing Action which on invocation will execute the body of this tag.
36   * The Action is then output as a variable for reuse if the 'var' attribute is specified
37   * otherwise the action is added to the parent JellySwing widget.
38   *
39   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
40   * @version $Revision: 1.7 $
41   */
42  public class ActionTag extends UseBeanTag {
43  
44      /*** The Log to which logging calls will be made. */
45      private static final Log log = LogFactory.getLog(ActionTag.class);
46  
47      public ActionTag() {
48      }
49  
50  
51      // Properties
52      //-------------------------------------------------------------------------
53  
54      /***
55       * @return the Action object for this tag
56       */
57      public Action getAction() {
58          return (Action) getBean();
59      }
60  
61  
62      // Implementation methods
63      //-------------------------------------------------------------------------
64  
65  
66      /***
67       * An existing Action could be specified via the 'action' attribute or an action class
68       * may be specified via the 'class' attribute, otherwise a default Action class is created.
69       */
70      protected Class convertToClass(Object classObject) throws MissingAttributeException, ClassNotFoundException {
71          if (classObject == null) {
72              return null;
73          }
74          else {
75              return super.convertToClass(classObject);
76          }
77      }
78  
79      /***
80       * An existing Action could be specified via the 'action' attribute or an action class
81       * may be specified via the 'class' attribute, otherwise a default Action class is created.
82       */
83      protected Object newInstance(Class theClass, Map attributes, final XMLOutput output) throws JellyTagException {
84          Action action = (Action) attributes.remove( "action" );
85          if ( action == null ) {
86              if (theClass != null ) {
87  
88                  try {
89                      return theClass.newInstance();
90                  } catch (InstantiationException e) {
91                      throw new JellyTagException(e);
92                  } catch (IllegalAccessException e) {
93                      throw new JellyTagException(e);
94                  }
95  
96              }
97              else {
98                  action = new AbstractAction() {
99                      public void actionPerformed(ActionEvent event) {
100                         context.setVariable( "event", event );
101                         try {
102                             invokeBody(output);
103                         }
104                         catch (Exception e) {
105                             log.error( "Caught: " + e, e );
106                         }
107                     }
108                 };
109             }
110         }
111         return action;
112     }
113 
114 
115     /***
116      * Either defines a variable or adds the current component to the parent
117      */
118     protected void processBean(String var, Object bean) throws JellyTagException {
119         if (var != null) {
120             context.setVariable(var, bean);
121         }
122         else {
123             ComponentTag tag = (ComponentTag) findAncestorWithClass( ComponentTag.class );
124             if ( tag != null ) {
125                 tag.setAction((Action) bean);
126             }
127             else {
128                 throw new JellyTagException( "Either the 'var' attribute must be specified to export this Action or this tag must be nested within a JellySwing widget tag" );
129             }
130         }
131     }
132 
133 
134     /***
135      * Perform the strange setting of Action properties using its custom API
136      */
137     protected void setBeanProperties(Object bean, Map attributes) throws JellyTagException {
138         Action action = getAction();
139 
140         String enabled = "enabled";
141         if (attributes.containsKey(enabled)) {
142             try {
143                 BeanUtils.copyProperty(action, enabled, attributes.get(enabled));
144             } catch (IllegalAccessException e) {
145                 throw new JellyTagException("Failed to set the enabled property.", e);
146             } catch (InvocationTargetException e) {
147                 throw new JellyTagException("Failed to set the enabled property.", e);
148             }
149 
150             attributes.remove(enabled);
151         }
152 
153         for ( Iterator iter = attributes.entrySet().iterator(); iter.hasNext(); ) {
154             Map.Entry entry = (Map.Entry) iter.next();
155             String name = (String) entry.getKey();
156 
157             // typically standard Action names start with upper case, so lets upper case it
158             name = capitalize(name);
159             Object value = entry.getValue();
160 
161             action.putValue( name, value );
162         }
163     }
164 
165 
166     protected String capitalize(String text) {
167         char ch = text.charAt(0);
168         if ( Character.isUpperCase( ch ) ) {
169             return text;
170         }
171         StringBuffer buffer = new StringBuffer(text.length());
172         buffer.append( Character.toUpperCase( ch ) );
173         buffer.append( text.substring(1) );
174         return buffer.toString();
175     }
176 
177 }