/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2013 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.server.ngclient.component; import java.awt.Point; import java.sql.Timestamp; import java.util.List; import org.json.JSONException; import org.json.JSONObject; import org.mozilla.javascript.Function; import org.mozilla.javascript.Scriptable; import org.sablo.WebComponent; import com.servoy.base.persistence.constants.IContentSpecConstantsBase; import com.servoy.base.scripting.api.IJSEvent; import com.servoy.j2db.FormController; import com.servoy.j2db.IForm; import com.servoy.j2db.IFormController; import com.servoy.j2db.persistence.AbstractBase; import com.servoy.j2db.persistence.IContentSpecConstants; import com.servoy.j2db.persistence.IPersist; import com.servoy.j2db.persistence.ScriptMethod; import com.servoy.j2db.scripting.ElementScope; import com.servoy.j2db.scripting.FormScope; import com.servoy.j2db.scripting.GlobalScope; import com.servoy.j2db.scripting.JSEvent; import com.servoy.j2db.server.ngclient.FormElement; import com.servoy.j2db.server.ngclient.WebFormComponent; import com.servoy.j2db.util.Debug; import com.servoy.j2db.util.Utils; /** * @author lvostinar * */ public class EventExecutor { private final IFormController formController; public EventExecutor(IFormController formController) { this.formController = formController; } public Object executeEvent(WebComponent component, String eventType, int eventId, Object[] args) { Scriptable scope = null; Function f = null; if (eventId > 0) { FormScope formScope = formController.getFormScope(); String name = formScope.getFunctionName(new Integer(eventId)); if (name != null) { f = formScope.getFunctionByName(name); if (f != null && f != Scriptable.NOT_FOUND) { scope = formScope; } } if (scope == null) { ScriptMethod scriptMethod = formController.getApplication().getFlattenedSolution().getScriptMethod(eventId); if (scriptMethod != null) { scope = formController.getApplication().getScriptEngine().getScopesScope().getGlobalScope(scriptMethod.getScopeName()); } if (scope != null) { name = ((GlobalScope)scope).getFunctionName(new Integer(eventId)); f = ((GlobalScope)scope).getFunctionByName(name); } } if (name == null && scope == null && formController.getFormModel() != null) { try { ScriptMethod method = AbstractBase.selectById( formController.getApplication().getFlattenedSolution().getFoundsetMethods(formController.getTable(), false).iterator(), eventId); if (method != null) { name = method.getName(); scope = formController.getFormModel(); f = (Function)scope.getPrototype().get(name, scope); } } catch (Exception ex) { Debug.error(ex); } } } if (formController.isInFindMode() && !Utils.getAsBoolean(f.get("_AllowToRunInFind_", f))) return null; if (args != null) { for (int i = 0; i < args.length; i++) { if (args[i] instanceof JSONObject && "event".equals(((JSONObject)args[i]).optString("type"))) { JSONObject json = (JSONObject)args[i]; JSEvent event = new JSEvent(); event.setType(getEventType(eventType)); event.setFormName(formController.getName()); // the names used in scripting are the actual persist names // not the processed names (web friendly) String componentName = component instanceof WebFormComponent ? ((WebFormComponent)component).getFormElement().getRawName() : component.getName(); event.setElementName(componentName); FormScope formScope = formController.getFormScope(); if (formScope != null) { ElementScope elementsScope = (ElementScope)formScope.get("elements", null); if (elementsScope != null) { Object scriptableElement = componentName != null ? elementsScope.get(componentName, null) : null; if (scriptableElement != null && scriptableElement != Scriptable.NOT_FOUND) { event.setSource(scriptableElement); } else if (component instanceof WebFormComponent) { // quickly create a scriptable wrappar around the component so that the source can be set to a value that we expect. FormElement fe = ((WebFormComponent)component).getFormElement(); RuntimeWebComponent runtimeComponent = new RuntimeWebComponent((WebFormComponent)component, component.getSpecification()); if (fe.isLegacy() || ((fe.getForm().getView() == IForm.LIST_VIEW || fe.getForm().getView() == FormController.LOCKED_LIST_VIEW || fe.getForm().getView() == FormController.TABLE_VIEW || fe.getForm().getView() == FormController.LOCKED_TABLE_VIEW) && fe.getTypeName().startsWith("svy-"))) { // add legacy behavior runtimeComponent.setPrototype(new RuntimeLegacyComponent((WebFormComponent)component)); } event.setSource(runtimeComponent); } } } try { event.setTimestamp(new Timestamp(json.getLong("timestamp"))); if (json.has("x")) event.setLocation(new Point(json.getInt("x"), json.getInt("y"))); if (json.has("modifiers")) event.setModifiers(json.getInt("modifiers")); } catch (Exception ex) { Debug.error("error setting event properties from " + json + ", for component: " + componentName, ex); } args[i] = event; } } } if (component instanceof WebFormComponent) { IPersist persist = ((WebFormComponent)component).getFormElement().getPersistIfAvailable(); if (persist instanceof AbstractBase) { List<Object> instanceMethodArguments = ((AbstractBase)persist).getInstanceMethodArguments(eventType); if (instanceMethodArguments != null && instanceMethodArguments.size() > 0) { args = Utils.arrayMerge(args, Utils.parseJSExpressions(instanceMethodArguments)); } } } try { return formController.getApplication().getScriptEngine().executeFunction(f, scope, scope, args, false, false); } catch (Exception ex) { formController.getApplication().reportJSError(ex.getMessage(), ex); return null; } } /** * Get the event type based on the methodID property. * @param methodID * @return */ private String getEventType(String methodID) { switch (methodID) { case IContentSpecConstantsBase.PROPERTY_ONACTIONMETHODID : return IJSEvent.ACTION; case IContentSpecConstants.PROPERTY_ONDOUBLECLICKMETHODID : return IJSEvent.DOUBLECLICK; case IContentSpecConstants.PROPERTY_ONRIGHTCLICKMETHODID : return IJSEvent.RIGHTCLICK; case IContentSpecConstants.PROPERTY_ONDATACHANGEMETHODID : return IJSEvent.DATACHANGE; case IContentSpecConstants.PROPERTY_ONFOCUSGAINEDMETHODID : return IJSEvent.FOCUSGAINED; case IContentSpecConstants.PROPERTY_ONFOCUSLOSTMETHODID : return IJSEvent.FOCUSLOST; case IContentSpecConstants.PROPERTY_ONDRAGMETHODID : return JSEvent.EventType.onDrag.toString(); case IContentSpecConstants.PROPERTY_ONDRAGENDMETHODID : return JSEvent.EventType.onDragEnd.toString(); case IContentSpecConstants.PROPERTY_ONDRAGOVERMETHODID : return JSEvent.EventType.onDragOver.toString(); case IContentSpecConstants.PROPERTY_ONDROPMETHODID : return JSEvent.EventType.onDrop.toString(); default : return methodID; } } public static JSONObject createEvent(String type, int i) { JSONObject event = new JSONObject(); try { event.put("type", "event"); event.put("eventName", type); event.put("timestamp", System.currentTimeMillis()); event.put("modifiers", 0); event.put("x", 0); event.put("y", 0); event.put("selectedIndex", i); } catch (JSONException ex) { Debug.error(ex); } return event; } }