/*
* Copyright 2011 JBoss Inc
*
* 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 org.jbpm.formapi.client.form;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jbpm.formapi.common.reflect.ReflectionHelper;
import org.jbpm.formapi.shared.api.FBScript;
import org.jbpm.formapi.shared.api.FBValidation;
import org.jbpm.formapi.shared.api.FormItemRepresentation;
import org.jbpm.formapi.shared.api.FormRepresentation;
import org.jbpm.formapi.shared.api.InputData;
import org.jbpm.formapi.shared.api.Mappable;
import org.jbpm.formapi.shared.api.OutputData;
import org.jbpm.formapi.shared.form.FormEncodingException;
import org.jbpm.formapi.shared.form.FormRepresentationDecoder;
import org.jbpm.formapi.shared.menu.MenuItemDescription;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
/**
* Decodes json to different objects on the client side
*/
public class FormRepresentationDecoderClient implements
FormRepresentationDecoder {
@Override
public Object decode(Map<String, Object> data) throws FormEncodingException {
if (data == null || data.isEmpty()) {
return null;
}
String className = (String) data.get("@className");
Object obj = null;
try {
obj = ReflectionHelper.newInstance(className);
if (obj instanceof Mappable) {
Mappable item = (Mappable) obj;
item.setDataMap(data);
} else {
throw new FormEncodingException("Cannot cast class "
+ obj.getClass().getName() + " to Mappable");
}
} catch (Exception e) {
throw new FormEncodingException("Couldn't instantiate class "
+ className, e);
}
return obj;
}
@Override
public FormRepresentation decode(String code) throws FormEncodingException {
FormRepresentation form = new FormRepresentation();
JSONValue json = JSONParser.parseLenient(code);
if (json.isObject() != null) {
JSONObject jsonObj = json.isObject();
if (jsonObj.get("action").isString() != null) {
form.setAction(jsonObj.get("action").isString().stringValue());
}
if (jsonObj.get("documentation").isString() != null) {
form.setDocumentation(jsonObj.get("documentation").isString()
.stringValue());
}
if (jsonObj.get("enctype").isString() != null) {
form.setEnctype(jsonObj.get("enctype").isString().stringValue());
}
if (jsonObj.get("lastModified").isNumber() != null) {
form.setLastModified(Double.valueOf(
jsonObj.get("lastModified").isNumber().doubleValue())
.longValue());
} else if (jsonObj.get("lastModified").isString() != null) {
form.setLastModified(Double.valueOf(
jsonObj.get("lastModified").isString().stringValue())
.longValue());
}
if (jsonObj.get("method").isString() != null) {
form.setMethod(jsonObj.get("method").isString().stringValue());
}
if (jsonObj.get("name").isString() != null) {
form.setName(jsonObj.get("name").isString().stringValue());
}
if (jsonObj.get("taskId").isString() != null) {
form.setTaskId(jsonObj.get("taskId").isString().stringValue());
}
if (jsonObj.get("processName").isString() != null) {
form.setProcessName(jsonObj.get("processName").isString()
.stringValue());
}
form.setFormItems(decodeItems(jsonObj.get("formItems")));
form.setFormValidations(decodeValidations(jsonObj
.get("formValidations")));
form.setInputs(decodeInputs(jsonObj.get("inputs")));
form.setOutputs(decodeOutputs(jsonObj.get("outputs")));
form.setOnLoadScripts(decodeScripts(jsonObj.get("onLoadScripts")));
form.setOnSubmitScripts(decodeScripts(jsonObj
.get("onSubmitScripts")));
}
return form;
}
@Override
@SuppressWarnings("unchecked")
public Map<String, List<MenuItemDescription>> decodeMenuItemsMap(String json)
throws FormEncodingException {
JSONObject jsonObj = JSONParser.parseLenient(json).isObject();
Map<String, Object> dataMap = asMap(jsonObj);
Map<String, List<MenuItemDescription>> retval = null;
if (dataMap != null) {
retval = new HashMap<String, List<MenuItemDescription>>();
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
List<MenuItemDescription> itemsList = new ArrayList<MenuItemDescription>();
String key = entry.getKey();
Object obj = entry.getValue();
if (obj != null) {
List<Object> itemsMapList = (List<Object>) obj;
for (Object itemObj : itemsMapList) {
Map<String, Object> itemDescMap = (Map<String, Object>) itemObj;
MenuItemDescription desc = new MenuItemDescription();
desc.setDataMap(itemDescMap);
itemsList.add(desc);
}
}
retval.put(key, itemsList);
}
}
return retval;
}
@Override
public FormItemRepresentation decodeItem(String json)
throws FormEncodingException {
JSONValue jsonValue = JSONParser.parseLenient(json);
if (jsonValue.isObject() != null) {
JSONObject jsonObj = jsonValue.isObject();
Map<String, Object> dataMap = asMap(jsonObj);
return (FormItemRepresentation) decode(dataMap);
} else {
throw new FormEncodingException("Expected JSON Object: "
+ jsonValue);
}
}
public Map<String, InputData> decodeInputs(JSONValue json)
throws FormEncodingException {
Map<String, InputData> retval = new HashMap<String, InputData>();
if (json != null && json.isObject() != null) {
for (String key : json.isObject().keySet()) {
JSONValue value = json.isObject().get(key);
if (value.isObject() != null) {
JSONObject jsonObj = value.isObject();
retval.put(key, (InputData) decode(asMap(jsonObj)));
}
}
}
return retval;
}
public Map<String, OutputData> decodeOutputs(JSONValue json)
throws FormEncodingException {
Map<String, OutputData> retval = new HashMap<String, OutputData>();
if (json != null && json.isObject() != null) {
for (String key : json.isObject().keySet()) {
JSONValue value = json.isObject().get(key);
if (value.isObject() != null) {
JSONObject jsonObj = value.isObject();
retval.put(key, (OutputData) decode(asMap(jsonObj)));
}
}
}
return retval;
}
public List<FBScript> decodeScripts(JSONValue json)
throws FormEncodingException {
List<FBScript> retval = new ArrayList<FBScript>();
if (json != null && json.isArray() != null) {
JSONArray array = json.isArray();
for (int index = 0; index < array.size(); index++) {
JSONValue elem = array.get(index);
JSONObject jsonObj = elem.isObject();
retval.add((FBScript) decode(asMap(jsonObj)));
}
}
return retval;
}
public List<FormItemRepresentation> decodeItems(JSONValue json)
throws FormEncodingException {
List<FormItemRepresentation> retval = new ArrayList<FormItemRepresentation>();
if (json != null && json.isArray() != null) {
JSONArray array = json.isArray();
for (int index = 0; index < array.size(); index++) {
JSONValue elem = array.get(index);
JSONObject jsonObj = elem.isObject();
retval.add((FormItemRepresentation) decode(asMap(jsonObj)));
}
}
return retval;
}
public List<FBValidation> decodeValidations(JSONValue json)
throws FormEncodingException {
List<FBValidation> retval = new ArrayList<FBValidation>();
if (json != null && json.isArray() != null) {
JSONArray array = json.isArray();
for (int index = 0; index < array.size(); index++) {
JSONValue elem = array.get(index);
JSONObject jsonObj = elem.isObject();
retval.add((FBValidation) decode(asMap(jsonObj)));
}
}
return retval;
}
private Map<String, Object> asMap(JSONObject jsonObj) {
Map<String, Object> retval = new HashMap<String, Object>();
for (String key : jsonObj.keySet()) {
JSONValue value = jsonObj.get(key);
retval.put(key, fromJsonValue(value));
}
return retval;
}
private List<Object> asList(JSONArray array) {
List<Object> retval = new ArrayList<Object>();
if (array != null) {
for (int index = 0; index < array.size(); index++) {
retval.add(fromJsonValue(array.get(index)));
}
}
return retval;
}
private Object fromJsonValue(JSONValue elem) {
if (elem.isString() != null) {
return elem.isString().stringValue();
} else if (elem.isNumber() != null) {
return elem.isNumber().doubleValue();
} else if (elem.isArray() != null) {
return asList(elem.isArray());
} else if (elem.isNull() != null) {
return null;
} else if (elem.isObject() != null) {
return asMap(elem.isObject());
} else {
return "";
}
}
}