package org.joget.plugin.json;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.joget.plugin.base.DefaultPlugin;
import org.joget.plugin.base.PluginProperty;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.joget.commons.util.LogUtil;
import org.joget.commons.util.StringUtil;
import org.joget.form.model.Form;
import org.joget.form.model.service.FormManager;
import org.joget.plugin.base.ApplicationPlugin;
import org.joget.plugin.base.PluginManager;
import org.joget.workflow.model.WorkflowAssignment;
import org.joget.workflow.model.service.WorkflowManager;
import org.joget.workflow.util.WorkflowUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
public class JsonPlugin extends DefaultPlugin implements ApplicationPlugin {
public static final String TYPE_JAVASCRIPT = "JavaScript";
public static final String TYPE_HTML = "HTML";
public String getName() {
return "JSON Plugin";
}
public String getDescription() {
return "Reads a JSON feed URL, and inserts formatted data into form data table or workflow variable";
}
public String getVersion() {
return "1.0.8";
}
public PluginProperty[] getPluginProperties() {
PluginProperty[] properties = new PluginProperty[]{
new PluginProperty("formDataTable", "Form Data Table", PluginProperty.TYPE_TEXTFIELD, null, null),
new PluginProperty("formDataTableColumn", "Form Data Table Column", PluginProperty.TYPE_TEXTFIELD, null, null),
new PluginProperty("workflowVariable", "Workflow Variable Name", PluginProperty.TYPE_TEXTFIELD, null, null),
new PluginProperty("jsonUrl", "Json Feed URL", PluginProperty.TYPE_TEXTFIELD, null, null),
new PluginProperty("formatterType", "Formatter Type", PluginProperty.TYPE_RADIO, new String[]{TYPE_JAVASCRIPT, TYPE_HTML}, null),
new PluginProperty("formatter", "Formatter", PluginProperty.TYPE_TEXTAREA, null, null)
};
return properties;
}
public Object execute(Map properties) {
PluginManager pluginManager = (PluginManager) properties.get("pluginManager");
WorkflowAssignment wfAssignment = (WorkflowAssignment) properties.get("workflowAssignment");
String formDataTable = (String) properties.get("formDataTable");
String formDataTableColumn = (String) properties.get("formDataTableColumn");
String jsonUrl = (String) properties.get("jsonUrl");
String formatterType = (String) properties.get("formatterType");
String formatter = (String) properties.get("formatter");
String workflowVariable = (String) properties.get("workflowVariable");
GetMethod get = null;
try {
HttpClient client = new HttpClient();
jsonUrl = WorkflowUtil.processVariable(jsonUrl, formDataTable, wfAssignment);
jsonUrl = StringUtil.encodeUrlParam(jsonUrl);
get = new GetMethod(jsonUrl);
client.executeMethod(get);
InputStream in = get.getResponseBodyAsStream();
String jsonResponse = streamToString(in);
if (formatterType != null && !formatterType.trim().equals("")) {
String formattedOutput = "";
if (formatterType.equals(TYPE_JAVASCRIPT)) {
formattedOutput = processJavaScript(formatter, jsonResponse);
} else {
formattedOutput = processHtml(formatter, jsonResponse);
}
FormManager formManager = (FormManager) pluginManager.getBean("formManager");
Form form = formManager.loadDynamicFormByProcessId(formDataTable, wfAssignment.getProcessId());
if (form != null) {
form.setTableName(formDataTable);
form.setValueOfCustomField(formDataTableColumn, formattedOutput);
formManager.saveOrUpdateDynamicForm(form);
}
if (workflowVariable != null && !workflowVariable.trim().equals("")) {
WorkflowManager workflowManager = (WorkflowManager) pluginManager.getBean("workflowManager");
workflowManager.activityVariable(wfAssignment.getActivityId(), workflowVariable, formattedOutput);
}
}
} catch (Exception ex) {
LogUtil.error(getClass().getName(), ex, "");
} finally {
if (get != null) {
get.releaseConnection();
}
}
return null;
}
public String processJavaScript(String script, String json) {
Context cx = Context.enter();
try {
String evalObj = "var obj = " + json + ";";
Scriptable scope = cx.initStandardObjects();
Object result = cx.evaluateString(scope, evalObj + script, "JsonPlugin", 1, null);
return Context.toString(result);
} catch (Exception ex) {
LogUtil.error(getClass().getName(), ex, "");
} finally {
Context.exit();
}
return "";
}
public String processHtml(String target, String json) throws JSONException {
Pattern pattern = Pattern.compile("\\#([^#])*\\#");
Matcher matcher = pattern.matcher(target);
List<String> varList = new ArrayList<String>();
while (matcher.find()) {
varList.add(matcher.group());
}
for (String var : varList) {
try {
String tempVar = var.replaceAll("#", "");
if (tempVar.startsWith("obj")) {
tempVar = tempVar.replace("obj.", "");
String[] chain = tempVar.split("\\.");
JSONObject obj = new JSONObject(json);
int i = 0;
for (i = 0; i < chain.length - 1; i++) {
String tempChain = chain[i];
if (tempChain.indexOf("[") != -1 && tempChain.indexOf("]") != -1) {
int firstIndex = tempChain.indexOf("[");
int lastIndex = tempChain.indexOf("]");
Integer index = Integer.parseInt(tempChain.substring(firstIndex + 1, lastIndex));
tempChain = tempChain.substring(0, firstIndex);
JSONArray tempArray = obj.getJSONArray(tempChain);
obj = tempArray.getJSONObject(index);
} else {
obj = obj.getJSONObject(chain[i]);
}
}
target = target.replaceAll(StringUtil.escapeRegex(var), obj.getString(chain[i]));
}
} catch (Exception ex) {
target = target.replaceAll(StringUtil.escapeRegex(var), "");
}
}
return target;
}
public String streamToString(InputStream in) {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
LogUtil.error(getClass().getName(), e, "");
}
}
return sb.toString();
}
}