Protograph preview now works.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@95 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-02-16 20:15:19 +00:00
parent 0d11e469a6
commit 5de0c36f86
16 changed files with 631 additions and 15 deletions

View File

@ -38,6 +38,7 @@ import com.metaweb.gridworks.commands.recon.JudgeOneCellCommand;
import com.metaweb.gridworks.commands.recon.ReconcileCommand;
import com.metaweb.gridworks.commands.util.GetExpressionLanguageInfoCommand;
import com.metaweb.gridworks.commands.util.PreviewExpressionCommand;
import com.metaweb.gridworks.commands.util.PreviewProtographCommand;
public class GridworksServlet extends HttpServlet {
private static final long serialVersionUID = 2386057901503517403L;
@ -75,6 +76,7 @@ public class GridworksServlet extends HttpServlet {
_commands.put("preview-expression", new PreviewExpressionCommand());
_commands.put("get-expression-language-info", new GetExpressionLanguageInfoCommand());
_commands.put("preview-protograph", new PreviewProtographCommand());
}
@Override

View File

@ -0,0 +1,42 @@
package com.metaweb.gridworks.commands.util;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;
import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.protograph.Protograph;
import com.metaweb.gridworks.protograph.transpose.MqlreadLikeTransposedNodeFactory;
import com.metaweb.gridworks.protograph.transpose.Transposer;
public class PreviewProtographCommand 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);
MqlreadLikeTransposedNodeFactory nodeFactory = new MqlreadLikeTransposedNodeFactory();
Transposer.transpose(project, protograph, protograph.getRootNode(0), nodeFactory);
JSONArray results = nodeFactory.getJSON();
respond(response, "{ \"result\" : " + results.toString() + " }");
} catch (Exception e) {
respondException(response, e);
}
}
}

View File

@ -36,4 +36,12 @@ public class AnonymousNode implements Node, NodeWithLinks {
public void addLink(Link link) {
links.add(link);
}
public Link getLink(int index) {
return links.get(index);
}
public int getLinkCount() {
return links.size();
}
}

View File

@ -49,4 +49,12 @@ public class CellTopicNode extends CellNode implements NodeWithLinks {
public void addLink(Link link) {
links.add(link);
}
public Link getLink(int index) {
return links.get(index);
}
public int getLinkCount() {
return links.size();
}
}

View File

@ -37,4 +37,12 @@ public class FreebaseTopicNode implements Node, NodeWithLinks {
public void addLink(Link link) {
links.add(link);
}
public Link getLink(int index) {
return links.get(index);
}
public int getLinkCount() {
return links.size();
}
}

View File

@ -2,4 +2,8 @@ package com.metaweb.gridworks.protograph;
public interface NodeWithLinks {
public void addLink(Link link);
public int getLinkCount();
public Link getLink(int index);
}

View File

@ -17,6 +17,14 @@ public class Protograph implements Serializable, Jsonizable {
final protected List<Node> _rootNodes = new LinkedList<Node>();
public int getRootNodeCount() {
return _rootNodes.size();
}
public Node getRootNode(int index) {
return _rootNodes.get(index);
}
static public Protograph reconstruct(JSONObject o) throws JSONException {
Protograph g = new Protograph();

View File

@ -0,0 +1,306 @@
package com.metaweb.gridworks.protograph.transpose;
import java.util.LinkedList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Recon;
import com.metaweb.gridworks.protograph.AnonymousNode;
import com.metaweb.gridworks.protograph.CellKeyNode;
import com.metaweb.gridworks.protograph.CellNode;
import com.metaweb.gridworks.protograph.CellTopicNode;
import com.metaweb.gridworks.protograph.CellValueNode;
import com.metaweb.gridworks.protograph.FreebaseProperty;
import com.metaweb.gridworks.protograph.FreebaseTopicNode;
import com.metaweb.gridworks.protograph.ValueNode;
public class MqlreadLikeTransposedNodeFactory implements TransposedNodeFactory {
protected List<JSONObject> rootObjects = new LinkedList<JSONObject>();
public JSONArray getJSON() {
return new JSONArray(rootObjects);
}
abstract protected class JsonTransposedNode implements TransposedNode {
abstract public Object getJSON();
}
abstract protected class JsonObjectTransposedNode extends JsonTransposedNode {
abstract public JSONObject getJSONObject();
protected JSONObject obj;
public Object getJSON() {
return getJSONObject();
}
}
protected class AnonymousTransposedNode extends JsonObjectTransposedNode {
JsonObjectTransposedNode parent;
FreebaseProperty property;
AnonymousNode node;
protected AnonymousTransposedNode(
JsonObjectTransposedNode parent,
FreebaseProperty property,
AnonymousNode node
) {
this.parent = parent;
this.property = property;
this.node = node;
}
public JSONObject getJSONObject() {
if (obj == null) {
obj = new JSONObject();
try {
obj.put("type", this.node.type.id);
obj.put("id", (String) null);
obj.put("create", "unconditional");
} catch (JSONException e) {
e.printStackTrace();
}
linkTransposedNodeJSON(obj, parent, property);
}
return obj;
}
}
protected class CellTopicTransposedNode extends JsonObjectTransposedNode {
protected CellTopicNode node;
protected Cell cell;
public CellTopicTransposedNode(CellTopicNode node, Cell cell) {
this.node = node;
this.cell = cell;
}
@Override
public JSONObject getJSONObject() {
if (obj == null) {
obj = new JSONObject();
try {
if (cell.recon != null &&
cell.recon.judgment == Recon.Judgment.Matched &&
cell.recon.match != null) {
obj.put("id", cell.recon.match.topicID);
} else {
obj.put("id", (String) null);
obj.put("name", cell.value.toString());
obj.put("type", node.type.id);
obj.put("create", "unless_exists");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return obj;
}
}
protected class CellValueTransposedNode extends JsonTransposedNode {
protected JSONObject obj;
protected CellValueNode node;
protected Cell cell;
public CellValueTransposedNode(CellValueNode node, Cell cell) {
this.node = node;
this.cell = cell;
}
public Object getJSON() {
if (obj == null) {
obj = new JSONObject();
try {
obj.put("value", cell.value.toString());
if (node.lang != null) {
obj.put("lang", node.lang);
}
obj.put("connect", "insert");
} catch (JSONException e) {
e.printStackTrace();
}
}
return obj;
}
}
protected class CellKeyTransposedNode extends JsonTransposedNode {
protected JSONObject obj;
protected CellKeyNode node;
protected Cell cell;
public CellKeyTransposedNode(CellKeyNode node, Cell cell) {
this.node = node;
this.cell = cell;
}
public Object getJSON() {
if (obj == null) {
obj = new JSONObject();
try {
obj.put("value", cell.value.toString());
JSONObject nsObj = new JSONObject();
nsObj.put("id", node.namespace.id);
obj.put("namespace", nsObj);
obj.put("connect", "insert");
} catch (JSONException e) {
e.printStackTrace();
}
}
return obj;
}
}
protected class TopicTransposedNode extends JsonObjectTransposedNode {
protected FreebaseTopicNode node;
public TopicTransposedNode(FreebaseTopicNode node) {
this.node = node;
}
@Override
public JSONObject getJSONObject() {
if (obj == null) {
obj = new JSONObject();
try {
obj.put("id", node.topic.id);
} catch (JSONException e) {
e.printStackTrace();
}
}
return obj;
}
}
protected class ValueTransposedNode extends JsonTransposedNode {
protected JSONObject obj;
protected ValueNode node;
public ValueTransposedNode(ValueNode node) {
this.node = node;
}
public Object getJSON() {
if (obj == null) {
obj = new JSONObject();
try {
obj.put("value", node.value);
if (node.lang != null) {
obj.put("lang", node.lang);
}
obj.put("connect", "insert");
} catch (JSONException e) {
e.printStackTrace();
}
}
return obj;
}
}
public TransposedNode transposeAnonymousNode(
TransposedNode parentNode,
FreebaseProperty property,
AnonymousNode node) {
return new AnonymousTransposedNode(
parentNode instanceof JsonObjectTransposedNode ? (JsonObjectTransposedNode) parentNode : null,
property,
node
);
}
public TransposedNode transposeCellNode(
TransposedNode parentNode,
FreebaseProperty property,
CellNode node,
Cell cell) {
JsonTransposedNode tnode = null;
if (node instanceof CellTopicNode) {
tnode = new CellTopicTransposedNode((CellTopicNode) node, cell);
} else if (node instanceof CellValueNode) {
tnode = new CellValueTransposedNode((CellValueNode) node, cell);
} else if (node instanceof CellKeyNode) {
tnode = new CellKeyTransposedNode((CellKeyNode) node, cell);
}
if (tnode != null) {
processTransposedNode(tnode, parentNode, property);
}
return tnode;
}
public TransposedNode transposeTopicNode(
TransposedNode parentNode,
FreebaseProperty property,
FreebaseTopicNode node) {
JsonTransposedNode tnode = new TopicTransposedNode(node);
processTransposedNode(tnode, parentNode, property);
return tnode;
}
public TransposedNode transposeValueNode(
TransposedNode parentNode,
FreebaseProperty property,
ValueNode node) {
JsonTransposedNode tnode = new ValueTransposedNode(node);
processTransposedNode(tnode, parentNode, property);
return tnode;
}
protected void processTransposedNode(
JsonTransposedNode tnode,
TransposedNode parentNode,
FreebaseProperty property
) {
if (!(tnode instanceof AnonymousTransposedNode)) {
linkTransposedNodeJSON(tnode.getJSON(), parentNode, property);
}
}
protected void linkTransposedNodeJSON(
Object obj,
TransposedNode parentNode,
FreebaseProperty property
) {
if (parentNode == null) {
if (obj instanceof JSONObject) {
rootObjects.add((JSONObject) obj);
}
} else if (parentNode instanceof JsonTransposedNode) {
JSONObject parentObj = ((JsonObjectTransposedNode) parentNode).getJSONObject();
try {
JSONArray a = null;
if (parentObj.has(property.id)) {
a = parentObj.getJSONArray(property.id);
} else {
a = new JSONArray();
parentObj.put(property.id, a);
}
a.put(a.length(), obj);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,4 @@
package com.metaweb.gridworks.protograph.transpose;
public interface TransposedNode {
}

View File

@ -0,0 +1,35 @@
package com.metaweb.gridworks.protograph.transpose;
import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.protograph.AnonymousNode;
import com.metaweb.gridworks.protograph.CellNode;
import com.metaweb.gridworks.protograph.FreebaseProperty;
import com.metaweb.gridworks.protograph.FreebaseTopicNode;
import com.metaweb.gridworks.protograph.ValueNode;
public interface TransposedNodeFactory {
public TransposedNode transposeAnonymousNode(
TransposedNode parentNode,
FreebaseProperty property,
AnonymousNode node
);
public TransposedNode transposeCellNode(
TransposedNode parentNode,
FreebaseProperty property,
CellNode node,
Cell cell
);
public TransposedNode transposeValueNode(
TransposedNode parentNode,
FreebaseProperty property,
ValueNode node
);
public TransposedNode transposeTopicNode(
TransposedNode parentNode,
FreebaseProperty property,
FreebaseTopicNode node
);
}

View File

@ -0,0 +1,152 @@
package com.metaweb.gridworks.protograph.transpose;
import java.util.LinkedList;
import java.util.List;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Column;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
import com.metaweb.gridworks.protograph.AnonymousNode;
import com.metaweb.gridworks.protograph.CellNode;
import com.metaweb.gridworks.protograph.FreebaseProperty;
import com.metaweb.gridworks.protograph.FreebaseTopicNode;
import com.metaweb.gridworks.protograph.Link;
import com.metaweb.gridworks.protograph.Node;
import com.metaweb.gridworks.protograph.NodeWithLinks;
import com.metaweb.gridworks.protograph.Protograph;
import com.metaweb.gridworks.protograph.ValueNode;
public class Transposer {
static public void transpose(
Project project,
Protograph protograph,
Node rootNode,
TransposedNodeFactory nodeFactory
) {
Context rootContext = new Context(rootNode, null, null, 5);
for (Row row : project.rows) {
descend(project, protograph, nodeFactory, row, rootNode, rootContext);
if (rootContext.limit > 0 && rootContext.count > rootContext.limit) {
break;
}
}
}
static protected void descend(
Project project,
Protograph protograph,
TransposedNodeFactory nodeFactory,
Row row,
Node node,
Context context
) {
TransposedNode tnode = null;
TransposedNode parentNode = context.parent == null ? null : context.parent.transposedNode;
FreebaseProperty property = context.parent == null ? null : context.link.property;
if (node instanceof CellNode) {
CellNode node2 = (CellNode) node;
Column column = project.columnModel.getColumnByName(node2.columnName);
Cell cell = row.getCell(column.getCellIndex());
if (cell != null && !ExpressionUtils.isBlank(cell.value)) {
context.count++;
if (context.limit > 0 && context.count > context.limit) {
return;
}
tnode = nodeFactory.transposeCellNode(
parentNode,
property,
node2,
cell
);
}
} else {
if (node instanceof AnonymousNode) {
tnode = nodeFactory.transposeAnonymousNode(
parentNode,
property,
(AnonymousNode) node
);
} else if (node instanceof FreebaseTopicNode) {
tnode = nodeFactory.transposeTopicNode(
parentNode,
property,
(FreebaseTopicNode) node
);
} else if (node instanceof ValueNode) {
tnode = nodeFactory.transposeValueNode(
parentNode,
property,
(ValueNode) node
);
}
}
if (tnode != null) {
context.transposedNode = tnode;
context.nullifySubContextNodes();
} /*
else, previous rows might have set the context transposed node already,
and we simply inherit that transposed node.
*/
if (node instanceof NodeWithLinks && context.transposedNode != null) {
NodeWithLinks node2 = (NodeWithLinks) node;
int linkCount = node2.getLinkCount();
for (int i = 0; i < linkCount; i++) {
descend(
project,
protograph,
nodeFactory,
row,
node2.getLink(i).getTarget(),
context.subContexts.get(i)
);
}
}
}
static class Context {
TransposedNode transposedNode;
List<Context> subContexts;
Context parent;
Link link;
int count;
int limit;
Context(Node node, Context parent, Link link, int limit) {
this.parent = parent;
this.link = link;
this.limit = limit;
if (node instanceof NodeWithLinks) {
NodeWithLinks node2 = (NodeWithLinks) node;
int subContextCount = node2.getLinkCount();
subContexts = new LinkedList<Context>();
for (int i = 0; i < subContextCount; i++) {
Link link2 = node2.getLink(i);
subContexts.add(
new Context(link2.getTarget(), this, link2, -1));
}
}
}
public void nullifySubContextNodes() {
if (subContexts != null) {
for (Context context : subContexts) {
context.transposedNode = null;
context.nullifySubContextNodes();
}
}
}
}
}

View File

@ -19,13 +19,13 @@ MenuBar.prototype._initializeUI = function() {
}
]);
this._createTopLevelMenuItem("Schemas", [
{
/*{
label: "Auto-Align with Freebase ...",
click: function() { self._doAutoSchemaAlignment(); }
},
},*/
{
label: "Edit Schema Alignment ...",
click: function() { }
click: function() { self._doEditSchemaAlignment(); }
}
]);
@ -136,8 +136,8 @@ MenuBar.prototype._doExportRows = function() {
MenuBar.prototype._doAutoSchemaAlignment = function() {
//SchemaAlignment.autoAlign();
new SchemaAlignmentDialog(theProject.protograph, function(newProtograph) {
});
};
MenuBar.prototype._doEditSchemaAlignment = function() {
new SchemaAlignmentDialog(theProject.protograph, function(newProtograph) {});
};

View File

@ -1,4 +1,5 @@
SchemaAlignmentDialog.UILink = function(link, table, options, parentUINode) {
SchemaAlignmentDialog.UILink = function(dialog, link, table, options, parentUINode) {
this._dialog = dialog;
this._link = link;
this._options = options;
this._parentUINode = parentUINode;
@ -76,6 +77,7 @@ SchemaAlignmentDialog.UILink.prototype._renderMain = function() {
SchemaAlignmentDialog.UILink.prototype._renderDetails = function() {
var tableDetails = $('<table></table>').addClass("schema-alignment-table-layout").appendTo(this._expandedDetailDiv)[0];
this._targetUI = new SchemaAlignmentDialog.UINode(
this._dialog,
this._link.target,
tableDetails,
{ expanded: "links" in this._link.target && this._link.target.links.length > 0 });
@ -115,6 +117,7 @@ SchemaAlignmentDialog.UILink.prototype._showPropertySuggestPopup = function(elmt
window.setTimeout(function() {
MenuSystem.dismissAll();
self._renderMain();
self._dialog.preview();
}, 100);
});
input[0].focus();

View File

@ -1,4 +1,5 @@
SchemaAlignmentDialog.UINode = function(node, table, options) {
SchemaAlignmentDialog.UINode = function(dialog, node, table, options) {
this._dialog = dialog;
this._node = node;
this._options = options;
@ -149,7 +150,13 @@ SchemaAlignmentDialog.UINode.prototype._renderDetails = function() {
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, { expanded: true }, this));
this._linkUIs.push(new SchemaAlignmentDialog.UILink(
this._dialog,
this._node.links[i],
this._tableLinks,
{ expanded: true },
this
));
}
}
@ -167,6 +174,7 @@ SchemaAlignmentDialog.UINode.prototype._renderDetails = function() {
}
};
self._linkUIs.push(new SchemaAlignmentDialog.UILink(
self._dialog,
newLink,
self._tableLinks,
{
@ -519,7 +527,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
}
if ("valueType" in this._node) {
elmts.valueNodeTypeValueTypeSelect[0].value = this._node.valueType;
elmts.cellAsValueTypeSelect.value(this._node.valueType);
elmts.cellAsValueTypeSelect[0].value = this._node.valueType;
}
/*--------------------------------------------------
@ -554,8 +562,10 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
} else if (node.nodeType == "cell-as-value") {
node.valueType = elmts.cellAsValueTypeSelect[0].value;
var l = elmts.cellAsValueLanguageInput[0].data("data.suggest");
node.lang = (l) ? l.id : "/type/text";
if (node.valueType == "/type/text") {
var l = elmts.cellAsValueLanguageInput.data("data.suggest");
node.lang = (l) ? l.id : "/lang/en";
}
} else if (node.nodeType == "cell-as-key") {
var t = elmts.cellAsKeyInput.data("data.suggest");
if (!(t)) {
@ -595,8 +605,10 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
}
node.valueType = elmts.valueNodeTypeValueTypeSelect[0].value;
var l = elmts.valueNodeTypeLanguageInput[0].data("data.suggest");
node.lang = (l) ? l.id : "/type/text";
if (node.valueType == "/type/text") {
var l = elmts.valueNodeTypeLanguageInput.data("data.suggest");
node.lang = (l) ? l.id : "/lang/en";
}
}
return node;
@ -609,6 +621,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
self._node = node;
self.render();
self._dialog.preview();
}
}).appendTo(footer);

View File

@ -105,6 +105,7 @@ function SchemaAlignmentDialog(protograph, onDone) {
this._nodeUIs = [];
this._createDialog();
this.preview();
};
SchemaAlignmentDialog.prototype._createDialog = function() {
@ -173,6 +174,7 @@ SchemaAlignmentDialog.prototype._renderBody = function(body) {
for (var i = 0; i < this._protograph.rootNodes.length; i++) {
this._nodeUIs.push(new SchemaAlignmentDialog.UINode(
this,
this._protograph.rootNodes[i],
this._nodeTable,
{
@ -199,6 +201,24 @@ SchemaAlignmentDialog.prototype.getJSON = function() {
};
};
SchemaAlignmentDialog.prototype.preview = function() {
var self = this;
this._previewPane.empty();
var protograph = this.getJSON();
$.post(
"/command/preview-protograph?" + $.param({ project: theProject.id }),
{ protograph: JSON.stringify(protograph) },
function(data) {
if ("result" in data) {
self._previewPane.text(JSON.stringify(data.result, null, 2));
}
},
"json"
);
};
SchemaAlignmentDialog._findColumn = function(cellIndex) {
var columns = theProject.columnModel.columns;
for (var i = 0; i < columns.length; i++) {

View File

@ -70,6 +70,9 @@ div.schema-alignment-dialog-preview {
border: 1px solid #aaa;
padding: 10px;
margin-top: 10px;
white-space: pre;
font-family: monospace;
font-size: 11pt;
}
/*--------------------------------------------------