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 }