Keep track of type names of reconciled columns so we can display them later in the schema alignment dialog.

Automatically create properties linking to all columns when starting with an empty protograph.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@110 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-02-19 18:32:48 +00:00
parent acb0c91306
commit 846e540ff6
7 changed files with 122 additions and 81 deletions

View File

@ -91,7 +91,8 @@ public class ApplyOperationsCommand extends Command {
operation = new ReconOperation(
engineConfig,
columnName,
obj.getString("typeID")
obj.getString("typeID"),
obj.getString("typeName")
);
} else if ("save-protograph".equals(op)) {
operation = new SaveProtographOperation(

View File

@ -15,8 +15,9 @@ public class ReconcileCommand extends EngineDependentCommand {
JSONObject engineConfig) throws Exception {
String columnName = request.getParameter("columnName");
String typeID = request.getParameter("type");
String typeID = request.getParameter("typeID");
String typeName = request.getParameter("typeName");
return new ReconOperation(engineConfig, columnName, typeID);
return new ReconOperation(engineConfig, columnName, typeID, typeName);
}
}

View File

@ -12,16 +12,22 @@ public class ReconConfig implements Serializable, Jsonizable {
private static final long serialVersionUID = -4831409797104437854L;
final public String typeID;
final public String typeName;
public ReconConfig(String typeID) {
public ReconConfig(String typeID, String typeName) {
this.typeID = typeID;
this.typeName = typeName;
}
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("type"); writer.value(typeID);
writer.key("type");
writer.object();
writer.key("id"); writer.value(typeID);
writer.key("name"); writer.value(typeName);
writer.endObject();
writer.endObject();
}
}

View File

@ -43,11 +43,13 @@ public class ReconOperation extends EngineDependentOperation {
final protected String _columnName;
final protected String _typeID;
final protected String _typeName;
public ReconOperation(JSONObject engineConfig, String columnName, String typeID) {
public ReconOperation(JSONObject engineConfig, String columnName, String typeID, String typeName) {
super(engineConfig);
_columnName = columnName;
_typeID = typeID;
_typeName = typeName;
}
public Process createProcess(Project project, Properties options) throws Exception {
@ -75,6 +77,7 @@ public class ReconOperation extends EngineDependentOperation {
writer.key("description"); writer.value("Reconcile cells in column " + _columnName + " to type " + _typeID);
writer.key("columnName"); writer.value(_columnName);
writer.key("typeID"); writer.value(_typeID);
writer.key("typeName"); writer.value(_typeName);
writer.key("engineConfig"); writer.value(getEngineConfig());
writer.endObject();
}
@ -214,7 +217,7 @@ public class ReconOperation extends EngineDependentOperation {
}
}
ReconConfig reconConfig = new ReconConfig(_typeID);
ReconConfig reconConfig = new ReconConfig(_typeID, _typeName);
Change reconChange = new ReconChange(cellChanges, _columnName, reconConfig);

View File

@ -20,6 +20,7 @@ ReconDialog.prototype._createDialog = function() {
var div = $('<div>').appendTo(body);
$('<input type="radio" name="recon-dialog-type-choice">')
.attr("value", type.id)
.attr("typeName", type.name)
.appendTo(div);
$('<span></span>').text(" " + type.name).appendTo(div);
@ -40,14 +41,20 @@ ReconDialog.prototype._createDialog = function() {
var type = null;
var input = $('<input />').appendTo($('<p></p>').appendTo(body));
input.suggest({ type : '/type/type' }).bind("fb-select", function(e, data) {
type = data.id;
type = {
id: data.id,
name: data.name
};
$('input[name="recon-dialog-type-choice"][value=""]').attr("checked", "true");
});
$('<button></button>').text("Start Reconciling").click(function() {
var choices = $('input[name="recon-dialog-type-choice"]:checked');
if (choices != null && choices.length > 0 && choices[0].value != "") {
type = choices[0].value;
type = {
id: choices[0].value,
name: choices.attr("typeName")
};
}
if (type == null) {
@ -55,7 +62,7 @@ ReconDialog.prototype._createDialog = function() {
} else {
DialogSystem.dismissUntil(level - 1);
$.post(
"/command/reconcile?" + $.param({ project: theProject.id, columnName: self._column.headerLabel, type: type }),
"/command/reconcile?" + $.param({ project: theProject.id, columnName: self._column.headerLabel, typeID: type.id, typeName: type.name }),
{ engine: JSON.stringify(ui.browsingEngine.getJSON()) },
function(data) {
if (data.code != "error") {

View File

@ -263,59 +263,6 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
var html = $(
'<table class="schema-align-node-dialog-layout">' +
'<tr>' +
'<td>' +
'<table class="schema-align-node-dialog-layout2">' +
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="anonymous" id="radioNodeTypeAnonymous" /> Generate an anonymous graph node' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Assign a type to the node</td>' +
'<td>&nbsp;<input id="anonymousNodeTypeInput" /></td>' +
'</tr>' +
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="topic" id="radioNodeTypeTopic" /> Use one existing Freebase topic' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Topic</td>' +
'<td><input id="topicNodeTypeInput" /></td>' +
'</tr>' +
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="value" id="radioNodeTypeValue" /> Use a literal value' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Value</td>' +
'<td><input id="valueNodeTypeValueInput" /></td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Value type</td>' +
'<td><select id="valueNodeTypeValueTypeSelect">' + literalTypeSelectHtml + '</select></td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Language</td>' +
'<td><input id="valueNodeTypeLanguageInput" /></td>' +
'</tr>' +
'</table>' +
'</td>' +
'<td>' +
'<table class="schema-align-node-dialog-layout2">' +
'<tr>' +
@ -383,6 +330,59 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
'</tr>' +
'</table>' +
'</td>' +
'<td>' +
'<table class="schema-align-node-dialog-layout2">' +
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="anonymous" id="radioNodeTypeAnonymous" /> Generate an anonymous graph node' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Assign a type to the node</td>' +
'<td>&nbsp;<input id="anonymousNodeTypeInput" /></td>' +
'</tr>' +
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="topic" id="radioNodeTypeTopic" /> Use one existing Freebase topic' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Topic</td>' +
'<td><input id="topicNodeTypeInput" /></td>' +
'</tr>' +
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="value" id="radioNodeTypeValue" /> Use a literal value' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Value</td>' +
'<td><input id="valueNodeTypeValueInput" /></td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Value type</td>' +
'<td><select id="valueNodeTypeValueTypeSelect">' + literalTypeSelectHtml + '</select></td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Language</td>' +
'<td><input id="valueNodeTypeLanguageInput" /></td>' +
'</tr>' +
'</table>' +
'</td>' +
'</tr>' +
'</table>'
).appendTo(body);
@ -406,19 +406,12 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
elmts.radioNodeTypeCellAs[0].checked = true;
if ("reconConfig" in column) {
var typeID = column.reconConfig.type;
$.getJSON(
"http://api.freebase.com/api/service/mqlread?query=" + JSON.stringify({ query: { "id" : typeID, "name" : null } }) + "&callback=?",
null,
function(o) {
if ("result" in o) {
elmts.cellAsTopicNodeTypeInput[0].value = o.result.name;
elmts.cellAsTopicNodeTypeInput.data("data.suggest", { "id" : typeID, "name" : o.result.name });
elmts.radioNodeTypeCellAsTopicCreate[0].checked = true;
}
},
"jsonp"
);
var typeID = column.reconConfig.type.id;
var typeName = column.reconConfig.type.name;
elmts.cellAsTopicNodeTypeInput[0].value = typeName;
elmts.cellAsTopicNodeTypeInput.data("data.suggest", { "id" : typeID, "name" : typeName });
elmts.radioNodeTypeCellAsTopicCreate[0].checked = true;
}
});

View File

@ -90,17 +90,47 @@ SchemaAlignment._cleanName = function(s) {
return s.replace(/\W/g, " ").replace(/\s+/g, " ").toLowerCase();
}
SchemaAlignment.createNewRootNode = function() {
var rootNode = null;
var links = [];
var columns = theProject.columnModel.columns;
for (var i = 0; i < columns.length; i++) {
var column = columns[i];
var target = {
nodeType: "cell-as-topic",
columnName: column.headerLabel,
createForNoReconMatch: true
};
if ("reconConfig" in column && column.reconConfig != null) {
target.type = {
id: column.reconConfig.type.id,
name: column.reconConfig.type.name
};
}
if (column.headerLabel == theProject.columnModel.keyColumnName) {
rootNode = target;
} else {
links.push({
property: null,
target: target
});
}
}
rootNode = rootNode || { nodeType: "cell-as-topic" };
rootNode.links = links;
return rootNode;
};
function SchemaAlignmentDialog(protograph, onDone) {
this._onDone = onDone;
this._originalProtograph = protograph || { rootNodes: [] };
this._protograph = cloneDeep(this._originalProtograph); // this is what can be munched on
if (this._protograph.rootNodes.length == 0) {
this._protograph.rootNodes.push({
nodeType: "cell-as-topic",
links: [
]
});
this._protograph.rootNodes.push(SchemaAlignment.createNewRootNode());
}
this._nodeUIs = [];