diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellNode.java
index 9213e1910..24b56f796 100644
--- a/src/main/java/com/metaweb/gridworks/protograph/CellNode.java
+++ b/src/main/java/com/metaweb/gridworks/protograph/CellNode.java
@@ -1,31 +1,13 @@
package com.metaweb.gridworks.protograph;
-import java.util.Properties;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-
-public class CellNode extends Node {
+abstract public class CellNode extends Node {
private static final long serialVersionUID = 5820786756175547307L;
- final public int cellIndex;
- final public boolean createUnlessRecon;
- final public FreebaseType type;
+ final public int cellIndex;
public CellNode(
- int cellIndex,
- boolean createUnlessRecon,
- FreebaseType type
+ int cellIndex
) {
this.cellIndex = cellIndex;
- this.createUnlessRecon = createUnlessRecon;
- this.type = type;
}
-
- public void write(JSONWriter writer, Properties options)
- throws JSONException {
- // TODO Auto-generated method stub
-
- }
-
}
diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java
new file mode 100644
index 000000000..41564c4f9
--- /dev/null
+++ b/src/main/java/com/metaweb/gridworks/protograph/CellTopicNode.java
@@ -0,0 +1,35 @@
+package com.metaweb.gridworks.protograph;
+
+import java.util.Properties;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+
+public class CellTopicNode extends CellNode {
+ private static final long serialVersionUID = 1684854896739592911L;
+
+ final public boolean createForNoReconMatch;
+ final public FreebaseType type;
+
+ public CellTopicNode(
+ int cellIndex,
+ boolean createForNoReconMatch,
+ FreebaseType type
+ ) {
+ super(cellIndex);
+
+ this.createForNoReconMatch = createForNoReconMatch;
+ this.type = type;
+ }
+
+ public void write(JSONWriter writer, Properties options)
+ throws JSONException {
+
+ writer.object();
+ writer.key("nodeType"); writer.value("cell-as-topic");
+ writer.key("cellIndex"); writer.value(cellIndex);
+ writer.key("type"); type.write(writer, options);
+ writer.key("createUnlessRecon"); writer.value(createForNoReconMatch);
+ writer.endObject();
+ }
+}
diff --git a/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java b/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java
new file mode 100644
index 000000000..3b056cb2c
--- /dev/null
+++ b/src/main/java/com/metaweb/gridworks/protograph/CellValueNode.java
@@ -0,0 +1,36 @@
+package com.metaweb.gridworks.protograph;
+
+import java.util.Properties;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+
+public class CellValueNode extends CellNode {
+ private static final long serialVersionUID = 7311884925532708576L;
+
+ final public String valueType;
+ final public String lang;
+
+ public CellValueNode(
+ int cellIndex,
+ String valueType,
+ String lang
+ ) {
+ super(cellIndex);
+
+ this.valueType = valueType;
+ this.lang = lang;
+ }
+
+ public void write(JSONWriter writer, Properties options)
+ throws JSONException {
+
+ writer.object();
+ writer.key("nodeType"); writer.value("cell-as-value");
+ writer.key("cellIndex"); writer.value(cellIndex);
+ writer.key("valueType"); writer.value(valueType);
+ writer.key("lang"); writer.value(lang);
+ writer.endObject();
+ }
+
+}
diff --git a/src/main/java/com/metaweb/gridworks/protograph/ExistingTopicNode.java b/src/main/java/com/metaweb/gridworks/protograph/ExistingTopicNode.java
deleted file mode 100644
index 140fd9e5f..000000000
--- a/src/main/java/com/metaweb/gridworks/protograph/ExistingTopicNode.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.metaweb.gridworks.protograph;
-
-import java.util.Properties;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-
-public class ExistingTopicNode extends Node {
- private static final long serialVersionUID = 8418548867745587387L;
-
- final protected FreebaseTopic _topic;
-
- public ExistingTopicNode(FreebaseTopic topic) {
- _topic = topic;
- }
-
- public void write(JSONWriter writer, Properties options)
- throws JSONException {
- // TODO Auto-generated method stub
-
- }
-}
diff --git a/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java b/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java
new file mode 100644
index 000000000..1c632a9e8
--- /dev/null
+++ b/src/main/java/com/metaweb/gridworks/protograph/FreebaseTopicNode.java
@@ -0,0 +1,25 @@
+package com.metaweb.gridworks.protograph;
+
+import java.util.Properties;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+
+public class FreebaseTopicNode extends Node {
+ private static final long serialVersionUID = 8418548867745587387L;
+
+ final public FreebaseTopic topic;
+
+ public FreebaseTopicNode(FreebaseTopic topic) {
+ this.topic = topic;
+ }
+
+ public void write(JSONWriter writer, Properties options)
+ throws JSONException {
+
+ writer.object();
+ writer.key("nodeType"); writer.value("topic");
+ writer.key("topic"); topic.write(writer, options);
+ writer.endObject();
+ }
+}
diff --git a/src/main/java/com/metaweb/gridworks/protograph/Link.java b/src/main/java/com/metaweb/gridworks/protograph/Link.java
index 0c14eab11..3c17600b3 100644
--- a/src/main/java/com/metaweb/gridworks/protograph/Link.java
+++ b/src/main/java/com/metaweb/gridworks/protograph/Link.java
@@ -11,26 +11,29 @@ import com.metaweb.gridworks.Jsonizable;
public class Link implements Serializable, Jsonizable {
private static final long serialVersionUID = 2908086768260322876L;
- final protected FreebaseProperty _property;
- final protected Node _target;
+ final public FreebaseProperty property;
+ final public Node target;
public Link(FreebaseProperty property, Node target) {
- _property = property;
- _target = target;
+ this.property = property;
+ this.target = target;
}
public FreebaseProperty getProperty() {
- return _property;
+ return property;
}
public Node getTarget() {
- return _target;
+ return target;
}
public void write(JSONWriter writer, Properties options)
throws JSONException {
- // TODO Auto-generated method stub
-
+
+ writer.object();
+ writer.key("property"); property.write(writer, options);
+ writer.key("target"); target.write(writer, options);
+ writer.endObject();
}
}
diff --git a/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java b/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java
new file mode 100644
index 000000000..167c1b2ee
--- /dev/null
+++ b/src/main/java/com/metaweb/gridworks/protograph/ValueNode.java
@@ -0,0 +1,31 @@
+package com.metaweb.gridworks.protograph;
+
+import java.util.Properties;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+
+public class ValueNode extends Node {
+ private static final long serialVersionUID = -5626883493437735688L;
+
+ final public Object value;
+ final public String valueType;
+ final public String lang;
+
+ public ValueNode(Object value, String valueType, String lang) {
+ this.value = value;
+ this.valueType = valueType;
+ this.lang = lang;
+ }
+
+ public void write(JSONWriter writer, Properties options)
+ throws JSONException {
+
+ writer.object();
+ writer.key("nodeType"); writer.value("value");
+ writer.key("value"); writer.value(value);
+ writer.key("valueType"); writer.value(valueType);
+ writer.key("lang"); writer.value(lang);
+ writer.endObject();
+ }
+}
diff --git a/src/main/webapp/images/arrow-end.png b/src/main/webapp/images/arrow-end.png
new file mode 100644
index 000000000..5df656c2c
Binary files /dev/null and b/src/main/webapp/images/arrow-end.png differ
diff --git a/src/main/webapp/images/arrow-start.png b/src/main/webapp/images/arrow-start.png
new file mode 100644
index 000000000..df70be001
Binary files /dev/null and b/src/main/webapp/images/arrow-start.png differ
diff --git a/src/main/webapp/images/collapsed.png b/src/main/webapp/images/collapsed.png
new file mode 100644
index 000000000..1a171be45
Binary files /dev/null and b/src/main/webapp/images/collapsed.png differ
diff --git a/src/main/webapp/images/expanded.png b/src/main/webapp/images/expanded.png
new file mode 100644
index 000000000..523d27e29
Binary files /dev/null and b/src/main/webapp/images/expanded.png differ
diff --git a/src/main/webapp/scripts/project/schema-alignment.js b/src/main/webapp/scripts/project/schema-alignment.js
index db19719d2..a0f1b7845 100644
--- a/src/main/webapp/scripts/project/schema-alignment.js
+++ b/src/main/webapp/scripts/project/schema-alignment.js
@@ -91,16 +91,18 @@ SchemaAlignment._cleanName = function(s) {
}
function SchemaAlignmentDialog(protograph) {
- this._originalProtograph = {
+ protograph = {
rootNodes: [
{
nodeType: "cell-as-topic",
- column: "name",
- linkages: [
+ links: [
]
}
]
};
+
+ this._originalProtograph = protograph;
+ this._protograph = cloneDeep(protograph);
this._createDialog();
};
@@ -138,22 +140,29 @@ SchemaAlignmentDialog.prototype._renderBody = function(body) {
var self = this;
this._canvas = $('
').addClass("schema-alignment-dialog-canvas").appendTo(body);
- this._nodeTable = $('').appendTo(this._canvas)[0];
+ 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._originalProtograph.rootNodes[i],
+ this._protograph.rootNodes[i],
this._nodeTable,
- true
+ {
+ expanded: true,
+ mustBeCellTopic: true
+ }
);
}
};
-SchemaAlignmentDialog.UINode = function(node, table, expanded) {
- this._originalNode = node;
- this._newNode = {
- nodeType: node.nodeType
- };
+/*----------------------------------------------------------------------
+ * UINode
+ *----------------------------------------------------------------------
+ */
+SchemaAlignmentDialog.UINode = function(node, table, options) {
+ this._node = node;
+ this._options = options;
+
+ this._linkUIs = [];
this._detailsRendered = false;
this._tr = table.insertRow(table.rows.length);
@@ -161,24 +170,74 @@ SchemaAlignmentDialog.UINode = function(node, table, expanded) {
this._tdToggle = this._tr.insertCell(1);
this._tdDetails = this._tr.insertCell(2);
- $(this._tdMain).addClass("schema-alignment-node-main").attr("width", "250");
- $(this._tdToggle).addClass("schema-alignment-node-toggle").attr("width", "1%").hide();
+ $(this._tdMain).addClass("schema-alignment-node-main").attr("width", "250").addClass("padded");
+ $(this._tdToggle).addClass("schema-alignment-node-toggle").attr("width", "1%").addClass("padded").hide();
$(this._tdDetails).addClass("schema-alignment-node-details").attr("width", "90%").hide();
this._renderMain();
- this._expanded = expanded;
+ this._expanded = options.expanded;
if (this._isExpandable()) {
this._showExpandable();
}
};
SchemaAlignmentDialog.UINode.prototype._isExpandable = function() {
- return this._newNode.nodeType != "existing-content" && this._newNode.nodeType != "cell-as-content";
+ return this._node.nodeType == "cell-as-topic";
+};
+
+SchemaAlignmentDialog._findColumn = function(cellIndex) {
+ var columns = theProject.columnModel.columns;
+ for (var i = 0; i < columns.length; i++) {
+ var column = columns[i];
+ if (column.cellIndex == cellIndex) {
+ return column;
+ }
+ }
+ return null;
};
SchemaAlignmentDialog.UINode.prototype._renderMain = function() {
- $(this._tdMain).empty().html(this._newNode.nodeType);
+ $(this._tdMain).empty();
+
+ var self = this;
+ var a = $('')
+ .addClass("schema-alignment-node-tag")
+ .appendTo(this._tdMain)
+ .click(function(evt) {
+ self._showTagMenu(this);
+ });
+
+ if (this._node.nodeType == "cell-as-topic" || this._node.nodeType == "cell-as-value") {
+ if ("cellIndex" in this._node) {
+ a.html(" cell");
+
+ $('')
+ .text(SchemaAlignmentDialog._findColumn(this._node.cellIndex).headerLabel)
+ .addClass("schema-alignment-node-column")
+ .prependTo(a);
+ } else {
+ a.html("Which column?");
+ }
+ } else if (this._node.nodeType == "topic") {
+ if ("topic" in this._node) {
+ a.html(this._node.topic.name);
+ } else if ("id" in this._node) {
+ a.html(this._node.topic.id);
+ } else {
+ a.html("Which topic?");
+ }
+ } else if (this._node.nodeType == "value") {
+ if ("value" in this._node) {
+ a.html(this._node.value);
+ } else {
+ a.html("What value?");
+ }
+ } else if (this._node.nodeType == "anonymous") {
+ a.html("(anonymous)");
+ }
+
+ $('').attr("src", "images/down-arrow.png").appendTo(a);
};
SchemaAlignmentDialog.UINode.prototype._showExpandable = function() {
@@ -190,8 +249,8 @@ SchemaAlignmentDialog.UINode.prototype._showExpandable = function() {
}
this._detailsRendered = true;
- this._collapsedDetailDiv = $('').appendTo(this._tdDetails).html("...");
- this._expandedDetailDiv = $('').appendTo(this._tdDetails).html("details");
+ this._collapsedDetailDiv = $('').appendTo(this._tdDetails).addClass("padded").html("...");
+ this._expandedDetailDiv = $('').appendTo(this._tdDetails).addClass("schema-alignment-detail-container");
this._renderDetails();
@@ -208,14 +267,13 @@ SchemaAlignmentDialog.UINode.prototype._showExpandable = function() {
show();
$(this._tdToggle).html(" ");
-
$('')
- .attr("src", this._expanded ? "images/down-arrow.png" : "images/right-arrow.png")
+ .attr("src", this._expanded ? "images/expanded.png" : "images/collapsed.png")
.appendTo(this._tdToggle)
.click(function() {
self._expanded = !self._expanded;
- $(this).attr("src", self._expanded ? "images/down-arrow.png" : "images/right-arrow.png");
+ $(this).attr("src", self._expanded ? "images/expanded.png" : "images/collapsed.png");
show();
});
@@ -227,5 +285,187 @@ SchemaAlignmentDialog.UINode.prototype._hideExpandable = function() {
};
SchemaAlignmentDialog.UINode.prototype._renderDetails = function() {
- var tableDetails = $('').appendTo(this._tdDetails)[0];
+ var self = this;
+
+ this._tableLinks = $('').addClass("schema-alignment-table-layout").appendTo(this._expandedDetailDiv)[0];
+
+ if ("links" in this._node && this._node.links != null) {
+ for (var i = 0; i < this._node.links.length; i++) {
+ this._linkUIs.push(new SchemaAlignmentDialog.UILink(this._node.links[i], this._tableLinks, true));
+ }
+ }
+
+ var divFooter = $('').addClass("padded").appendTo(this._expandedDetailDiv);
+
+ $('')
+ .addClass("action")
+ .text("add property")
+ .appendTo(divFooter)
+ .click(function() {
+ var newLink = {
+ property: null,
+ target: {
+ nodeType: "cell-as-value"
+ }
+ };
+ self._linkUIs.push(new SchemaAlignmentDialog.UILink(
+ newLink,
+ self._tableLinks,
+ {
+ expanded: true,
+ mustBeCellTopic: false
+ }
+ ));
+ });
};
+
+SchemaAlignmentDialog.UINode.prototype._showTagMenu = function(elmt) {
+ self = this;
+
+ var menu = [];
+
+ if (!this._options.mustBeCellTopic) {
+ menu.push({
+ label: "Anonymous Node",
+ click: function() {
+ self._node.nodeType = "anonymous";
+ self._showExpandable();
+ self._renderMain();
+ }
+ });
+ menu.push({
+ label: "Freebase Topic",
+ click: function() {
+ self._node.nodeType = "topic";
+ self._hideExpandable();
+ self._renderMain();
+ }
+ });
+ menu.push({
+ label: "Value",
+ click: function() {
+ self._node.nodeType = "value";
+ self._hideExpandable();
+ self._renderMain();
+ }
+ });
+ menu.push({}); // separator
+ }
+
+ var columns = theProject.columnModel.columns;
+ var createColumnMenuItem = function(index) {
+ menu.push({
+ label: columns[index].headerLabel,
+ click: function() {
+ self._node.nodeType = "cell-as-topic";
+ self._node.cellIndex = columns[index].cellIndex;
+ self._showExpandable();
+ self._renderMain();
+ }
+ });
+ };
+ for (var i = 0; i < columns.length; i++) {
+ createColumnMenuItem(i);
+ }
+
+ MenuSystem.createAndShowStandardMenu(menu, elmt);
+};
+
+/*----------------------------------------------------------------------
+ * UILink
+ *----------------------------------------------------------------------
+ */
+SchemaAlignmentDialog.UILink = function(link, table, expanded) {
+ this._link = link;
+ this._expanded = expanded;
+
+ this._tr = table.insertRow(table.rows.length);
+ this._tdMain = this._tr.insertCell(0);
+ this._tdToggle = this._tr.insertCell(1);
+ this._tdDetails = this._tr.insertCell(2);
+
+ $(this._tdMain).addClass("schema-alignment-link-main").attr("width", "250").addClass("padded");
+ $(this._tdToggle).addClass("schema-alignment-link-toggle").attr("width", "1%").addClass("padded");
+ $(this._tdDetails).addClass("schema-alignment-link-details").attr("width", "90%");
+
+ this._collapsedDetailDiv = $('').appendTo(this._tdDetails).addClass("padded").html("...");
+ this._expandedDetailDiv = $('').appendTo(this._tdDetails).addClass("schema-alignment-detail-container");
+ var self = this;
+ var show = function() {
+ if (self._expanded) {
+ self._collapsedDetailDiv.hide();
+ self._expandedDetailDiv.show();
+ } else {
+ self._collapsedDetailDiv.show();
+ self._expandedDetailDiv.hide();
+ }
+ };
+ show();
+
+ $(this._tdToggle).html(" ");
+ $('')
+ .attr("src", this._expanded ? "images/expanded.png" : "images/collapsed.png")
+ .appendTo(this._tdToggle)
+ .click(function() {
+ self._expanded = !self._expanded;
+
+ $(this).attr("src", self._expanded ? "images/expanded.png" : "images/collapsed.png");
+
+ show();
+ });
+
+ this._renderMain();
+ this._renderDetails();
+};
+
+SchemaAlignmentDialog.UILink.prototype._renderMain = function() {
+ $(this._tdMain).empty()
+
+ var label = this._link.property != null ? this._link.property.id : "property?";
+
+ var self = this;
+
+ var a = $('')
+ .addClass("schema-alignment-link-tag")
+ .html(label)
+ .appendTo(this._tdMain)
+ .click(function(evt) {
+ self._showTagSuggest(this);
+ });
+
+ $('').attr("src", "images/arrow-start.png").prependTo(a);
+ $('').attr("src", "images/arrow-end.png").appendTo(a);
+};
+
+SchemaAlignmentDialog.UILink.prototype._renderDetails = function() {
+ var tableDetails = $('').addClass("schema-alignment-table-layout").appendTo(this._expandedDetailDiv)[0];
+ this._targetUI = new SchemaAlignmentDialog.UINode(this._link.target, tableDetails, true);
+};
+
+SchemaAlignmentDialog.UILink.prototype._showTagSuggest = function(elmt) {
+ self = this;
+
+ var fakeMenu = MenuSystem.createMenu()
+ .width(300)
+ .height(100)
+ .css("background", "none")
+ .css("border", "none");
+
+ var input = $('').appendTo(fakeMenu);
+
+ var level = MenuSystem.showMenu(fakeMenu, function(){});
+ MenuSystem.positionMenuAboveBelow(fakeMenu, $(elmt));
+
+ input.suggest({ type : '/type/property' }).bind("fb-select", function(e, data) {
+ self._link.property = {
+ id: data.id,
+ name: data.name
+ };
+
+ window.setTimeout(function() {
+ MenuSystem.dismissAll();
+ self._renderMain();
+ }, 100);
+ });
+ input[0].focus();
+};
\ No newline at end of file
diff --git a/src/main/webapp/styles/common.css b/src/main/webapp/styles/common.css
index c2003678e..09c935cf6 100644
--- a/src/main/webapp/styles/common.css
+++ b/src/main/webapp/styles/common.css
@@ -62,4 +62,8 @@ a img {
img {
vertical-align: middle;
+}
+
+.fbs-pane, .fbs-flyout-pane {
+ z-index: 2000;
}
\ No newline at end of file
diff --git a/src/main/webapp/styles/process.css b/src/main/webapp/styles/process.css
index 7c89b2f51..3e8952988 100644
--- a/src/main/webapp/styles/process.css
+++ b/src/main/webapp/styles/process.css
@@ -14,6 +14,3 @@
text-align: left;
}
-.fbs-pane, .fbs-flyout-pane {
- z-index: 200;
-}
\ No newline at end of file
diff --git a/src/main/webapp/styles/schema-alignment-dialog.css b/src/main/webapp/styles/schema-alignment-dialog.css
index e94db0a41..2a165970c 100644
--- a/src/main/webapp/styles/schema-alignment-dialog.css
+++ b/src/main/webapp/styles/schema-alignment-dialog.css
@@ -2,25 +2,64 @@
height: 500px;
overflow: auto;
border: 1px solid #aaa;
+ padding: 10px;
}
-td.schema-alignment-node-main {
+table.schema-alignment-table-layout {
+ border-collapse: collapse;
+ margin: 0px;
+ padding: 0px;
+ margin-bottom: 1em;
+}
+
+table.schema-alignment-table-layout .padded {
+ padding: 3px 6px;
+}
+
+div.schema-alignment-detail-container {
+ border-left: 3px solid #eee;
+}
+
+td.schema-alignment-node-main, td.schema-alignment-link-main {
white-space: pre;
width: 300px;
}
-td.schema-alignment-node-toggle {
+td.schema-alignment-node-toggle, td.schema-alignment-link-toggle {
white-space: pre;
width: 1%;
}
-td.schema-alignment-node-toggle img {
+td.schema-alignment-node-toggle img, td.schema-alignment-link-toggle img {
cursor: pointer;
vertical-align: middle;
padding: 2px;
}
-td.schema-alignment-node-details {
+td.schema-alignment-node-details, td.schema-alignment-link-details {
width: 90%;
}
+a.schema-alignment-node-tag {
+ padding: 3px 6px;
+ background: #ddd;
+ text-decoration: none;
+ color: black;
+ -moz-border-radius: 10px;
+}
+a.schema-alignment-node-tag:hover {
+ background: #888;
+ color: white;
+}
+.schema-alignment-node-column {
+ font-weight: bold;
+}
+
+a.schema-alignment-link-tag {
+ padding: 3px 6px;
+ text-decoration: none;
+ color: black;
+}
+a.schema-alignment-link-tag:hover {
+ color: #88f;
+}