X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.document.server%2Fsrc%2Forg%2Fsimantics%2Fdocument%2Fserver%2Fclient%2FDocumentClient.java;fp=bundles%2Forg.simantics.document.server%2Fsrc%2Forg%2Fsimantics%2Fdocument%2Fserver%2Fclient%2FDocumentClient.java;h=be4e44bdd5a82ca6b89afcf04f0dcb6594a40b4f;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/client/DocumentClient.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/client/DocumentClient.java new file mode 100644 index 000000000..be4e44bdd --- /dev/null +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/client/DocumentClient.java @@ -0,0 +1,213 @@ +package org.simantics.document.server.client; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; + +import org.simantics.db.common.procedure.adapter.ListenerAdapter; +import org.simantics.db.common.procedure.adapter.ListenerSupport; +import org.simantics.db.layer0.variable.ProxyChildVariable; +import org.simantics.document.server.DocumentHistoryCollector; +import org.simantics.document.server.JSONObject; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.threads.IThreadWorkQueue; + +abstract public class DocumentClient implements Document { + + protected HashMap widgetData = new HashMap(); + private WidgetMapping mapping; + private CommandMapping commandMapping; + + public DocumentClient(WidgetMapping mapping, CommandMapping commandMapping) { + this.mapping = mapping; + this.commandMapping = commandMapping; + } + + @Override + public WidgetManager getManager(JSONObject object) { + return mapping.getWidget(object.getType()); + } + + @Override + public WidgetData getWidget(String id) { + return widgetData.get(id); + } + + abstract public IThreadWorkQueue thread(); + + protected void updateDocument(Collection objects) { + + ArrayList updatedData = new ArrayList(); + // Cache data + for (JSONObject object : objects) { + WidgetData datum = widgetData.get(object.getId()); + if(datum == null) { + datum = new WidgetData(this, null, object); + widgetData.put(object.getId(), datum); + } else { + // This could replace changed information instead of replacing the whole object + datum.object = object; + } + updatedData.add(datum); + } + + // Create widgets + for(WidgetData datum : updatedData) { + createElementIfNecessary(datum); + } + + HashSet updatedParents = new HashSet(); + + // Update parent hierarchy + for(WidgetData datum : updatedData) { + updateChildmaps(datum, updatedParents); + } + + updateTree(updatedParents); + + // Set values + for(WidgetData datum : updatedData) { + datum.updateProperties(); + datum.updateCommands(); + } + + } + + private void createElementIfNecessary(WidgetData data) { + if(data.widget == null) { + data.widget = data.createElement(); + } + } + + private void updateChildmaps(WidgetData data, HashSet updates) { + + // Root + if(data.object == null) return; + +// System.err.println("p:" + data.object); +// Object o = data.object.getParent(); + + WidgetData parent = widgetData.get(data.object.getParent()); + +// System.out.println("parent:" + parent); + + if(parent == null) return; + + String parentOrd = data.object.getParentOrd(); + + WidgetData existing = parent.childmap.get(parentOrd); + if(!data.equals(existing)) { + updates.add(parent); + parent.childmap.put(parentOrd, data); + } + + } + + protected void updateTree(HashSet updates) { + + if(updates.isEmpty()) return; + + ArrayList updateList = new ArrayList(updates); + Collections.sort(updateList, new Comparator() { + + private boolean isParent(WidgetData data, WidgetData possibleParent) { + WidgetData parent = widgetData.get(data.object.getParent()); + if(parent == null) return false; + else if(parent == possibleParent) return true; + else return isParent(parent, possibleParent); + } + + @Override + public int compare(WidgetData arg0, WidgetData arg1) { + if(arg0 == arg1) return 0; + else if( isParent(arg0, arg1) ) return 1; + else if( isParent(arg1, arg0) ) return -1; + else return 0; + } + + }); + + for(WidgetData d : updateList) d.updateChildren(); + + } + + public class DocumentListener extends ListenerAdapter { + + int revision = -1; + + final private ListenerSupport support; + final private String document; + final private String input; + private boolean performing = false; + + public DocumentListener(ListenerSupport support, String document, String input) { + this.support = support; + this.document = document; + this.input = input; + } + + public synchronized void perform() { + if(performing) return; + performing = true; + try { + Pair> content = DocumentHistoryCollector.getContent(DocumentListener.this, document + "/" + ProxyChildVariable.CONTEXT_BEGIN + input + "/" + ProxyChildVariable.CONTEXT_END, revision); + revision = content.first; + updateDocument(content.second); + } finally { + performing = false; + } + } + + Runnable updater = new Runnable() { + + @Override + public void run() { + perform(); +// Pair> content = DocumentHistoryCollector.getContent(DocumentListener.this, document + "/???" + input + "/???", revision); +// revision = content.first; +// updateDocument(content.second); + } + + }; + + @Override + public void execute(Integer result) { + IThreadWorkQueue thread = thread(); + if(thread.currentThreadAccess()) thread.syncExec(updater); + else thread.asyncExec(updater); + } + + @Override + public boolean isDisposed() { + return support.isDisposed(); + } + + }; + + public void track(ListenerSupport support, String document, String input) { + + new DocumentListener(support, document, input).perform(); + +// DocumentHistoryCollector.register(location, listener); +// listener.execute(-1); + + } + + WidgetData getRoot() { + return widgetData.get("root"); + } + + @SuppressWarnings("unchecked") + T getRootWidget() { + return (T)getRoot().widget; + } + + @Override + public CommandManager getCommandManager(JSONObject object) { + return commandMapping.getCommandManager(object.getType()); + } + +}