/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2014 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;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;
import org.sablo.services.server.FormServiceHandler;
import org.sablo.specification.property.IBrowserConverterContext;
import org.sablo.websocket.utils.JSONUtils.IToJSONConverter;
import com.servoy.j2db.ExitScriptException;
import com.servoy.j2db.IBasicFormManager.History;
import com.servoy.j2db.dataprocessing.FoundSet;
import com.servoy.j2db.dataprocessing.IRecordInternal;
import com.servoy.j2db.persistence.Form;
import com.servoy.j2db.server.ngclient.component.RuntimeWebComponent;
import com.servoy.j2db.server.ngclient.property.types.NGConversions.InitialToJSONConverter;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.SecuritySupport;
import com.servoy.j2db.util.Settings;
import com.servoy.j2db.util.Utils;
/**
* FormService implementation to handle methods at form level.
*
* @author rgansevles
*
*/
public class NGFormServiceHandler extends FormServiceHandler
{
private final INGClientWebsocketSession websocketSession;
public NGFormServiceHandler(INGClientWebsocketSession websocketSession)
{
this.websocketSession = websocketSession;
}
protected INGApplication getApplication()
{
return websocketSession.getClient();
}
@Override
protected IToJSONConverter<IBrowserConverterContext> getInitialRequestDataConverter()
{
return InitialToJSONConverter.INSTANCE;
}
@Override
public Object executeMethod(String methodName, JSONObject args) throws Exception
{
switch (methodName)
{
case "svyPush" :
{
String formName = args.getString("formname");
IWebFormUI form = (IWebFormUI)NGClientWindow.getCurrentWindow().getForm(formName);
if (form == null)
{
log.warn("svyPush for unknown form '" + formName + "'");
}
else
{
JSONObject changes = args.getJSONObject("changes");
WebFormComponent webComponent = form.getWebComponent(args.getString("beanname"));
if (changes.length() > 0)
{
Iterator<String> keys = changes.keys();
while (keys.hasNext())
{
String key = keys.next();
Object value = changes.get(key);
if ("".equals(value) && form.getDataAdapterList().getValueObject(form.getDataAdapterList().getRecord(),
form.getDataAdapterList().getDataProviderID(webComponent, args.getString("property"))) == null)
{
keys.remove();
}
}
args.put("changes", changes);
}
if (changes.length() > 0)
{
dataPush(args);
form.getDataAdapterList().pushChanges(webComponent, args.getString("property"));
}
}
break;
}
case "startEdit" :
{
IWebFormUI form = getApplication().getFormManager().getFormAndSetCurrentWindow(args.optString("formname")).getFormUI();
form.getDataAdapterList().startEdit(form.getWebComponent(args.optString("beanname")), args.optString("property"));
break;
}
case "executeInlineScript" :
{
try
{
String formName = args.optString("formname", null);
if (formName == null)
{
formName = getApplication().getFormManager().getCurrentForm().getName();
}
else
{
formName = SecuritySupport.decrypt(Settings.getInstance(), formName);
}
IWebFormUI form = getApplication().getFormManager().getFormAndSetCurrentWindow(formName).getFormUI();
return form.getDataAdapterList().executeInlineScript(args.optString("script"), args.optJSONObject("params"), args.optJSONArray("params"));
}
catch (Exception ex)
{
if (!(ex instanceof ExitScriptException))
{
Debug.error("Cannot execute inline script", ex);
}
}
break;
}
case "formvisibility" :
{
IWebFormController parentForm = null;
IWebFormController controller = null;
String formName = args.optString("formname");
checkAndSetParentWindow(formName);
if (args.has("parentForm") && !args.isNull("parentForm"))
{
checkAndSetParentWindow(args.optString("parentForm"));
parentForm = getApplication().getFormManager().getFormAndSetCurrentWindow(args.optString("parentForm"));
controller = getApplication().getFormManager().getForm(formName);
}
else
{
controller = getApplication().getFormManager().getFormAndSetCurrentWindow(formName);
}
if (controller == null) return Boolean.valueOf(true);
List<Runnable> invokeLaterRunnables = new ArrayList<Runnable>();
boolean isVisible = args.getBoolean("visible");
WebFormComponent containerComponent = null;
if (parentForm != null)
{
containerComponent = parentForm.getFormUI().getWebComponent(args.getString("bean"));
if (isVisible && containerComponent != null)
{
containerComponent.updateVisibleForm(controller.getFormUI(), isVisible, args.optInt("formIndex"));
}
}
boolean ok = controller.notifyVisible(isVisible, invokeLaterRunnables);
if (ok && parentForm != null)
{
if (!isVisible && containerComponent != null)
{
containerComponent.updateVisibleForm(controller.getFormUI(), isVisible, args.optInt("formIndex"));
}
String relation = null;
if (isVisible && args.has("relation") && !args.isNull("relation") && !"".equals(args.getString("relation")))
{
relation = args.getString("relation");
FoundSet parentFs = parentForm.getFormModel();
IRecordInternal selectedRecord = (IRecordInternal)parentFs.getSelectedRecord();
if (selectedRecord != null)
{
controller.loadRecords(selectedRecord.getRelatedFoundSet(relation));
}
else
{
// no selected record, then use prototype so we can get global relations
controller.loadRecords(parentFs.getPrototypeState().getRelatedFoundSet(relation));
}
}
if (isVisible)
{
// was shown
parentForm.getFormUI().getDataAdapterList().addVisibleChildForm(controller, relation, true);
}
else
{
// was hidden
parentForm.getFormUI().getDataAdapterList().removeVisibleChildForm(controller, true);
}
}
Utils.invokeLater(getApplication(), invokeLaterRunnables);
Form form = getApplication().getFormManager().getPossibleForm(formName);
if (form != null) NGClientWindow.getCurrentWindow().touchForm(getApplication().getFlattenedSolution().getFlattenedForm(form), formName, true);
return Boolean.valueOf(ok);
}
case "formLoaded" :
{
NGClientWindow.getCurrentWindow().formCreated(args.optString("formname"));
break;
}
case "gotoform" :
{
String formName = args.optString("formname");
IWebFormController form = getApplication().getFormManager().getForm(formName);
if (form != null)
{
String windowName = form.getFormUI().getParentWindowName();
NGRuntimeWindow window = null;
if (windowName != null && (window = getApplication().getRuntimeWindowManager().getWindow(windowName)) != null)
{
History history = window.getHistory();
if (history.getFormIndex(formName) != -1)
{
history.go(history.getFormIndex(formName) - history.getIndex());
}
else
{
Debug.log("Form " + formName + " was not found in the history of window " + windowName);
}
}
else
{
Debug.error("Window was not found for form " + formName);
}
}
else
{
Debug.error("Form " + formName + " was not found");
}
break;
}
case "callServerSideApi" :
{
String formName = args.getString("formname");
IWebFormUI form = (IWebFormUI)NGClientWindow.getCurrentWindow().getForm(formName);
if (form != null)
{
WebFormComponent webComponent = form.getWebComponent(args.getString("beanname"));
if (webComponent != null)
{
RuntimeWebComponent runtimeComponent = null;
RuntimeWebComponent[] webComponentElements = form.getController().getWebComponentElements();
for (RuntimeWebComponent runtimeWebComponent : webComponentElements)
{
if (runtimeWebComponent.getComponent() == webComponent)
{
runtimeComponent = runtimeWebComponent;
break;
}
}
if (runtimeComponent != null)
{
return runtimeComponent.executeScopeFunction(args.getString("methodName"), args.getJSONArray("args"));
}
else
{
log.warn("callServerSideApi for unknown bean '" + args.getString("beanname") + "' of form '" + formName + "'");
}
}
else
{
log.warn("callServerSideApi for unknown bean '" + args.getString("beanname") + "' of form '" + formName + "'");
}
}
else
{
log.warn("callServerSideApi for unknown form '" + formName + "'");
}
break;
}
case "performFind" :
String formName = args.optString("formname");
boolean clear = args.optBoolean("clear");
boolean reduce = args.optBoolean("reduce");
boolean showDialogOnNoResults = args.optBoolean("showDialogOnNoResults");
IWebFormController controller = getApplication().getFormManager().getForm(formName);
if (controller != null)
{
controller.performFind(clear, reduce, showDialogOnNoResults);
}
break;
default :
{
return super.executeMethod(methodName, args);
}
}
return null;
}
@Override
protected Object executeEvent(JSONObject obj) throws Exception
{
String formName = obj.optString("formname");
if (formName != null) getApplication().getFormManager().getFormAndSetCurrentWindow(formName);
return super.executeEvent(obj);
}
@Override
protected JSONString requestData(String formName) throws JSONException
{
getApplication().getFormManager().getFormAndSetCurrentWindow(formName);
return super.requestData(formName);
}
@Override
public int getMethodEventThreadLevel(String methodName, JSONObject arguments, int dontCareLevel)
{
if ("formLoaded".equals(methodName)) return EVENT_LEVEL_INITIAL_FORM_DATA_REQUEST; // allow it to run on dispatch thread even if some API call is waiting (suspended)
return super.getMethodEventThreadLevel(methodName, arguments, dontCareLevel);
}
private void checkAndSetParentWindow(String formName)
{
if (formName != null)
{
INGFormManager fm = websocketSession.getClient().getFormManager();
if (fm.getForm(formName) != null)
{
IWebFormUI formUI = fm.getForm(formName).getFormUI();
if (formUI != null && formUI.getParentContainer() == null)
{
NGRuntimeWindowManager wm = websocketSession.getClient().getRuntimeWindowManager();
String currentWindowName = wm.getCurrentWindow().getName();
if (currentWindowName == null)
{
currentWindowName = wm.getMainApplicationWindow().getName();
}
formUI.setParentWindowName(currentWindowName);
}
}
}
}
}