package greencode.kernel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.websocket.RemoteEndpoint.Basic;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import greencode.http.HttpRequest;
import greencode.http.ViewSession;
import greencode.jscript.DOM;
import greencode.jscript.DOMHandle;
import greencode.jscript.JSExecutor;
public class DOMScanner {
final List<JSExecutor> comm = new ArrayList<JSExecutor>();
JsonObject sync;
Integer[] args;
private DOMScanner() {
}
static DOMScanner getElements(ViewSession viewSession) {
DOMScanner elements = (DOMScanner) viewSession.getAttribute("_ELEMENTS");
if (elements == null)
viewSession.setAttribute("_ELEMENTS", elements = new DOMScanner());
return elements;
}
public static void registerExecution(JSExecutor execution) {
getElements(execution.view).comm.add(execution);
}
static void setSync(GreenContext context, int uid, String varName, JSExecutor jsCommand) {
DOMScanner scan = getElements(context.getRequest().getViewSession());
JsonArray list;
if(scan.sync == null) {
scan.sync = new JsonObject();
scan.sync.add("list", list = new JsonArray());
scan.sync.addProperty("set", context.immediateSync);
scan.sync.addProperty("viewId", context.request.getViewSession().getId());
scan.sync.addProperty("cid", context.request.getConversationId());
if(!context.immediateSync) {
scan.sync.addProperty("accessCode", Thread.currentThread().hashCode());
}
} else {
list = (JsonArray) scan.sync.get("list");
}
JsonObject json = new JsonObject();
json.addProperty("uid", uid);
json.addProperty("varName", varName);
json.add("command", context.gsonInstance.toJsonTree(jsCommand));
list.add(json);
}
public static void sendElements(GreenContext context) throws IOException {
DOMScanner elements = DOMScanner.getElements(context.getRequest().getViewSession());
send(context, elements);
elements.comm.clear();
elements.args = null;
elements.sync = null;
}
static void send(GreenContext context, Object o) throws IOException {
send(context, o, context.gsonInstance);
}
static String getMsgEventId(WebSocketData wsData) {
return GreenCodeConfig.Browser.websocketSingleton ? "{-websocket-msg-:" + wsData.eventId + "}" : "";
}
static String getCloseEventId(WebSocketData wsData) {
return GreenCodeConfig.Browser.websocketSingleton ? "{-websocket-close-:" + wsData.eventId + "}" : "";
}
private static void send(GreenContext context, Object o, Gson gson) throws IOException {
final boolean isWebSocket = context.request.isWebSocket();
if(isWebSocket && !context.request.getWebSocketSession().isOpen()) {
return;
}
final StringBuilder json = new StringBuilder();
if (o != null) {
try {
json.append(context.gsonInstance.toJson(o));
} catch (Exception e) { // java.util.ConcurrentModificationException
// || java.util.NoSuchElementException
send(context, o, context.getGsonInstance());
return;
}
}
if (isWebSocket) {
Basic basicRemote = context.request.getWebSocketSession().getBasicRemote();
if (greencode.http.$HttpRequest.contentIsHtml(context.request)) {
json.insert(0, "<json style=\"display: none;\">").append("</json>");
}
String msgText = getMsgEventId(context.webSocketData) + json.toString();
// Correção temporaria.
while(true) {
try {
basicRemote.sendText(msgText);
break;
} catch (Exception e) {
try {
Thread.sleep(5);
} catch (InterruptedException e1) {
}
}
}
} else {
context.response.getWriter().write(json.insert(0, "<json style=\"display: none;\">").append("</json>").toString());
}
}
static void synchronize(final String servletPath, final HttpServletRequest httpServletRequest, ServletResponse response, final WebSocketData webSocketData) throws IOException {
final GreenContext context = new GreenContext(httpServletRequest, response, null, webSocketData);
final HttpRequest __request = context.request;
final ViewSession viewSession = __request.getViewSession();
final boolean set = Boolean.parseBoolean(__request.getParameter("set"));
final Map<Integer, DOM> DOMList = greencode.jscript.$DOMHandle.getDOMSync(viewSession);
final Map<String, List<Map<String, String>>> list = context.gsonInstance.fromJson(__request.getParameter("list"), new HashMap<String, List<Map<String, String>>>().getClass());
Map<Integer, Thread> threadList = null;
Thread th = null;
Integer accessCode = null;
if(!set) {
threadList = GreenContext.getThreadList(__request.getConversation());
accessCode = Integer.parseInt(__request.getParameter("accessCode"));
th = threadList.get(accessCode);
}
synchronized(set ? Object.class : th) {
for (Entry<String, List<Map<String, String>>> o : list.entrySet()) {
final Integer uid = Integer.parseInt(o.getKey());
DOM dom = DOMList.get(uid);
synchronized (dom) {
DOMList.remove(uid);
List<Map<String, String>> attrs = o.getValue();
StringBuilder strInforme = new StringBuilder("[Synchronized] {uid=" + uid);
if(attrs.size() == 0) {
strInforme.append(":Not Found}");
} else {
strInforme.append(", attrs = [");
boolean first = true;
for (Map<String, String> attr : attrs) {
final String varName = attr.get("name");
final String value = attr.get("var");
if(!first) {
strInforme.append(", ");
} else {
first = false;
}
if(set) {
DOMHandle.setVariableValue(dom, varName, value);
} else {
try {
Class<?> cast = attr.get("cast") != null ? Class.forName(attr.get("cast")) : null;
DOMHandle.setVariableValue(dom, varName, greencode.jscript.$DOMHandle.setVariableValue(context, dom, varName, cast, value));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
strInforme.append("{varName=" + varName + ", value=" + value+"}");
}
strInforme.append("]}");
}
Console.log(strInforme.toString());
if(set) {
dom.notify();
}
}
}
if(!set) {
th.notify();
threadList.remove(accessCode);
}
}
context.destroy();
}
}