/**
* Copyright 2008-2016 Qualogy Solutions B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.qualogy.qafe.gwt.client.ui.renderer.events;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.UIObject;
import com.qualogy.qafe.gwt.client.component.HasDataModel;
import com.qualogy.qafe.gwt.client.context.ClientApplicationContext;
import com.qualogy.qafe.gwt.client.exception.GWTServiceException;
import com.qualogy.qafe.gwt.client.service.RPCService;
import com.qualogy.qafe.gwt.client.service.RPCServiceAsync;
import com.qualogy.qafe.gwt.client.ui.renderer.RendererHelper;
import com.qualogy.qafe.gwt.client.ui.renderer.events.exception.RequiredFieldException;
import com.qualogy.qafe.gwt.client.util.ComponentRepository;
import com.qualogy.qafe.gwt.client.util.QAMLConstants;
import com.qualogy.qafe.gwt.client.vo.data.EventDataGVO;
import com.qualogy.qafe.gwt.client.vo.data.EventDataI;
import com.qualogy.qafe.gwt.client.vo.data.GDataObject;
import com.qualogy.qafe.gwt.client.vo.functions.BuiltInFunctionGVO;
import com.qualogy.qafe.gwt.client.vo.functions.DataContainerGVO;
import com.qualogy.qafe.gwt.client.vo.functions.execute.FunctionsExecutor;
import com.qualogy.qafe.gwt.client.vo.handlers.BuiltinHandlerHelper;
import com.qualogy.qafe.gwt.client.vo.handlers.EventHandler;
import com.qualogy.qafe.gwt.client.vo.ui.event.EventListenerGVO;
import com.qualogy.qafe.gwt.client.vo.ui.event.InputVariableGVO;
public class CallbackHandler {
private final static RPCServiceAsync service = (RPCServiceAsync) GWT.create(RPCService.class);
private static AsyncCallback<?> callback = null;
final public static void createCallBack(final Object sender, final String listenerType, final EventListenerGVO eventGVO, List<InputVariableGVO> listOfInputVariables, Map<String,String> mouseInfo) {
if (sender instanceof UIObject) {
createCallBack((UIObject) sender, listenerType, eventGVO, listOfInputVariables, null, mouseInfo);
}
}
final public static void createCallBack(final Object sender, final String listenerType, final EventListenerGVO eventGVO, List<InputVariableGVO> listOfInputVariables) {
createCallBack(sender, listenerType, eventGVO, listOfInputVariables, null);
}
final private static AsyncCallback<?> createCallBack(final String listenerType) {
ServiceDefTarget endpoint = (ServiceDefTarget) service;
String moduleRelativeURL = GWT.getModuleBaseURL() + "rpc.service";
endpoint.setServiceEntryPoint(moduleRelativeURL);
if (callback == null){
callback = new AsyncCallback<Object>() {
@Override
public void onSuccess(Object result) {
GDataObject data = (GDataObject) result;
//this is to trigger handler registered to do on success of event body execution.
ClientApplicationContext.getInstance().fireResult(data);
/* Data is processed after the event firing is done.
* This makes it possible to get handle to newly added rows on a datagrid when the add button event on datagrid tool bar is triggered.
* Also enables to set a cell value when new row is added in the same event.
*/
processOutput(data);
ClientApplicationContext.getInstance().setBusy(false);
}
@Override
public void onFailure(Throwable caught) {
ClientApplicationContext.getInstance().log("Event execution for " + listenerType + " failed", caught.getMessage(), true, false, caught);
ClientApplicationContext.getInstance().setBusy(false);
if (caught instanceof GWTServiceException) {
GWTServiceException gWTServiceException = (GWTServiceException) caught;
processOutput(gWTServiceException.getGDataObject());
}
}
};
}
return callback;
}
final public static void createCallBack(final UIObject sender, final String listenerType, final EventListenerGVO eventGVO, List<InputVariableGVO> listOfInputVariables) {
createCallBack(sender, listenerType, eventGVO, listOfInputVariables, null);
}
// CHECKSTYLE.OFF: CyclomaticComplexity
final public static void createCallBack(final UIObject sender, final String listenerType, final EventListenerGVO eventGVO, List<InputVariableGVO> listOfInputVariables, Map<String,Object> internalVariables, Map<String,String> mouseInfo) {
if (ClientApplicationContext.getInstance().isClientSideEventEnabled()) {
EventHandler.getInstance().handleEvent(sender, listenerType, eventGVO, mouseInfo, internalVariables);
ClientApplicationContext.getInstance().log("Sender: " + sender + " - " + listenerType);
return;
}
if (eventGVO != null) {
String senderUUID = DOM.getElementProperty(sender.getElement(), "uuid");
String senderId = DOM.getElementAttribute(sender.getElement(), "id");
if (senderId != null && senderId.length() > 0) {
String context = RendererHelper.getComponentContext(sender);
String parent = RendererHelper.getParentComponent(sender);
String senderName = RendererHelper.getNamedComponentName(sender);
ClientApplicationContext.getInstance().setBusy(true);
AsyncCallback<?> callback = createCallBack(listenerType);
EventDataGVO eventDataObject = new EventDataGVO();
eventDataObject.setUuid(senderUUID);
eventDataObject.setEventId(eventGVO.getEventId());
eventDataObject.setListenerType(listenerType);
eventDataObject.setSenderName(senderName);
eventDataObject.setUserUID(ClientApplicationContext.getInstance().getAppUUID());
eventDataObject.setWindowSession(ClientApplicationContext.getInstance().getWindowSession());
eventDataObject.setInternalVariables(internalVariables);
eventDataObject.setParameters(ClientApplicationContext.getInstance().getParameters());
eventDataObject.setSender(senderId);
eventDataObject.setOriginalSenderId(senderId); // unmanipulated Mouse Coordinates
if(senderId.startsWith(QAMLConstants.TOKEN_INDEXING)) {
eventDataObject.setIndex(senderId.substring(senderId.indexOf(QAMLConstants.TOKEN_INDEXING) + QAMLConstants.TOKEN_INDEXING.length(), senderId.lastIndexOf(QAMLConstants.TOKEN_INDEXING)));
}
if (mouseInfo!=null){
eventDataObject.setMouseCoordinates(mouseInfo.get(EventDataI.MOUSE_X), mouseInfo.get(EventDataI.MOUSE_Y));
}
// sender id
eventDataObject.setParent(parent);
if (eventGVO.getSourceId() != null) {
eventDataObject.setSourceId(eventGVO.getSourceId());
if (!senderId.startsWith("||") && !senderId.startsWith(QAMLConstants.TOKEN_INDEXING)) {
if (senderId.indexOf('|') > 0) {
eventDataObject.setSourceIdValue(senderId.substring(0, senderId.indexOf('|')));
}
}
}
if (eventGVO.getSourceName() != null) {
eventDataObject.setSourceName(eventGVO.getSourceName());
if (RendererHelper.isNamedComponent(sender)) {
eventDataObject.setSourceNameValue(RendererHelper.getNamedComponentName(sender));
}
}
if (eventGVO.getSourceValue() != null) {
eventDataObject.setSourceValue(eventGVO.getSourceValue());
Object o = getValue(sender, sender, true, null);
if (o instanceof String) {
eventDataObject.setSourceValueValue(o.toString());
}
}
if (eventGVO.getSourceListenerType() != null) {
eventDataObject.setSourceListenerType(eventGVO.getSourceListenerType());
eventDataObject.setSourceListenerTypeValue(listenerType);
}
if (senderId.startsWith("||")) { // so this is a click from a table{
eventDataObject.setSender(senderId.substring(senderId.lastIndexOf("||") + 2));
} else if (senderId.startsWith(QAMLConstants.TOKEN_INDEXING)) { // so this is a click from a tile or an inner component in datagrid
eventDataObject.setSender(senderId.substring(senderId.lastIndexOf(QAMLConstants.TOKEN_INDEXING) + QAMLConstants.TOKEN_INDEXING.length()));
}
boolean error = false;
if (listOfInputVariables != null) {
try {
for (InputVariableGVO inputVariables : listOfInputVariables) {
String value = null;
DataContainerGVO dataContainerObject = null;
String inputVariableReference = inputVariables.getReference();
if (hasAttribute(inputVariableReference)) {
value = getAttributeValue(inputVariableReference, parent, context);
} else if(inputVariableReference.contains(".$$")){
dataContainerObject = fetchDatagridRowValues(inputVariableReference, parent, context);
} else if(inputVariableReference.contains("[")){
dataContainerObject = fetchDatagridCellValue(inputVariableReference, parent, context);
} else {
String key = RendererHelper.generateId(inputVariableReference, parent, context); // inputVariables[i][1]
ClientApplicationContext.getInstance().log(key);
List<UIObject> uiObjects = ComponentRepository.getInstance().getComponent(key);
// since the parameter can be a complex object, we need to create a substitute for it.
// This can only be used in the name variant though (namedcomponents)
if (uiObjects != null) {
for (UIObject uiObject : uiObjects) {
Object o = getValue(uiObject, sender, false, null);
if (o instanceof String) {
value = o.toString();
} else if (o instanceof DataContainerGVO) {
dataContainerObject = (DataContainerGVO) o;
}
if (uiObject instanceof HasDataModel) {
// Get also the data model behind
HasDataModel hasDataModel = (HasDataModel)uiObject;
if (hasDataModel.getDataModel() != null) {
Object dataModel = hasDataModel.getDataModel();
String newInputVariableReference = inputVariableReference + QAMLConstants.DATAMODEL_POSTFIX;
if (eventDataObject.getInternalVariables() == null) {
eventDataObject.setInternalVariables(new HashMap<String,Object>());
}
eventDataObject.getInternalVariables().put(newInputVariableReference, dataModel);
}
}
}
} else {
// so the object could not be found in the ComponentRepository, maybe we try by name to find it.
ClientApplicationContext.getInstance().log("Reference" + inputVariables.getReference());
String[] keysSet = inputVariables.getReference().split("[.]");
if (keysSet != null) {
String searchKey = null;
if (keysSet.length == 1) {// so only the key
searchKey = key;
} else {
searchKey = RendererHelper.generateId(keysSet[0], parent, context);
}
if (searchKey != null) {
uiObjects = ComponentRepository.getInstance().getNamedComponent(searchKey);
if (uiObjects != null) {
for (UIObject uiObject : uiObjects) {
// Collect all the data from a list of named components
DataContainerGVO dataContainer = createDataContainer(inputVariables.getReference(), uiObject, sender);
if (dataContainerObject == null) {
dataContainerObject = dataContainer;
} else if (dataContainer != null) {
if (dataContainer.getKind() == dataContainerObject.getKind()) {
switch (dataContainer.getKind()) {
case DataContainerGVO.KIND_MAP : {
dataContainerObject.getDataMap().putAll(dataContainer.getDataMap());
} break;
}
}
}
// Get value of a data member
if(keysSet.length > 1){
if(dataContainerObject.getDataMap().get(keysSet[1]) != null){
value = dataContainerObject.getDataMap().get(keysSet[1]).getDataString();
}
dataContainerObject = null;
}
}
} else { // Apparently we have to search for the Group now.
dataContainerObject = BuiltinHandlerHelper.getGroupedComponentValue(sender, inputVariables.getReference(), key);
}
}
}
}
}
String x = inputVariables.getComponentValue() != null ? inputVariables.getComponentValue() : value;
if ((inputVariableReference != null) && inputVariableReference.startsWith("||")) {
// so this is a click from a table
inputVariableReference = (inputVariables.getReference().substring(senderId.lastIndexOf("||") + 2));
}
eventDataObject.getInputVariables().add(new InputVariableGVO(inputVariables.getName(), inputVariableReference, inputVariables.getDefaultValue(), x, dataContainerObject));
}
} catch (RequiredFieldException e) {
ClientApplicationContext.getInstance().log(e.getTitle(), e.getMessage(), true, true, e);
error = true;
} catch (TypeValidationException e) {
ClientApplicationContext.getInstance().log("Validation Error: ", e.getMessage(), true, true, e);
error = true;
}
}
if (!error) {
service.executeEvent(EnrichEventUtil.enrichEvent(eventDataObject), callback);
}
} else {
ClientApplicationContext.getInstance().log("Callbackhander: Trying to call event while id is empty !!");
}
} else {
ClientApplicationContext.getInstance().log("Callbackhander: eventGVO cannot be null !!");
}
}
// CHECKSTYLE.ON: CyclomaticComplexity
private static DataContainerGVO fetchDatagridRowValues(String inputVariableReference, String parent,String context) {
return BuiltinHandlerHelper.fetchDatagridRowValues(inputVariableReference, parent, context);
}
private static DataContainerGVO fetchDatagridCellValue(String inputVariableReference, String parent,String context) {
return BuiltinHandlerHelper.fetchDatagridCellValue(inputVariableReference, parent, context);
}
private static boolean hasAttribute(String inputVariableReference) {
return BuiltinHandlerHelper.hasAttribute(inputVariableReference);
}
private static String getAttributeValue(String inputVariableReference, String parent, String context) {
return BuiltinHandlerHelper.getAttributeValue(inputVariableReference, parent, context);
}
public static DataContainerGVO createDataContainer(String parameterName, UIObject uiObject, final UIObject sender) throws RequiredFieldException {
return BuiltinHandlerHelper.createDataContainer(parameterName, uiObject, sender);
}
private static void processOutput(GDataObject data) {
if (data != null) {
BuiltInFunctionGVO[] builtInFunctions = data.getFunctions();
if (builtInFunctions != null) {
for (int i = 0; i < builtInFunctions.length; i++) {
BuiltInFunctionGVO builtInFunctionGVO = builtInFunctions[i];
builtInFunctionGVO.setSenderId(data.getSenderId());
builtInFunctionGVO.setListenerType(data.getListenerType());
GWT.log("Process output:" + builtInFunctionGVO.getClassName(), null);
FunctionsExecutor.getInstance().execute(builtInFunctionGVO);
}
}
ClientApplicationContext.getInstance().setLogText("Execution time:" + data.getTime() + " ms");
}
}
public static Object getValue(UIObject uiObject, final UIObject sender, boolean idValueOnly, String groupName){
return BuiltinHandlerHelper.getValue(uiObject, sender, idValueOnly, groupName);
}
}