From f5942773ec56fd2cfe3b0f508d3500c9de6dce18 Mon Sep 17 00:00:00 2001 From: David Huynh Date: Thu, 11 Feb 2010 06:44:48 +0000 Subject: [PATCH] Still more work on the protograph, toward being able to build and save a protograph, but it's not working yet. git-svn-id: http://google-refine.googlecode.com/svn/trunk@89 7d457c2a-affb-35e4-300a-418c747d4874 --- .../metaweb/gridworks/GridworksServlet.java | 7 +- .../commands/edit/SaveProtographCommand.java | 42 +++ .../commands/info/GetColumnModelCommand.java | 28 -- .../commands/info/GetModelsCommand.java | 44 +++ .../com/metaweb/gridworks/model/Project.java | 2 + .../operations/SaveProtographOperation.java | 69 ++++ .../gridworks/protograph/AnonymousNode.java | 2 +- .../gridworks/protograph/CellKeyNode.java | 31 ++ .../gridworks/protograph/CellNode.java | 8 +- .../gridworks/protograph/CellTopicNode.java | 22 +- .../gridworks/protograph/CellValueNode.java | 6 +- .../protograph/FreebaseTopicNode.java | 16 +- .../metaweb/gridworks/protograph/Node.java | 4 +- .../gridworks/protograph/NodeWithLinks.java | 5 + .../gridworks/protograph/Protograph.java | 132 ++++++++ .../gridworks/protograph/ValueNode.java | 2 +- src/main/webapp/project.html | 2 +- src/main/webapp/scripts/project.js | 6 +- src/main/webapp/scripts/project/menu-bar.js | 12 +- .../scripts/project/schema-alignment.js | 307 ++++++++++++++---- src/main/webapp/scripts/util/dom.js | 37 +++ 21 files changed, 667 insertions(+), 117 deletions(-) create mode 100644 src/main/java/com/metaweb/gridworks/commands/edit/SaveProtographCommand.java delete mode 100644 src/main/java/com/metaweb/gridworks/commands/info/GetColumnModelCommand.java create mode 100644 src/main/java/com/metaweb/gridworks/commands/info/GetModelsCommand.java create mode 100644 src/main/java/com/metaweb/gridworks/model/operations/SaveProtographOperation.java create mode 100644 src/main/java/com/metaweb/gridworks/protograph/CellKeyNode.java create mode 100644 src/main/java/com/metaweb/gridworks/protograph/NodeWithLinks.java create mode 100644 src/main/java/com/metaweb/gridworks/protograph/Protograph.java create mode 100644 src/main/webapp/scripts/util/dom.js diff --git a/src/main/java/com/metaweb/gridworks/GridworksServlet.java b/src/main/java/com/metaweb/gridworks/GridworksServlet.java index e40edf63e..dc5dd7d22 100644 --- a/src/main/java/com/metaweb/gridworks/GridworksServlet.java +++ b/src/main/java/com/metaweb/gridworks/GridworksServlet.java @@ -20,12 +20,13 @@ import com.metaweb.gridworks.commands.edit.CreateProjectCommand; import com.metaweb.gridworks.commands.edit.DoTextTransformCommand; import com.metaweb.gridworks.commands.edit.JoinMultiValueCellsCommand; import com.metaweb.gridworks.commands.edit.RemoveColumnCommand; +import com.metaweb.gridworks.commands.edit.SaveProtographCommand; import com.metaweb.gridworks.commands.edit.SplitMultiValueCellsCommand; import com.metaweb.gridworks.commands.edit.UndoRedoCommand; import com.metaweb.gridworks.commands.info.ComputeFacetsCommand; import com.metaweb.gridworks.commands.info.ExportRowsCommand; import com.metaweb.gridworks.commands.info.GetAllProjectMetadataCommand; -import com.metaweb.gridworks.commands.info.GetColumnModelCommand; +import com.metaweb.gridworks.commands.info.GetModelsCommand; import com.metaweb.gridworks.commands.info.GetHistoryCommand; import com.metaweb.gridworks.commands.info.GetProcessesCommand; import com.metaweb.gridworks.commands.info.GetProjectMetadataCommand; @@ -50,7 +51,7 @@ public class GridworksServlet extends HttpServlet { _commands.put("get-project-metadata", new GetProjectMetadataCommand()); _commands.put("get-all-project-metadata", new GetAllProjectMetadataCommand()); - _commands.put("get-column-model", new GetColumnModelCommand()); + _commands.put("get-models", new GetModelsCommand()); _commands.put("get-rows", new GetRowsCommand()); _commands.put("get-processes", new GetProcessesCommand()); _commands.put("get-history", new GetHistoryCommand()); @@ -70,6 +71,8 @@ public class GridworksServlet extends HttpServlet { _commands.put("discard-reconcile", new DiscardReconcileCommand()); _commands.put("judge-one-cell", new JudgeOneCellCommand()); + _commands.put("save-protograph", new SaveProtographCommand()); + _commands.put("preview-expression", new PreviewExpressionCommand()); _commands.put("get-expression-language-info", new GetExpressionLanguageInfoCommand()); } diff --git a/src/main/java/com/metaweb/gridworks/commands/edit/SaveProtographCommand.java b/src/main/java/com/metaweb/gridworks/commands/edit/SaveProtographCommand.java new file mode 100644 index 000000000..782563285 --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/commands/edit/SaveProtographCommand.java @@ -0,0 +1,42 @@ +package com.metaweb.gridworks.commands.edit; + +import java.io.IOException; +import java.util.Properties; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.JSONObject; + +import com.metaweb.gridworks.commands.Command; +import com.metaweb.gridworks.model.AbstractOperation; +import com.metaweb.gridworks.model.Project; +import com.metaweb.gridworks.model.operations.SaveProtographOperation; +import com.metaweb.gridworks.process.Process; +import com.metaweb.gridworks.protograph.Protograph; + +public class SaveProtographCommand extends Command { + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + try { + Project project = getProject(request); + + String jsonString = request.getParameter("protograph"); + JSONObject json = jsonStringToObject(jsonString); + Protograph protograph = Protograph.reconstruct(json); + + AbstractOperation op = new SaveProtographOperation(protograph); + Process process = op.createProcess(project, new Properties()); + + boolean done = project.processManager.queueProcess(process); + + respond(response, "{ \"code\" : " + (done ? "\"ok\"" : "\"pending\"") + " }"); + + } catch (Exception e) { + respondException(response, e); + } + } +} diff --git a/src/main/java/com/metaweb/gridworks/commands/info/GetColumnModelCommand.java b/src/main/java/com/metaweb/gridworks/commands/info/GetColumnModelCommand.java deleted file mode 100644 index d5e121c3f..000000000 --- a/src/main/java/com/metaweb/gridworks/commands/info/GetColumnModelCommand.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.metaweb.gridworks.commands.info; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.json.JSONException; - -import com.metaweb.gridworks.commands.Command; -import com.metaweb.gridworks.model.Project; - -public class GetColumnModelCommand extends Command { - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - Project project = getProject(request); - - try { - respondJSON(response, project.columnModel); - } catch (JSONException e) { - respondException(response, e); - } - } - -} diff --git a/src/main/java/com/metaweb/gridworks/commands/info/GetModelsCommand.java b/src/main/java/com/metaweb/gridworks/commands/info/GetModelsCommand.java new file mode 100644 index 000000000..6da1da20e --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/commands/info/GetModelsCommand.java @@ -0,0 +1,44 @@ +package com.metaweb.gridworks.commands.info; + +import java.io.IOException; +import java.util.Properties; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.JSONException; +import org.json.JSONWriter; + +import com.metaweb.gridworks.commands.Command; +import com.metaweb.gridworks.model.Project; + +public class GetModelsCommand extends Command { + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + Project project = getProject(request); + + try { + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Type", "application/json"); + + Properties options = new Properties(); + JSONWriter writer = new JSONWriter(response.getWriter()); + + writer.object(); + writer.key("columnModel"); project.columnModel.write(writer, options); + writer.key("protograph"); + if (project.protograph == null) { + writer.value(null); + } else { + project.protograph.write(writer, options); + } + writer.endObject(); + } catch (JSONException e) { + respondException(response, e); + } + } + +} diff --git a/src/main/java/com/metaweb/gridworks/model/Project.java b/src/main/java/com/metaweb/gridworks/model/Project.java index 15e40f322..e4f5e95a8 100644 --- a/src/main/java/com/metaweb/gridworks/model/Project.java +++ b/src/main/java/com/metaweb/gridworks/model/Project.java @@ -11,6 +11,7 @@ import java.util.List; import com.metaweb.gridworks.expr.ExpressionUtils; import com.metaweb.gridworks.history.History; import com.metaweb.gridworks.process.ProcessManager; +import com.metaweb.gridworks.protograph.Protograph; public class Project implements Serializable { private static final long serialVersionUID = -5089046824819472570L; @@ -20,6 +21,7 @@ public class Project implements Serializable { final public ColumnModel columnModel = new ColumnModel(); final public List rows = new ArrayList(); final public History history; + public Protograph protograph; transient public ProcessManager processManager; diff --git a/src/main/java/com/metaweb/gridworks/model/operations/SaveProtographOperation.java b/src/main/java/com/metaweb/gridworks/model/operations/SaveProtographOperation.java new file mode 100644 index 000000000..a057c12a3 --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/model/operations/SaveProtographOperation.java @@ -0,0 +1,69 @@ +package com.metaweb.gridworks.model.operations; + +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; + +import com.metaweb.gridworks.history.Change; +import com.metaweb.gridworks.history.HistoryEntry; +import com.metaweb.gridworks.model.AbstractOperation; +import com.metaweb.gridworks.model.Project; +import com.metaweb.gridworks.process.Process; +import com.metaweb.gridworks.process.QuickHistoryEntryProcess; +import com.metaweb.gridworks.protograph.Protograph; + +public class SaveProtographOperation implements AbstractOperation { + private static final long serialVersionUID = 3134524625206033285L; + + final protected Protograph _protograph; + + public SaveProtographOperation( + Protograph protograph + ) { + _protograph = protograph; + } + + public Process createProcess(Project project, Properties options) + throws Exception { + + String description = "Save schema-alignment protograph"; + + Change change = new ProtographChange(_protograph); + HistoryEntry historyEntry = new HistoryEntry( + project, description, this, change); + + return new QuickHistoryEntryProcess(project, historyEntry); + } + + public void write(JSONWriter writer, Properties options) + throws JSONException { + // TODO Auto-generated method stub + + } + + + static public class ProtographChange implements Change { + private static final long serialVersionUID = -564820111174473901L; + + final protected Protograph _newProtograph; + protected Protograph _oldProtograph; + + public ProtographChange(Protograph protograph) { + _newProtograph = protograph; + } + + public void apply(Project project) { + synchronized (project) { + _oldProtograph = project.protograph; + project.protograph = _newProtograph; + } + } + + public void revert(Project project) { + synchronized (project) { + project.protograph = _oldProtograph; + } + } + } +} diff --git a/src/main/java/com/metaweb/gridworks/protograph/AnonymousNode.java b/src/main/java/com/metaweb/gridworks/protograph/AnonymousNode.java index 7fb1498a7..7352af171 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/AnonymousNode.java +++ b/src/main/java/com/metaweb/gridworks/protograph/AnonymousNode.java @@ -5,7 +5,7 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; -public class AnonymousNode extends Node { +public class AnonymousNode implements Node { private static final long serialVersionUID = -6956243664838720646L; final public FreebaseType type; diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellKeyNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellKeyNode.java new file mode 100644 index 000000000..2d77a19b3 --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/protograph/CellKeyNode.java @@ -0,0 +1,31 @@ +package com.metaweb.gridworks.protograph; + +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONWriter; + +public class CellKeyNode extends CellNode { + private static final long serialVersionUID = 1684854896739592911L; + + final public FreebaseTopic namespace; + + public CellKeyNode( + String columnName, + FreebaseTopic namespace + ) { + super(columnName); + + this.namespace = namespace; + } + + public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("nodeType"); writer.value("cell-as-key"); + writer.key("columnName"); writer.value(columnName); + writer.key("namespace"); namespace.write(writer, options); + writer.endObject(); + } +} diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellNode.java index 24b56f796..da076828b 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/CellNode.java +++ b/src/main/java/com/metaweb/gridworks/protograph/CellNode.java @@ -1,13 +1,13 @@ package com.metaweb.gridworks.protograph; -abstract public class CellNode extends Node { +abstract public class CellNode implements Node { private static final long serialVersionUID = 5820786756175547307L; - final public int cellIndex; + final public String columnName; public CellNode( - int cellIndex + String columnName ) { - this.cellIndex = cellIndex; + this.columnName = columnName; } } diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java index 41564c4f9..ab7869a76 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java +++ b/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java @@ -1,22 +1,25 @@ package com.metaweb.gridworks.protograph; +import java.util.LinkedList; +import java.util.List; import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; -public class CellTopicNode extends CellNode { +public class CellTopicNode extends CellNode implements NodeWithLinks { private static final long serialVersionUID = 1684854896739592911L; final public boolean createForNoReconMatch; final public FreebaseType type; + final public List links = new LinkedList(); public CellTopicNode( - int cellIndex, + String columnName, boolean createForNoReconMatch, FreebaseType type ) { - super(cellIndex); + super(columnName); this.createForNoReconMatch = createForNoReconMatch; this.type = type; @@ -27,9 +30,20 @@ public class CellTopicNode extends CellNode { writer.object(); writer.key("nodeType"); writer.value("cell-as-topic"); - writer.key("cellIndex"); writer.value(cellIndex); + writer.key("columnName"); writer.value(columnName); writer.key("type"); type.write(writer, options); writer.key("createUnlessRecon"); writer.value(createForNoReconMatch); + + writer.key("links"); writer.array(); + for (Link link : links) { + link.write(writer, options); + } + writer.endArray(); + writer.endObject(); } + + public void addLink(Link link) { + links.add(link); + } } diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java index 3b056cb2c..80c0237fe 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java +++ b/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java @@ -12,11 +12,11 @@ public class CellValueNode extends CellNode { final public String lang; public CellValueNode( - int cellIndex, + String columnName, String valueType, String lang ) { - super(cellIndex); + super(columnName); this.valueType = valueType; this.lang = lang; @@ -27,7 +27,7 @@ public class CellValueNode extends CellNode { writer.object(); writer.key("nodeType"); writer.value("cell-as-value"); - writer.key("cellIndex"); writer.value(cellIndex); + writer.key("columnName"); writer.value(columnName); writer.key("valueType"); writer.value(valueType); writer.key("lang"); writer.value(lang); writer.endObject(); diff --git a/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java b/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java index 1c632a9e8..68cd4c605 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java +++ b/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java @@ -1,14 +1,17 @@ package com.metaweb.gridworks.protograph; +import java.util.LinkedList; +import java.util.List; import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; -public class FreebaseTopicNode extends Node { +public class FreebaseTopicNode implements Node, NodeWithLinks { private static final long serialVersionUID = 8418548867745587387L; final public FreebaseTopic topic; + final public List links = new LinkedList(); public FreebaseTopicNode(FreebaseTopic topic) { this.topic = topic; @@ -20,6 +23,17 @@ public class FreebaseTopicNode extends Node { writer.object(); writer.key("nodeType"); writer.value("topic"); writer.key("topic"); topic.write(writer, options); + + writer.key("links"); writer.array(); + for (Link link : links) { + link.write(writer, options); + } + writer.endArray(); + writer.endObject(); } + + public void addLink(Link link) { + links.add(link); + } } diff --git a/src/main/java/com/metaweb/gridworks/protograph/Node.java b/src/main/java/com/metaweb/gridworks/protograph/Node.java index 8e3602697..8bef1a5c1 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/Node.java +++ b/src/main/java/com/metaweb/gridworks/protograph/Node.java @@ -4,7 +4,5 @@ import java.io.Serializable; import com.metaweb.gridworks.Jsonizable; -abstract public class Node implements Serializable, Jsonizable { - private static final long serialVersionUID = 2892833010059212143L; - +public interface Node extends Serializable, Jsonizable { } diff --git a/src/main/java/com/metaweb/gridworks/protograph/NodeWithLinks.java b/src/main/java/com/metaweb/gridworks/protograph/NodeWithLinks.java new file mode 100644 index 000000000..f246c5c7f --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/protograph/NodeWithLinks.java @@ -0,0 +1,5 @@ +package com.metaweb.gridworks.protograph; + +public interface NodeWithLinks { + public void addLink(Link link); +} diff --git a/src/main/java/com/metaweb/gridworks/protograph/Protograph.java b/src/main/java/com/metaweb/gridworks/protograph/Protograph.java new file mode 100644 index 000000000..70015534a --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/protograph/Protograph.java @@ -0,0 +1,132 @@ +package com.metaweb.gridworks.protograph; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; + +import com.metaweb.gridworks.Jsonizable; + +public class Protograph implements Serializable, Jsonizable { + private static final long serialVersionUID = 706700643851582450L; + + final protected List _rootNodes = new LinkedList(); + + static public Protograph reconstruct(JSONObject o) throws JSONException { + Protograph g = new Protograph(); + + JSONArray rootNodes = o.getJSONArray("rootNodes"); + int count = rootNodes.length(); + + for (int i = 0; i < count; i++) { + JSONObject o2 = rootNodes.getJSONObject(i); + Node node = reconstructNode(o2); + if (node != null) { + g._rootNodes.add(node); + } + } + + return g; + } + + static protected Node reconstructNode(JSONObject o) throws JSONException { + Node node = null; + + String nodeType = o.getString("nodeType"); + if (nodeType.startsWith("cell-as-")) { + String columnName = o.getString("columnName"); + + if ("cell-as-topic".equals(nodeType)) { + node = new CellTopicNode( + columnName, + o.getBoolean("createForNoReconMatch"), + reconstructType(o.getJSONObject("type")) + ); + } else if ("cell-as-value".equals(nodeType)) { + node = new CellValueNode( + columnName, + o.getString("valueType"), + o.getString("lang") + ); + } else if ("cell-as-key".equals(nodeType)) { + node = new CellKeyNode( + columnName, + reconstructTopic(o.getJSONObject("namespace")) + ); + } + } else if ("topic".equals(nodeType)) { + node = new FreebaseTopicNode(reconstructTopic(o.getJSONObject("topic"))); + } else if ("value".equals(nodeType)) { + node = new ValueNode( + o.get("value"), + o.getString("valueType"), + o.getString("lang") + ); + } else if ("anonymous".equals(nodeType)) { + node = new AnonymousNode(reconstructType(o.getJSONObject("type"))); + } + + if (node != null) { + if (node instanceof NodeWithLinks && o.has("links")) { + NodeWithLinks node2 = (NodeWithLinks) node; + + JSONArray links = o.getJSONArray("links"); + int linkCount = links.length(); + + for (int j = 0; j < linkCount; j++) { + JSONObject oLink = links.getJSONObject(j); + + node2.addLink(new Link( + reconstructProperty(oLink.getJSONObject("property")), + reconstructNode(oLink.getJSONObject("target")) + )); + } + } + } + + return node; + } + + static protected FreebaseProperty reconstructProperty(JSONObject o) throws JSONException { + return new FreebaseProperty( + o.getString("id"), + o.getString("name"), + reconstructType(o.getJSONObject("expected")) + ); + } + + static protected FreebaseType reconstructType(JSONObject o) throws JSONException { + return new FreebaseType( + o.getString("id"), + o.getString("name"), + o.getBoolean("cvt") + ); + } + + static protected FreebaseTopic reconstructTopic(JSONObject o) throws JSONException { + return new FreebaseTopic( + o.getString("id"), + o.getString("name") + ); + } + + public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("rootNodes"); writer.array(); + + for (Node node : _rootNodes) { + node.write(writer, options); + } + + writer.endArray(); + writer.endObject(); + } + +} diff --git a/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java b/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java index 167c1b2ee..98d42aa30 100644 --- a/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java +++ b/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java @@ -5,7 +5,7 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; -public class ValueNode extends Node { +public class ValueNode implements Node { private static final long serialVersionUID = -5626883493437735688L; final public Object value; diff --git a/src/main/webapp/project.html b/src/main/webapp/project.html index 3c82eb302..4d40f8cde 100644 --- a/src/main/webapp/project.html +++ b/src/main/webapp/project.html @@ -1,2 +1,2 @@ Gridlock -
starting up ...
\ No newline at end of file +
starting up ...
\ No newline at end of file diff --git a/src/main/webapp/scripts/project.js b/src/main/webapp/scripts/project.js index 110057aee..cfe17b0a4 100644 --- a/src/main/webapp/scripts/project.js +++ b/src/main/webapp/scripts/project.js @@ -50,9 +50,11 @@ function reinitializeProjectData(f) { function(data) { theProject.metadata = data; }, - "/command/get-column-model?" + $.param({ project: theProject.id }), null, + "/command/get-models?" + $.param({ project: theProject.id }), null, function(data) { - theProject.columnModel = data; + theProject.columnModel = data.columnModel; + theProject.protograph = data.protograph; + for (var i = 0; i < theProject.columnModel.columns.length; i++) { theProject.columnModel.columns[i].collapsed = false; } diff --git a/src/main/webapp/scripts/project/menu-bar.js b/src/main/webapp/scripts/project/menu-bar.js index 4dcf5e6eb..1b6375994 100644 --- a/src/main/webapp/scripts/project/menu-bar.js +++ b/src/main/webapp/scripts/project/menu-bar.js @@ -136,14 +136,18 @@ MenuBar.prototype._doExportRows = function() { MenuBar.prototype._doAutoSchemaAlignment = function() { //SchemaAlignment.autoAlign(); - new SchemaAlignmentDialog({ + + var protograph = theProject.protograph != null ? theProject.protograph : { rootNodes: [ { - nodeType: "existing", - column: "name", - linkages: [ + nodeType: "cell-as-topic", + links: [ ] } ] + }; + + new SchemaAlignmentDialog(protograph, function(newProtograph) { + }); }; diff --git a/src/main/webapp/scripts/project/schema-alignment.js b/src/main/webapp/scripts/project/schema-alignment.js index 0c5ef5f6f..b0c5381d6 100644 --- a/src/main/webapp/scripts/project/schema-alignment.js +++ b/src/main/webapp/scripts/project/schema-alignment.js @@ -90,19 +90,11 @@ SchemaAlignment._cleanName = function(s) { return s.replace(/\W/g, " ").replace(/\s+/g, " ").toLowerCase(); } -function SchemaAlignmentDialog(protograph) { - protograph = { - rootNodes: [ - { - nodeType: "cell-as-topic", - links: [ - ] - } - ] - }; - +function SchemaAlignmentDialog(protograph, onDone) { + this._onDone = onDone; this._originalProtograph = protograph; - this._protograph = cloneDeep(protograph); + this._protograph = cloneDeep(protograph); // this is what can be munched on + this._nodeUIs = []; this._createDialog(); }; @@ -127,8 +119,26 @@ SchemaAlignmentDialog.prototype._renderFooter = function(footer) { var self = this; $('').html("  OK  ").click(function() { - DialogSystem.dismissUntil(self._level - 1); - self._onDone(self._getNewProtograph()); + var protograph = self.getJSON(); + + $.post( + "/command/save-protograph?" + $.param({ project: theProject.id }), + { protograph: JSON.stringify(protograph) }, + function(data) { + if (data.code == "error") { + alert("Failed to save protograph"); + return; + } else if (data.code == "ok") { + ui.historyWidget.update(); + } else { + ui.processWidget.update(); + } + + DialogSystem.dismissUntil(self._level - 1); + self._onDone(prototgraph); + }, + "json" + ); }).appendTo(footer); $('').text("Cancel").click(function() { @@ -143,17 +153,31 @@ SchemaAlignmentDialog.prototype._renderBody = function(body) { this._nodeTable = $('
').addClass("schema-alignment-table-layout").appendTo(this._canvas)[0]; for (var i = 0; i < this._originalProtograph.rootNodes.length; i++) { - new SchemaAlignmentDialog.UINode( + this._nodeUIs.push(new SchemaAlignmentDialog.UINode( this._protograph.rootNodes[i], this._nodeTable, { expanded: true, mustBeCellTopic: true } - ); + )); } }; +SchemaAlignmentDialog.prototype.getJSON = function() { + var rootNodes = []; + for (var i = 0; i < this._nodeUIs.length; i++) { + var node = this._nodeUIs[i].getJSON(); + if (node != null) { + rootNodes.push(node); + } + } + + return { + rootNodes: rootNodes + }; +}; + /*---------------------------------------------------------------------- * UINode *---------------------------------------------------------------------- @@ -212,7 +236,10 @@ SchemaAlignmentDialog.UINode.prototype._renderMain = function() { } }); - if (this._node.nodeType == "cell-as-topic" || this._node.nodeType == "cell-as-value") { + if (this._node.nodeType == "cell-as-topic" || + this._node.nodeType == "cell-as-value" || + this._node.nodeType == "cell-as-key") { + if ("cellIndex" in this._node) { a.html(" cell"); @@ -385,53 +412,115 @@ SchemaAlignmentDialog.UINode.prototype._showTagDialog = function() { var body = $('
').addClass("dialog-body").appendTo(frame); var footer = $('
').addClass("dialog-footer").appendTo(frame); - /* + /*-------------------------------------------------- * Body + *-------------------------------------------------- */ - - var table = $('
') - .attr("width", "100%") - .attr("cellspacing", "10") - .attr("cellpadding", "0") - .appendTo(body)[0]; - - var tr0 = table.insertRow(0); - var tr1 = table.insertRow(1); - var tdTop = tr0.insertCell(0); - var tdRightColumn = tr0.insertCell(1); - var tdLeftColumn = tr1.insertCell(0); - var tdMiddleColumn = tr1.insertCell(1); + var html = $( + '' + + '' + + '' + + + '' + + '' + + '
' + + '

Set to Cell in Column

' + + '' + + '' + + '' + + '' + + '' + + '
' + + '

The cell\'s content will be ...

' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
name of a topic (as reconciled)
of Freebase type
create new topic if not reconciled
a literal value
of literal type
in language
a key in a namespace
in namespace
' + + '
' + + '
' + + '

Set to Anonymous Node

' + + '' + + '' + + '' + + '' + + '' + + '' + + '
of Freebase type
' + + + '

Set to Freebase Topic

' + + '' + + '' + + '' + + '' + + '' + + '' + + '
topic
' + + + '

Set to Literal Value

' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
value
value type
lang
' + + '
' + ).appendTo(body); - $(tdTop).attr("colspan", "2"); - $(tdRightColumn).attr("rowspan", "2"); + var elmtMap = DOM.bind(html, [ "divColumns" ]); - var makeNodeTypeChoice = function(label, value, checked, parent) { - var heading = $('

').appendTo(parent); - - var radio = $('') - .attr("type", "radio") - .attr("value", value) - .attr("name", "schema-align-node-dialog-node-type") - .appendTo(heading); - - if (checked) { - radio.attr("checked", "true"); - } - - $('').text(label).appendTo(heading); - }; - - makeNodeTypeChoice("Set to Cell in Column", "cell-as-topic", this._node.nodeType == "cell-as-value" || this._node.nodeType == "cell-as-topic", tdTop); - - var divColumns = $('
') - .addClass("schema-alignment-node-dialog-column-list") - .appendTo(tdLeftColumn); - var makeColumnChoice = function(column) { var div = $('
') .addClass("schema-alignment-node-dialog-column-choice") - .appendTo(divColumns); + .appendTo(elmtMap.divColumns); var radio = $('') .attr("type", "radio") @@ -449,13 +538,11 @@ SchemaAlignmentDialog.UINode.prototype._showTagDialog = function() { for (var i = 0; i < columns.length; i++) { makeColumnChoice(columns[i]); } + - makeNodeTypeChoice("Set to Anonymous Node", "anonymous", this._node.nodeType == "anonymous", tdRightColumn); - makeNodeTypeChoice("Set to Freebase Topic", "topic", this._node.nodeType == "topic", tdRightColumn); - makeNodeTypeChoice("Set to Value", "value", this._node.nodeType == "value", tdRightColumn); - - /* + /*-------------------------------------------------- * Footer + *-------------------------------------------------- */ $('').html("  OK  ").click(function() { @@ -470,7 +557,86 @@ SchemaAlignmentDialog.UINode.prototype._showTagDialog = function() { var level = DialogSystem.showDialog(frame); }; - +SchemaAlignmentDialog.UINode.prototype.getJSON = function() { + var result = null; + var getLinks = false; + + if (this._node.nodeType.match(/^cell-as-/)) { + if (!("columnName" in this._node) || this._node.columnName == null) { + return null; + } + + if (this._node.nodeType == "cell-as-topic") { + result = { + nodeType: this._node.nodeType, + columnName: this._node.columnName, + type: "type" in this._node ? cloneNode(this._node.type) : { "id" : "/common/topic", "name" : "Topic", "cvt" : false }, + createForNoReconMatch: "createForNoReconMatch" in this._node ? this._node.createForNoReconMatch : true + }; + getLinks = true; + } else if (this._node.nodeType == "cell-as-value") { + result = { + nodeType: this._node.nodeType, + columnName: this._node.columnName, + valueType: "valueType" in this._node ? this._node.valueType : "/type/text", + lang: "lang" in this._node ? this._node.lang : "/lang/en" + }; + } else if (this._node.nodeType == "cell-as-key") { + if (!("namespace" in this._node) || this._node.namespace == null) { + return null; + } + result = { + nodeType: this._node.nodeType, + columnName: this._node.columnName, + type: cloneNode(this._node.namespace) + }; + } + } else if (this._node.nodeType == "topic") { + if (!("topic" in this._node) || this._node.topic == null) { + return null; + } + result = { + nodeType: this._node.nodeType, + topic: cloneNode(this._node.topic) + }; + getLinks = true; + } else if (this._node.nodeType == "value") { + if (!("value" in this._node) || this._node.value == null) { + return null; + } + result = { + nodeType: this._node.nodeType, + value: this._node.value, + valueType: "valueType" in this._node ? this._node.valueType : "/type/text", + lang: "lang" in this._node ? this._node.lang : "/lang/en" + }; + } else if (this._node.nodeType == "anonymous") { + if (!("type" in this._node) || this._node.type == null) { + return null; + } + result = { + nodeType: this._node.nodeType, + type: cloneNode(this._node.type) + }; + getLinks = true; + } + + if (result == null) { + return null; + } + if (getLinks) { + var links = []; + for (var i = 0; i < this._linkUIs.length; i++) { + var link = this._linkUIs[i].getJSON(); + if (link != null) { + links.push(link); + } + } + result.links = links; + } + + return result; +}; /*---------------------------------------------------------------------- * UILink @@ -569,4 +735,19 @@ SchemaAlignmentDialog.UILink.prototype._showTagSuggest = function(elmt) { }, 100); }); input[0].focus(); -}; \ No newline at end of file +}; + +SchemaAlignmentDialog.UILink.prototype.getJSON = function() { + if ("property" in this._link && this._link.property != null && + "target" in this._link && this._link.target != null) { + + var targetJSON = this._targetUI.getJSON(); + if (targetJSON != null) { + return { + property: cloneNode(this._link.property), + target: targetJSON + }; + } + } + return null; +}; diff --git a/src/main/webapp/scripts/util/dom.js b/src/main/webapp/scripts/util/dom.js new file mode 100644 index 000000000..b6fdb9280 --- /dev/null +++ b/src/main/webapp/scripts/util/dom.js @@ -0,0 +1,37 @@ +var DOM = {}; + +DOM.bind = function(elmt, fields) { + var map = {}; + for (var i = 0; i < fields.length; i++) { + map[fields[i]] = null; + } + + DOM._bindDOMChildren(elmt[0], map); + + return map; +}; + +DOM._bindDOMElement = function(elmt, map) { + var id = elmt.id; + if (id != null && id.length > 0) { + if (id in map && map.hasOwnProperty(id)) { + map[id] = $(elmt); + elmt.removeAttribute("id"); + } + } + + if (elmt.hasChildNodes()) { + DOM._bindDOMChildren(elmt, map); + } +}; + +DOM._bindDOMChildren = function(elmt, map) { + var node = elmt.firstChild; + while (node != null) { + var node2 = node.nextSibling; + if (node.nodeType == 1) { + DOM._bindDOMElement(node, map); + } + node = node2; + } +}; \ No newline at end of file