/**
* 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.vo.handlers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.UIObject;
import com.qualogy.qafe.gwt.client.component.HasDataGridMethods;
import com.qualogy.qafe.gwt.client.storage.DataStorage;
import com.qualogy.qafe.gwt.client.ui.renderer.AnyComponentRenderer;
import com.qualogy.qafe.gwt.client.ui.renderer.RendererHelper;
import com.qualogy.qafe.gwt.client.util.ComponentRepository;
import com.qualogy.qafe.gwt.client.util.JSNIUtil;
import com.qualogy.qafe.gwt.client.util.QAMLConstants;
import com.qualogy.qafe.gwt.client.vo.data.EventItemDataGVO;
import com.qualogy.qafe.gwt.client.vo.data.GEventItemDataObject;
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.ui.BundleGVO;
import com.qualogy.qafe.gwt.client.vo.ui.ComponentGVO;
import com.qualogy.qafe.gwt.client.vo.ui.UIGVO;
import com.qualogy.qafe.gwt.client.vo.ui.event.ParameterGVO;
public abstract class AbstractBuiltInHandler implements BuiltInHandler {
@Override
public final BuiltInState handleBuiltIn(UIObject sender, String listenerType, Map<String, String> mouseInfo
, BuiltInFunctionGVO builtInGVO, String appId, String windowId
, String eventSessionId, Queue derivedBuiltIns) {
return executeBuiltIn(sender, listenerType, mouseInfo, builtInGVO, appId, windowId, eventSessionId, derivedBuiltIns);
}
protected Object getValue(UIObject sender, ParameterGVO parameterGVO, String appId, String windowId,
String eventSessionId) {
Object value = null;
if (parameterGVO == null) {
return value;
}
Map<String, Object> placeHolderValues = resolvePlaceholderValues(parameterGVO, sender, appId, windowId, eventSessionId);
value = getValue(sender, parameterGVO, appId, windowId, eventSessionId, placeHolderValues);
if (value instanceof DataContainerGVO) {
value = DataContainerGVO.createType((DataContainerGVO)value);
}
return value;
}
private final Object getValue(final UIObject sender, final ParameterGVO parameterGVO,
final String appId, final String windowId, final String eventSessionId,
final Map<String, Object> placeHolderValues) {
Object value = null;
if (parameterGVO == null) {
return value;
}
if (parameterGVO.getValue() != null) {
value = parameterGVO.getValue();
if (value instanceof String) {
value = resolveVariables((String) value, placeHolderValues, eventSessionId);
}
} else if (parameterGVO.getReference() != null) {
final String source = parameterGVO.getSource();
final String reference = resolveVariables(parameterGVO.getReference(), placeHolderValues, eventSessionId);
if (BuiltInFunctionGVO.SOURCE_COMPONENT_ID.equals(source)) {
value = getComponentValue(sender, reference, appId, windowId, eventSessionId);
} else {
if (BuiltInFunctionGVO.SOURCE_DATASTORE_ID.equals(source)
&& placeHolderValues.containsKey(reference)) {
value = placeHolderValues.get(reference);
} else if (BuiltInFunctionGVO.SOURCE_MESSAGE_ID.equals(source)) {
value = getLocalizedMessage(appId, reference);
} else {
final String dataId = generateDataId(source, appId, windowId, eventSessionId);
value = getData(dataId, reference);
}
}
} else if (parameterGVO.getExpression() != null) {
String expr = parameterGVO.getExpression();
expr = resolveExpression(expr, placeHolderValues, eventSessionId);
log(parameterGVO.getExpression() + " = " + expr);
value = evaluateExpression(expr);
}
return value;
}
private String getLocalizedMessage(String appId, String reference) {
String bundleId = BundleGVO.DEFAULT_BUNDLE_ID;
String messageKey = reference;
if (reference.contains(".")) {
String[] referenceList = reference.split("\\.");
bundleId = referenceList[0];
messageKey = referenceList[1];
}
UIGVO uiGVO = EventHandler.getInstance().getApplication(appId);
String currentLanguage = uiGVO.getCurrentLanguage();
BundleGVO bundleGVO = uiGVO.getBundle(bundleId);
if (bundleGVO != null) {
return bundleGVO.getLocalizedMessage(currentLanguage, messageKey);
}
return null;
}
// CHECKSTYLE.OFF: CyclomaticComplexity
// The solution is based on retrieving value from textfield
// TODO: Refactor to handle multiple components
private Object getComponentValue(final UIObject sender, final String reference, String appId,
String windowId, String eventSessionId) {
String value = null;
DataContainerGVO dataContainerObject = null;
if (BuiltinHandlerHelper.hasAttribute(reference)) {
value = BuiltinHandlerHelper.getAttributeValue(reference, windowId, appId);
dataContainerObject = DataContainerGVO.create(value);
} else if (reference.contains(".$$")) {
dataContainerObject =
BuiltinHandlerHelper.fetchDatagridRowValues(reference, windowId, appId);
} else if (reference.contains("[")) {
dataContainerObject =
BuiltinHandlerHelper.fetchDatagridCellValue(reference, windowId, appId);
} else {
final String key = generateId(reference, windowId, appId, eventSessionId); // inputVariables[i][1]
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 = BuiltinHandlerHelper.getValue(uiObject, sender, false, null);
/* value = ((HasText) uiObject).getText(); */
if (o instanceof String) {
//value = o.toString();
dataContainerObject = DataContainerGVO.create(o.toString());
} else if (o instanceof DataContainerGVO) {
dataContainerObject = (DataContainerGVO) o;
}
}
} else {
// so the object could not be found in the ComponentRepository,
// maybe we try by name to find it.
log("Reference" + reference);
String[] keysSet = reference.split("[.]");
if (keysSet != null) {
String searchKey = null;
if (keysSet.length == 1) {// so only the key
searchKey = key;
} else {
searchKey = generateId(keysSet[0], windowId, appId, eventSessionId);
}
if (searchKey != null) {
uiObjects = ComponentRepository.getInstance().getNamedComponent(searchKey);
if (uiObjects != null) {
for (UIObject uiObject : uiObjects) {
log("Title" + uiObject.getTitle());
// Collect all the data from a list of named
// components
DataContainerGVO dataContainer =
BuiltinHandlerHelper.createDataContainer(reference, 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 = DataContainerGVO.create(value);
}
}
}
} else { // Apparently we have to search for the Group
// now.
dataContainerObject =
BuiltinHandlerHelper.getGroupedComponentValue(sender, reference
, key);
}
}
}
}
}
return dataContainerObject;
}
// CHECKSTYLE.ON: CyclomaticComplexity
/**
*
* @param name
* @param placeHolderValues
* @param eventSessionId
* @return
*/
protected String resolveExpression(String name, Map<String, Object> placeHolderValues,
String eventSessionId) {
while (name != null && name.contains("${")) {
String varName = name.substring(name.indexOf("{") + 1, name.indexOf("}"));
Object value = null;
if (placeHolderValues != null && placeHolderValues.containsKey(varName)) {
value = placeHolderValues.get(varName);
} else {
value = getData(eventSessionId, varName);
}
if (value instanceof DataContainerGVO) {
value = DataContainerGVO.createType((DataContainerGVO) value);
}
value = resolveExpression(value);
name = name.replace("${" + varName + "}", value.toString());
}
return name;
}
private String resolveExpression(Object value) {
if (value == null) {
return "None";
}
if (value instanceof String) {
value = escapeQuotes((String)value);
// prefix with u to UTF-8 encode the string for in the python expression
return "u'" + value + "'";
}
if (value instanceof Boolean) {
boolean bool = (Boolean) value;
return bool ? "True" : "False";
}
if (value instanceof Date) {
return resolveExpression(value.toString());
}
if (value instanceof Map) {
Map mapValue = (Map) value;
StringBuilder newValueBuilder = new StringBuilder();
newValueBuilder.append("{");
for (Object key : mapValue.keySet()) {
newValueBuilder.append(resolveExpression(key));
newValueBuilder.append(":");
Object keyValue = mapValue.get(key);
newValueBuilder.append(resolveExpression(keyValue));
newValueBuilder.append(",");
}
newValueBuilder.append("}");
return newValueBuilder.toString();
}
if (value instanceof Collection) {
Collection collectionValue = (Collection) value;
StringBuilder newValueBuilder = new StringBuilder();
newValueBuilder.append("[");
for (Object item : collectionValue) {
newValueBuilder.append(resolveExpression(item));
newValueBuilder.append(",");
}
newValueBuilder.append("]");
return newValueBuilder.toString();
}
return value.toString();
}
private String escapeQuotes(String value) {
if (value != null) {
value = value.replaceAll("'", "\\\\'");
}
return value;
}
protected Map<String, Object> resolvePlaceholderValues(ParameterGVO parameterGVO, UIObject sender, String appId, String windowId, String eventSessionId) {
Map<String, Object> placeHolderValues = new HashMap<String, Object>();
if (parameterGVO.getPlaceHolders() != null && !parameterGVO.getPlaceHolders().isEmpty()) {
for (ParameterGVO placeholder : parameterGVO.getPlaceHolders()) {
Object placeHolderValue = getValue(sender, placeholder, appId, windowId, eventSessionId);
placeHolderValues.put(placeholder.getName(), placeHolderValue);
}
}
return placeHolderValues;
}
protected String resolveVariables(String name, Map<String, Object> placeHolderValues,
String eventSessionId) {
while (name != null && name.contains("${")) {
String varName = name.substring(name.indexOf("{") + 1, name.indexOf("}"));
Object value = null;
if (placeHolderValues != null && placeHolderValues.containsKey(varName)) {
value = placeHolderValues.get(varName);
} else {
value = getData(eventSessionId, varName);
}
if (value == null) {
value = "null";
}
name = name.replace("${" + varName + "}", value.toString());
}
return name;
}
protected int getRowIndex(String component, HasDataGridMethods hasDataGridMethods) {
int rowIndex = -1;
int indexPrefix = component.indexOf("[");
if (indexPrefix > -1) {
int indexPostfix = component.indexOf("]");
String selectedIndex = component.substring(indexPrefix + 1, indexPostfix);
rowIndex = hasDataGridMethods.getRowIndex(selectedIndex);
}
return rowIndex;
}
protected List<UIObject> collectCellUIObjects(String component, int rowIndex, List<UIObject> cellUIObjects) {
if (cellUIObjects == null) {
cellUIObjects = new ArrayList<UIObject>();
}
component = component.replaceFirst("\\[.+\\]", "");
boolean rowSelection = (rowIndex > -1);
while (true) {
String cellKey = QAMLConstants.TOKEN_INDEXING + rowIndex + QAMLConstants.TOKEN_INDEXING + component;
List<UIObject> uiObjects = ComponentRepository.getInstance().getComponent(cellKey);
if (uiObjects != null) {
cellUIObjects.addAll(uiObjects);
}
if (rowSelection || (uiObjects == null)) {
break;
}
rowIndex++;
}
return cellUIObjects;
}
protected List<UIObject> getParentUIObjects(String component) {
String parentKey = component.replaceFirst("\\.[\\w\\$]+\\|", "|").replaceFirst("\\[.+\\]", "");
return ComponentRepository.getInstance().getComponent(parentKey);
}
protected void storeData(String dataId, String name, Object data) {
EventHandler.getInstance().storeData(dataId, name, data);
}
protected Object getData(String dataId, String name) {
return getDataStorage().getData(dataId, name);
}
protected void removeData(String dataId) {
getDataStorage().removeData(dataId);
}
protected void removeData(String dataId, String name) {
getDataStorage().removeData(dataId, name);
}
protected DataStorage getDataStorage() {
return EventHandler.getInstance().getDataStorage();
}
protected String generateDataId(String sourceOrTarget, String appId, String windowId,
String eventSessionId) {
if (BuiltInFunctionGVO.SOURCE_DATASTORE_ID.equals(sourceOrTarget)) {
return eventSessionId;
}
if (BuiltInFunctionGVO.SOURCE_APP_GLOBAL_STORE_ID.equals(sourceOrTarget)) {
return appId;
}
if (BuiltInFunctionGVO.SOURCE_APP_LOCAL_STORE_ID.equals(sourceOrTarget)) {
return appId + "|" + windowId;
}
return null;
}
/**
* Get the component key.
*
* @param componentId
* @param appId
* @param windowId
* @param eventSessionId
* @return The key
*/
protected String generateId(String componentId, String windowId, String appId, String eventSessionId) {
if (componentId != null && componentId.contains("[")) {
// extract component id when dealing with indexes
componentId = componentId.substring(0, componentId.indexOf("["));
}
componentId = resolveVariables(componentId, null, eventSessionId);
return RendererHelper.generateId(componentId, windowId, appId);
}
/**
* Search for UIObjects considering ref is id.
*
* @param key
* @return List of UIObjects
*/
protected List<UIObject> getUIObjectsById(String key) {
return ComponentRepository.getInstance().getComponent(key);
}
/**
* Search for UIObjects considering ref is name.
*
* @param key
* @return List of UIObjects
*/
protected List<UIObject> getUIObjectsByName(String key) {
return ComponentRepository.getInstance().getNamedComponent(key);
}
/**
* Search for UIObjects considering ref is group.
*
* @param key
* @return List of UIObjects
*/
protected List<UIObject> getUIObjectsByGroup(String key) {
return ComponentRepository.getInstance().getGroupedComponent(key);
}
/**
* Search for UIObjects
* @param key
* @return
*/
protected List<UIObject> getUIObjects(String key) {
List<UIObject> uiObjects = getUIObjectsById(key);
if (uiObjects != null) {
return uiObjects;
}
uiObjects = getUIObjectsByName(key);
if (uiObjects != null) {
return uiObjects;
}
uiObjects = getUIObjectsByGroup(key);
return uiObjects;
}
protected String getSenderId(final UIObject sender) {
return RendererHelper.getComponentId(sender);
}
protected String getComponentName(final UIObject uiObject) {
return RendererHelper.getNamedComponentName(uiObject);
}
protected String getUUId(UIObject sender) {
return RendererHelper.getUUId(sender);
}
protected String getAppId(final UIObject sender) {
return RendererHelper.getComponentContext(sender);
}
protected boolean isNamedComponent(final UIObject uiObject) {
return RendererHelper.isNamedComponent(uiObject);
}
protected UIObject renderComponent(ComponentGVO componentGVO, String eventSessionId, String windowId, String appId) {
return AnyComponentRenderer.getInstance().render(componentGVO, eventSessionId, windowId, appId);
}
protected void log(String message) {
log("Log", message);
}
protected void log(String title, String message) {
log(title, message, false);
}
protected void log(String title, String message, boolean alert) {
EventHandler.getInstance().log(title, message, alert);
}
protected void executeBuiltInServerSide(UIObject sender, String listenerType, Map<String, String> mouseInfo
, EventItemDataGVO eventItemDataGVO, String appId, String windowId, String eventSessionId) {
setBusy(true);
AsyncCallback<?> callback = createCallback(sender, listenerType, mouseInfo, eventItemDataGVO, appId, windowId, eventSessionId);
EventHandler.getInstance().getRPCService().executeEventItem(eventItemDataGVO, callback);
}
private AsyncCallback<?> createCallback(final UIObject sender, final String listenerType
, final Map<String, String> mouseInfo, final EventItemDataGVO eventItemDataGVO
, final String appId, final String windowId, final String eventSessionId) {
return new AsyncCallback<Object>() {
@Override
public void onSuccess(Object result) {
setBusy(false);
GEventItemDataObject data = (GEventItemDataObject) result;
storeOutputValues(eventSessionId, data);
EventHandler.getInstance().handleEvent(eventSessionId, sender, listenerType
, mouseInfo, appId, windowId);
}
@Override
public void onFailure(Throwable exception) {
setBusy(false);
Object currentBuiltIn = eventItemDataGVO.getBuiltInGVO();
EventHandler.getInstance().handleException(exception, currentBuiltIn
, sender, listenerType, mouseInfo, appId, windowId, eventSessionId);
}
};
}
private void storeOutputValues(String eventSessionId, GEventItemDataObject data) {
Map<String, Object> outputValues = data.getOutputValues();
if (outputValues == null) {
return;
}
Iterator<String> itrOutputName = outputValues.keySet().iterator();
while (itrOutputName.hasNext()) {
String outputName = itrOutputName.next();
Object outputValue = outputValues.get(outputName);
if (DataStorage.KEY_WORD_QAFE_BUILT_IN_LIST.equals(outputName)) {
Collection<BuiltInFunctionGVO> builtIns = (Collection<BuiltInFunctionGVO>) outputValue;
EventHandler.getInstance().pushBuiltIns(eventSessionId, builtIns);
continue;
}
if (outputValue instanceof DataContainerGVO) {
outputValue = DataContainerGVO.createType((DataContainerGVO) outputValue);
}
storeData(eventSessionId, outputName, outputValue);
}
}
protected void setBusy(boolean busy) {
EventHandler.getInstance().setBusy(busy);
}
protected void showMessage(String title, String message) {
showMessage(title, message, null);
}
protected void showMessage(String title, String message, Throwable exception) {
EventHandler.getInstance().showMessage(title, message, exception);
}
protected String evaluateExpression(String expression) {
return JSNIUtil.evaluateExpression(expression);
}
protected String getShortenName(Object builtIn) {
return EventHandler.getInstance().getShortenName(builtIn);
}
protected String getSessionId() {
return EventHandler.getInstance().getSessionId();
}
protected abstract BuiltInState executeBuiltIn(UIObject sender, String listenerType, Map<String, String> mouseInfo
, BuiltInFunctionGVO builtInGVO, String appId, String windowId
, String eventSessionId, Queue derivedBuiltIns);
}