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: 155420 $
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                             ActionTag.super.invokeBody(output);
103                         }
104                         catch (Exception e) {
105                             log.error( "Caught: " + e, e );
106                         }
107                     }
108                 };
109             }
110         }
111         return action;
112     }
113 	
114 	public void invokeBody(XMLOutput output) {
115 		// do nothing
116 	}
117 
118 
119     /***
120      * Either defines a variable or adds the current component to the parent
121      */
122     protected void processBean(String var, Object bean) throws JellyTagException {
123         if (var != null) {
124             context.setVariable(var, bean);
125         }
126         else {
127             ComponentTag tag = (ComponentTag) findAncestorWithClass( ComponentTag.class );
128             if ( tag != null ) {
129                 tag.setAction((Action) bean);
130             }
131             else {
132                 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" );
133             }
134         }
135     }
136 
137 
138     /***
139      * Perform the strange setting of Action properties using its custom API
140      */
141     protected void setBeanProperties(Object bean, Map attributes) throws JellyTagException {
142         Action action = getAction();
143 
144         String enabled = "enabled";
145         if (attributes.containsKey(enabled)) {
146             try {
147                 BeanUtils.copyProperty(action, enabled, attributes.get(enabled));
148             } catch (IllegalAccessException e) {
149                 throw new JellyTagException("Failed to set the enabled property.", e);
150             } catch (InvocationTargetException e) {
151                 throw new JellyTagException("Failed to set the enabled property.", e);
152             }
153 
154             attributes.remove(enabled);
155         }
156 
157         for ( Iterator iter = attributes.entrySet().iterator(); iter.hasNext(); ) {
158             Map.Entry entry = (Map.Entry) iter.next();
159             String name = (String) entry.getKey();
160 
161             // typically standard Action names start with upper case, so lets upper case it
162             name = capitalize(name);
163             Object value = entry.getValue();
164 
165             action.putValue( name, value );
166         }
167     }
168 
169 
170     protected String capitalize(String text) {
171         char ch = text.charAt(0);
172         if ( Character.isUpperCase( ch ) ) {
173             return text;
174         }
175         StringBuffer buffer = new StringBuffer(text.length());
176         buffer.append( Character.toUpperCase( ch ) );
177         buffer.append( text.substring(1) );
178         return buffer.toString();
179     }
180 
181 }