/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.oobd.base.uihandler;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import org.oobd.base.*;
import org.oobd.base.support.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.JSONException;
import org.oobd.base.scriptengine.OobdScriptengine;
import org.oobd.base.visualizer.Visualizer;
/**
* generic abstract for the implementation of scriptengines
*
* @author steffen
*/
abstract public class LocalOobdUIHandler extends OobdUIHandler {
final HashMap<String, ArrayList<Visualizer>> visualizers = new HashMap<String, ArrayList<Visualizer>>();// /<stores all available visalizers
IFui userInterface;
public static String publicName() {
/* the abstract class also needs to have this method, because it's also loaded during dynamic loading, and the empty return string
** is the indicator for this abstract class
*/
return "LocalOobdUIHandler";
}
public LocalOobdUIHandler(String myID, Core myCore, IFsystem mySystem, String name) {
super(myID, myCore, mySystem, name);
userInterface = myCore.getUiIF();
Core.getSingleInstance().writeDataPool(OOBDConstants.DP_WEBUI_WS_READY_SIGNAL, true);
Logger.getLogger(LocalOobdUIHandler.class.getName()).log(Level.CONFIG, "Local UIHandler object created: {0}", id);
}
Onion actionRequest(Onion myOnion) {
try {
if (myOnion.isType(CM_VISUALIZE)) {
userInterface.visualize(myOnion);
return null;
}
if (myOnion.isType(CM_VALUE)) {
handleValue(myOnion);
return null;
}
if (myOnion.isType(CM_IOINPUT)) {
openTempFile(myOnion);
return new Onion();
}
if (myOnion.isType(CM_UPDATE)) {
core.transferMsg(new Message(this, myOnion.getString("to"), myOnion));
return null;
}
if (myOnion.isType(CM_PAGE)) {
userInterface.openPage(myOnion.getOnionString("owner"),
myOnion.getOnionString("name"), 1, 1);
return null;
}
if (myOnion.isType(CM_PAGEDONE)) {
userInterface.openPageCompleted(
myOnion.getOnionString("owner"),
myOnion.getOnionString("name"));
return null;
}
if (myOnion.isType(CM_WRITESTRING)) {
String modifier = myOnion.getOnionString("modifier"); // an absolutely work around. Here's is why: https://github.com/stko/oobd/issues/164
if (modifier == null) {
modifier = "";
}
userInterface.sm(Base64Coder.decodeString(myOnion.getOnionString("data")), Base64Coder.decodeString(modifier));
return null;
}
if (myOnion.isType(CM_PARAM)) {
return userInterface.requestParamInput(myOnion);
}
} catch (org.json.JSONException e) {
Logger.getLogger(Core.class.getName()).log(Level.SEVERE,
"JSON exception..");
return null;
}
return null;
}
public void handleMsg() {
Message thisMsg;
while ((thisMsg = this.getMsgPort().getMsg(0)) != null) { // just waiting
// and handling
// messages
Onion answer = actionRequest(thisMsg.getContent());
if (answer != null) {
try {
thisMsg.setContent(thisMsg.getContent().setValue("replyID",
thisMsg.getContent().getInt("msgID")));
} catch (JSONException ex) {
Logger.getLogger(Core.class.getName()).log(
Level.SEVERE, null, ex);
}
thisMsg.getContent().setValue("answer", answer);
msgPort.replyMsg(thisMsg, thisMsg.getContent());
}
}
updateVisualizers();
}
/**
* \brief add generated visualizers to global list
*
* several owners (=scriptengines) do have their own visualizers. This is
* stored in the visualizers hash
*
* @param owner who owns the visualizer
* @param vis the visualizer
*/
public void addVisualizer(String owner, Visualizer vis) {
if (visualizers.containsKey(owner)) {
((ArrayList) visualizers.get(owner)).add(vis);
} else {
ArrayList ar = new ArrayList();
ar.add(vis);
visualizers.put(owner, ar);
}
}
/**
* \brief Tells Value to all visualizers of a scriptengine
*
* @param value Onion containing value and scriptengine
*
*/
public void handleValue(Onion value) {
String owner = value.getOnionString("owner/name"); // who's the owner of
// that value?
if (owner == null) {
Logger.getLogger(Core.class.getName()).log(Level.WARNING,
"onion id does not contain name");
} else {
ArrayList affectedVisualizers = visualizers.get(owner); // which
// visualizers
// belong to
// that
// owner
if (affectedVisualizers != null) {
Iterator visItr = affectedVisualizers.iterator();
while (visItr.hasNext()) {
Visualizer vis = (Visualizer) visItr.next();
vis.setValue(value); // send the value to all visualisers of
// that owner
}
}
}
}
/**
* \brief Tells Value to all visualizers of a scriptengine
*
* @param value Onion containing value and scriptengine
*
*/
public void openTempFile(Onion value) {
InputStreamReader myInputStream = null;
String myFileName = null;
try {
String owner = value.getOnionString("owner/name"); // who's the owner of
// that value?
if (owner == null) {
Logger.getLogger(Core.class.getName()).log(Level.WARNING,
"onion id does not contain name");
return;
}
String filePath = Base64Coder.decodeString(value.getOnionString("filepath"));
String fileExtension = Base64Coder.decodeString(value.getOnionString("extension"));
String fileMessage = Base64Coder.decodeString(value.getOnionString("message"));
if (fileMessage.equalsIgnoreCase("html")) {
myFileName = filePath;
URL url = new URL(filePath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int HttpResult = conn.getResponseCode();
if (HttpResult == HttpURLConnection.HTTP_OK) {
myInputStream = new InputStreamReader(conn.getInputStream(), "utf-8");
} else {
System.err.println(conn.getResponseMessage());
}
} else {
if (fileMessage.equalsIgnoreCase("json")) {
myFileName = filePath;
URL url = new URL(filePath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-Type", "application/json; charset=utf8");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestMethod("POST");
conn.connect();
OutputStream os = conn.getOutputStream();
os.write(fileExtension.getBytes("UTF-8"));
os.close();
int HttpResult = conn.getResponseCode();
if (HttpResult == HttpURLConnection.HTTP_OK) {
myInputStream = new InputStreamReader(conn.getInputStream(), "utf-8");
} else {
System.err.println(conn.getResponseMessage());
}
} else {
if ("direct".equalsIgnoreCase(fileMessage)) {
myFileName = filePath;
} else {
myFileName = getCore().getSystemIF().doFileSelector(filePath, fileExtension, fileMessage, false);
}
if (myFileName != null) {
try {
myFileName=getCore().getSystemIF().generateUIFilePath(FT_SCRIPT, myFileName);
myInputStream = new FileReader(getCore().getSystemIF().generateUIFilePath(FT_SCRIPT, myFileName));
} catch (FileNotFoundException ex) {
Logger.getLogger(LocalOobdUIHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
if (myInputStream != null) {
OobdScriptengine actEngine = getCore().getScriptEngine();
getCore().getSystemIF().createEngineTempInputFile(actEngine);
actEngine.fillTempInputFile(myInputStream);
} else {
myFileName = "";
}
} catch (FileNotFoundException ex) {
} catch (IOException ex) {
}
value.setValue("result", Base64Coder.encodeString(myFileName));
}
/**
* \brief updates all visualizers
*
* to not having several UI refreshes in parallel, update requests are only
* be collected for each visualizer and only been refreshed when the central
* core raises this update event.
*
*
*
*/
public void updateVisualizers() {
synchronized (visualizers) { // Collection<ArrayList<Visualizer>> c =
// Collections
// .synchronizedCollection(visualizers.values());
Collection<ArrayList<Visualizer>> c = visualizers.values();
// synchronized (c) {
// obtain an Iterator for Collection
Iterator<ArrayList<Visualizer>> itr;
// iterate through HashMap values iterator
// run through the 3 update states: 0: start 1: update data 2:
// finish
for (int i = 0; i < 3; i++) {
itr = c.iterator();
while (itr.hasNext()) {
ArrayList<Visualizer> engineVisualizers = itr.next();
boolean somethingToRemove = false;
Iterator<Visualizer> visItr = engineVisualizers.iterator();
// synchronized (visItr) {
while (visItr.hasNext()) {
Visualizer vis = visItr.next();
if (vis != null) {
synchronized (vis) {
if (vis.getRemoved()) {
somethingToRemove = true;
} else {
vis.doUpdate(i);
}
}
}
}
// }
synchronized (engineVisualizers) {
if (somethingToRemove) {
int del = 0;
while (del < engineVisualizers.size()) {
if (engineVisualizers.get(del).getRemoved()) {
engineVisualizers.remove(del);
}
del++;
}
}
}
}
}
// }
}
}
}