001 // Copyright May 20, 2006 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014 package org.apache.tapestry.event;
015
016 import org.apache.hivemind.ApplicationRuntimeException;
017 import org.apache.hivemind.util.Defense;
018 import org.apache.tapestry.IRequestCycle;
019 import org.apache.tapestry.json.JSONArray;
020
021 import java.text.ParseException;
022 import java.util.Arrays;
023 import java.util.HashMap;
024 import java.util.Map;
025
026
027 /**
028 * Represents a client side generated browser event.
029 */
030 public class BrowserEvent
031 {
032 public static final String NAME = "beventname";
033 public static final String TYPE = "beventtype";
034 public static final String KEYS = "beventkeys";
035 public static final String CHAR_CODE = "beventcharCode";
036 public static final String PAGE_X = "beventpageX";
037 public static final String PAGE_Y = "beventpageY";
038 public static final String LAYER_X = "beventlayerX";
039 public static final String LAYER_Y = "beventlayerY";
040
041 public static final String TARGET = "beventtarget";
042 public static final String TARGET_ATTR_ID = "id";
043 public static final String COMPONENT_ID = "bcomponentid";
044 public static final String COMPONENT_ID_PATH = "bcomponentidpath";
045
046 public static final String METHOD_ARGUMENTS = "methodArguments";
047
048 private String _name;
049 private String _type;
050 private String[] _keys;
051 private String _charCode;
052 private String _pageX;
053 private String _pageY;
054 private String _layerX;
055 private String _layerY;
056 private EventTarget _target;
057 private String _componentId;
058 private String _componentIdPath;
059
060 private String _methodArguments;
061 private JSONArray _methodArgumentsArray;
062
063 /**
064 * Creates a new browser event that will extract its own
065 * parameters.
066 *
067 * @param cycle
068 * The request cycle to extract parameters from.
069 */
070 public BrowserEvent(IRequestCycle cycle)
071 {
072 Defense.notNull(cycle, "cycle");
073
074 _name = cycle.getParameter(NAME);
075 _type = cycle.getParameter(TYPE);
076 _keys = cycle.getParameters(KEYS);
077 _charCode = cycle.getParameter(CHAR_CODE);
078 _pageX = cycle.getParameter(PAGE_X);
079 _pageY = cycle.getParameter(PAGE_Y);
080 _layerX = cycle.getParameter(LAYER_X);
081 _layerY = cycle.getParameter(LAYER_Y);
082 _componentId = cycle.getParameter(COMPONENT_ID);
083 _componentIdPath = cycle.getParameter(COMPONENT_ID_PATH);
084
085 Map props = new HashMap();
086 _target = new EventTarget(props);
087
088 String targetId = cycle.getParameter(TARGET + "." + TARGET_ATTR_ID);
089 if (targetId != null)
090 {
091 props.put(TARGET_ATTR_ID, targetId);
092 }
093
094 _methodArguments = cycle.getParameter(METHOD_ARGUMENTS);
095 }
096
097 /**
098 * Creates a new browser event with the specified
099 * name/target properties.
100 *
101 * @param name The name of the event, ie "onClick", "onBlur", etc..
102 * @param target The target of the client side event.
103 */
104 public BrowserEvent(String name, EventTarget target)
105 {
106 this(name, null, null, target);
107 }
108
109 /**
110 * Creates a new browser event with the specified
111 * name/target properties.
112 *
113 * <p>Currently used for testing only.</p>
114 *
115 * @param name The name of the event, ie "onClick", "onBlur", etc..
116 * @param componentId Component targeted.
117 * @param componentIdPath The id path of the component.
118 * @param target The target of the client side event.
119 */
120 public BrowserEvent(String name, String componentId, String componentIdPath, EventTarget target)
121 {
122 _name = name;
123 _target = target;
124 _componentId = componentId;
125 _componentIdPath = componentIdPath;
126 }
127
128 /**
129 * The name of the event that was generated.
130 *
131 * <p>
132 * Examples would be <code>onClick,onSelect,onLoad,etc...</code>.
133 * </p>
134 * @return The event name.
135 */
136 public String getName()
137 {
138 return _name;
139 }
140
141 /**
142 * Returns the target of the client side event.
143 *
144 * @return The target representation of the client side object event originally bound for.
145 */
146 public EventTarget getTarget()
147 {
148 return _target;
149 }
150
151 /**
152 * Only when the event targeted a {@link org.apache.tapestry.IComponent} - will return the originating
153 * components id as returned from {@link org.apache.tapestry.IComponent#getId()}. <em>Not</em> present
154 * on element events.
155 *
156 * @return The originating component id that generated the event.
157 */
158 public String getComponentId()
159 {
160 return _componentId;
161 }
162
163 /**
164 * If the event was generated for a {@link org.apache.tapestry.IComponent} - will be the
165 * value returned from {@link org.apache.tapestry.IComponent#getExtendedId()}.
166 *
167 * @return Component path id, or null if not present.
168 */
169 public String getComponentIdPath()
170 {
171 return _componentIdPath;
172 }
173
174 /**
175 * @return the charCode
176 */
177 public String getCharCode()
178 {
179 return _charCode;
180 }
181
182 /**
183 * @return the keys
184 */
185 public String[] getKeys()
186 {
187 return _keys;
188 }
189
190 /**
191 * @return the layerX
192 */
193 public String getLayerX()
194 {
195 return _layerX;
196 }
197
198 /**
199 * @return the layerY
200 */
201 public String getLayerY()
202 {
203 return _layerY;
204 }
205
206 /**
207 * @return the pageX
208 */
209 public String getPageX()
210 {
211 return _pageX;
212 }
213
214 /**
215 * @return the pageY
216 */
217 public String getPageY()
218 {
219 return _pageY;
220 }
221
222 /**
223 * @return the type
224 */
225 public String getType()
226 {
227 return _type;
228 }
229
230
231 /**
232 * @return the method arguments of an intercepted method-call, if any. If none
233 * are available, return an empty JSONArray, never null.
234 *
235 * @throws ApplicationRuntimeException when the JSON-String could not be
236 * parsed.
237 */
238 public JSONArray getMethodArguments()
239 {
240 if ( _methodArgumentsArray == null)
241 {
242 try
243 {
244 _methodArgumentsArray = _methodArguments != null
245 ? new JSONArray( _methodArguments )
246 : new JSONArray();
247 }
248 catch (ParseException ex)
249 {
250 throw new ApplicationRuntimeException(ex);
251 }
252 }
253
254 return _methodArgumentsArray;
255 }
256
257 /**
258 * Utility method to check if the current request contains
259 * a browser event.
260 *
261 * @param cycle
262 * The associated request.
263 * @return True if the request contains browser event data.
264 */
265 public static boolean hasBrowserEvent(IRequestCycle cycle)
266 {
267 Defense.notNull(cycle, "cycle");
268
269 return cycle.getParameter(NAME) != null;
270 }
271
272 public String toString()
273 {
274 return "BrowserEvent[" +
275 "_name='" + _name + '\'' +
276 '\n' +
277 ", _type='" + _type + '\'' +
278 '\n' +
279 ", _keys=" + (_keys == null ? null : Arrays.asList(_keys)) +
280 '\n' +
281 ", _charCode='" + _charCode + '\'' +
282 '\n' +
283 ", _pageX='" + _pageX + '\'' +
284 '\n' +
285 ", _pageY='" + _pageY + '\'' +
286 '\n' +
287 ", _layerX='" + _layerX + '\'' +
288 '\n' +
289 ", _layerY='" + _layerY + '\'' +
290 '\n' +
291 ", _target=" + _target +
292 '\n' +
293 ", _componentId='" + _componentId + '\'' +
294 '\n' +
295 ", _componentIdPath='" + _componentIdPath + '\'' +
296 '\n' +
297 ", _methodArguments='" + _methodArguments + '\'' +
298 '\n' +
299 ", _methodArgumentsArray=" + _methodArgumentsArray +
300 '\n' +
301 ']';
302 }
303
304 public boolean equals(Object o)
305 {
306 if (this == o) return true;
307 if (o == null || getClass() != o.getClass()) return false;
308
309 BrowserEvent event = (BrowserEvent) o;
310
311 if (_charCode != null ? !_charCode.equals(event._charCode) : event._charCode != null) return false;
312 if (!Arrays.equals(_keys, event._keys)) return false;
313 if (_layerX != null ? !_layerX.equals(event._layerX) : event._layerX != null) return false;
314 if (_layerY != null ? !_layerY.equals(event._layerY) : event._layerY != null) return false;
315 if (_methodArguments != null ? !_methodArguments.equals(event._methodArguments) : event._methodArguments != null) return false;
316 if (_methodArgumentsArray != null ? !_methodArgumentsArray.equals(event._methodArgumentsArray) : event._methodArgumentsArray != null) return false;
317 if (_name != null ? !_name.equals(event._name) : event._name != null) return false;
318 if (_pageX != null ? !_pageX.equals(event._pageX) : event._pageX != null) return false;
319 if (_pageY != null ? !_pageY.equals(event._pageY) : event._pageY != null) return false;
320 if (_target != null ? !_target.equals(event._target) : event._target != null) return false;
321 if (_type != null ? !_type.equals(event._type) : event._type != null) return false;
322
323 return true;
324 }
325
326 public int hashCode()
327 {
328 int result;
329 result = (_name != null ? _name.hashCode() : 0);
330 result = 31 * result + (_type != null ? _type.hashCode() : 0);
331 result = 31 * result + (_keys != null ? Arrays.hashCode(_keys) : 0);
332 result = 31 * result + (_charCode != null ? _charCode.hashCode() : 0);
333 result = 31 * result + (_pageX != null ? _pageX.hashCode() : 0);
334 result = 31 * result + (_pageY != null ? _pageY.hashCode() : 0);
335 result = 31 * result + (_layerX != null ? _layerX.hashCode() : 0);
336 result = 31 * result + (_layerY != null ? _layerY.hashCode() : 0);
337 result = 31 * result + (_target != null ? _target.hashCode() : 0);
338 result = 31 * result + (_methodArguments != null ? _methodArguments.hashCode() : 0);
339 result = 31 * result + (_methodArgumentsArray != null ? _methodArgumentsArray.hashCode() : 0);
340 return result;
341 }
342 }