Refactoring to expose extension points that the rdf-exporter extension will plug into.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@1074 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-07-06 00:14:07 +00:00
parent ab82562016
commit f5fc44e24e
15 changed files with 233 additions and 87 deletions

View File

@ -7,11 +7,16 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.mit.simile.butterfly.ButterflyModule; import edu.mit.simile.butterfly.ButterflyModule;
import edu.mit.simile.butterfly.MountPoint; import edu.mit.simile.butterfly.MountPoint;
public class ClientSideResourceManager { public class ClientSideResourceManager {
final static Logger logger = LoggerFactory.getLogger("gridworks_clientSideResourceManager");
static public class ClientSideResourceBundle { static public class ClientSideResourceBundle {
final protected Set<String> _pathSet = new HashSet<String>(); final protected Set<String> _pathSet = new HashSet<String>();
final protected List<String> _pathList = new ArrayList<String>(); final protected List<String> _pathList = new ArrayList<String>();
@ -33,6 +38,10 @@ public class ClientSideResourceManager {
for (String path : paths) { for (String path : paths) {
String fullPath = resolve(module, path); String fullPath = resolve(module, path);
if (fullPath == null) {
logger.error("Failed to add paths to unmounted module " + module.getName());
break;
}
if (!bundle._pathSet.contains(fullPath)) { if (!bundle._pathSet.contains(fullPath)) {
bundle._pathSet.add(fullPath); bundle._pathSet.add(fullPath);
bundle._pathList.add(fullPath); bundle._pathList.add(fullPath);
@ -52,16 +61,21 @@ public class ClientSideResourceManager {
} }
static protected String resolve(ButterflyModule module, String path) { static protected String resolve(ButterflyModule module, String path) {
StringBuffer sb = new StringBuffer();
MountPoint mountPoint = module.getMountPoint(); MountPoint mountPoint = module.getMountPoint();
if (mountPoint != null) {
boolean slashed = path.startsWith("/"); String mountPointPath = mountPoint.getMountPoint();
char[] mountPointChars = mountPoint.getMountPoint().toCharArray(); if (mountPointPath != null) {
StringBuffer sb = new StringBuffer();
sb.append(mountPointChars, 0, slashed ? mountPointChars.length - 1 : mountPointChars.length);
sb.append(path); boolean slashed = path.startsWith("/");
char[] mountPointChars = mountPointPath.toCharArray();
return sb.toString();
sb.append(mountPointChars, 0, slashed ? mountPointChars.length - 1 : mountPointChars.length);
sb.append(path);
return sb.toString();
}
}
return null;
} }
} }

View File

@ -28,6 +28,8 @@ public class GridworksServlet extends Butterfly {
private static final String JAVAX_SERVLET_CONTEXT_TEMPDIR = "javax.servlet.context.tempdir"; private static final String JAVAX_SERVLET_CONTEXT_TEMPDIR = "javax.servlet.context.tempdir";
static private GridworksServlet s_singleton;
static final private Map<String, Command> commands = new HashMap<String, Command>(); static final private Map<String, Command> commands = new HashMap<String, Command>();
// timer for periodically saving projects // timer for periodically saving projects
@ -112,7 +114,7 @@ public class GridworksServlet extends Butterfly {
{"mqlwrite", "com.metaweb.gridworks.commands.freebase.MQLWriteCommand"}, {"mqlwrite", "com.metaweb.gridworks.commands.freebase.MQLWriteCommand"},
{"get-preference", "com.metaweb.gridworks.commands.GetPreferenceCommand"}, {"get-preference", "com.metaweb.gridworks.commands.GetPreferenceCommand"},
{"set-preference", "com.metaweb.gridworks.commands.SetPreferenceCommand"} {"set-preference", "com.metaweb.gridworks.commands.SetPreferenceCommand"},
}; };
public static String getVersion() { public static String getVersion() {
@ -138,6 +140,8 @@ public class GridworksServlet extends Butterfly {
@Override @Override
public void init() throws ServletException { public void init() throws ServletException {
super.init(); super.init();
s_singleton = this;
logger.trace("> initialize"); logger.trace("> initialize");
@ -249,29 +253,39 @@ public class GridworksServlet extends Butterfly {
for (String[] command : commandNames) { for (String[] command : commandNames) {
String commandName = command[0]; String commandName = command[0];
String className = command[1]; String className = command[1];
logger.debug("Loading command " + commandName + " class: " + className); status |= registerOneCommand(commandName, className);
Command cmd;
try {
cmd = (Command) this.getClass().getClassLoader().loadClass(className).newInstance();
cmd.init(this);
} catch (InstantiationException e) {
logger.error("Failed to load command class " + className, e);
status = false;
continue;
} catch (IllegalAccessException e) {
logger.error("Failed to load command class " + className, e);
status = false;
continue;
} catch (ClassNotFoundException e) {
logger.error("Failed to load command class " + className, e);
status = false;
continue;
}
status |= registerCommand(commandName, cmd);
} }
return status; return status;
} }
/**
* Register a single command given its class name.
*
* @param name
* command verb for command
* @param className
* class name of command class
* @return true if command was loaded and registered successfully
*/
protected boolean registerOneCommand(String commandName, String className) {
logger.debug("Loading command " + commandName + " class: " + className);
Command cmd;
try {
cmd = (Command) this.getClass().getClassLoader().loadClass(className).newInstance();
return registerOneCommand(commandName, cmd);
} catch (InstantiationException e) {
logger.error("Failed to load command class " + className, e);
return false;
} catch (IllegalAccessException e) {
logger.error("Failed to load command class " + className, e);
return false;
} catch (ClassNotFoundException e) {
logger.error("Failed to load command class " + className, e);
return false;
}
}
/** /**
* Register a single command. * Register a single command.
* *
@ -281,11 +295,14 @@ public class GridworksServlet extends Butterfly {
* object implementing the command * object implementing the command
* @return true if command was loaded and registered successfully * @return true if command was loaded and registered successfully
*/ */
protected boolean registerCommand(String name, Command commandObject) { protected boolean registerOneCommand(String name, Command commandObject) {
if (commands.containsKey(name)) { if (commands.containsKey(name)) {
return false; return false;
} }
commandObject.init(this);
commands.put(name, commandObject); commands.put(name, commandObject);
return true; return true;
} }
@ -293,5 +310,19 @@ public class GridworksServlet extends Butterfly {
protected boolean unregisterCommand(String verb) { protected boolean unregisterCommand(String verb) {
return commands.remove(verb) != null; return commands.remove(verb) != null;
} }
/**
* Register a single command. Used by extensions.
*
* @param name
* command verb for command
* @param commandObject
* object implementing the command
*
* @return true if command was loaded and registered successfully
*/
static public boolean registerCommand(String commandName, Command commandObject) {
return s_singleton.registerOneCommand(commandName, commandObject);
}
} }

View File

@ -38,6 +38,10 @@ public class ExportRowsCommand extends Command {
s_formatToExporter.put("mqlwrite", new MqlwriteLikeExporter()); s_formatToExporter.put("mqlwrite", new MqlwriteLikeExporter());
} }
static public void registerExporter(String format, Exporter exporter) {
s_formatToExporter.put(format, exporter);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static public Properties getRequestParameters(HttpServletRequest request) { static public Properties getRequestParameters(HttpServletRequest request) {
Properties options = new Properties(); Properties options = new Properties();

View File

@ -13,6 +13,7 @@ import org.json.JSONWriter;
import com.metaweb.gridworks.commands.Command; import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.expr.MetaParser; import com.metaweb.gridworks.expr.MetaParser;
import com.metaweb.gridworks.expr.MetaParser.LanguageInfo; import com.metaweb.gridworks.expr.MetaParser.LanguageInfo;
import com.metaweb.gridworks.model.OverlayModel;
import com.metaweb.gridworks.model.Project; import com.metaweb.gridworks.model.Project;
public class GetModelsCommand extends Command { public class GetModelsCommand extends Command {
@ -32,12 +33,17 @@ public class GetModelsCommand extends Command {
writer.object(); writer.object();
writer.key("columnModel"); project.columnModel.write(writer, options); writer.key("columnModel"); project.columnModel.write(writer, options);
writer.key("recordModel"); project.recordModel.write(writer, options); writer.key("recordModel"); project.recordModel.write(writer, options);
writer.key("protograph");
if (project.protograph == null) { writer.key("overlayModels"); writer.object();
writer.value(null); for (String modelName : project.overlayModels.keySet()) {
} else { OverlayModel overlayModel = project.overlayModels.get(modelName);
project.protograph.write(writer, options); if (overlayModel != null) {
writer.key(modelName);
project.overlayModels.get(modelName).write(writer, options);
}
} }
writer.endObject();
writer.key("scripting"); writer.object(); writer.key("scripting"); writer.object();
for (String languagePrefix : MetaParser.getLanguagePrefixes()) { for (String languagePrefix : MetaParser.getLanguagePrefixes()) {

View File

@ -36,12 +36,12 @@ abstract public class ProtographTransposeExporter implements Exporter {
public void export(Project project, Properties options, Engine engine, public void export(Project project, Properties options, Engine engine,
Writer writer) throws IOException { Writer writer) throws IOException {
if (project.protograph != null) { Protograph protograph = (Protograph) project.overlayModels.get("freebaseProtograph");
Protograph protograph = project.protograph; if (protograph != null) {
TransposedNodeFactory nodeFactory = createNodeFactory(project, writer); TransposedNodeFactory nodeFactory = createNodeFactory(project, writer);
Transposer.transpose(project, engine.getAllFilteredRows(), protograph, protograph.getRootNode(0), nodeFactory, -1); Transposer.transpose(project, engine.getAllFilteredRows(),
protograph, protograph.getRootNode(0), nodeFactory, -1);
nodeFactory.flush(); nodeFactory.flush();
} }

View File

@ -0,0 +1,13 @@
package com.metaweb.gridworks.expr;
import java.util.Properties;
import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
public interface Binder {
public void initializeBindings(Properties bindings, Project project);
public void bind(Properties bindings, Row row, int rowIndex, String columnName, Cell cell);
}

View File

@ -4,14 +4,22 @@ import java.io.Serializable;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
import com.metaweb.gridworks.model.Cell; import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Project; import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row; import com.metaweb.gridworks.model.Row;
public class ExpressionUtils { public class ExpressionUtils {
static protected Set<Binder> s_binders = new HashSet<Binder>();
static public void registerBinder(Binder binder) {
s_binders.add(binder);
}
static public Properties createBindings(Project project) { static public Properties createBindings(Project project) {
Properties bindings = new Properties(); Properties bindings = new Properties();
@ -20,6 +28,10 @@ public class ExpressionUtils {
bindings.put("project", project); bindings.put("project", project);
for (Binder binder : s_binders) {
binder.initializeBindings(bindings, project);
}
return bindings; return bindings;
} }
@ -45,6 +57,10 @@ public class ExpressionUtils {
bindings.put("value", cell.value); bindings.put("value", cell.value);
} }
} }
for (Binder binder : s_binders) {
binder.bind(bindings, row, rowIndex, columnName, cell);
}
} }
static public boolean isError(Object o) { static public boolean isError(Object o) {

View File

@ -103,12 +103,12 @@ public class ControlFunctionRegistry {
return s_nameToControl.entrySet(); return s_nameToControl.entrySet();
} }
static protected void registerFunction(String name, Function f) { static public void registerFunction(String name, Function f) {
s_nameToFunction.put(name, f); s_nameToFunction.put(name, f);
s_functionToName.put(f, name); s_functionToName.put(f, name);
} }
static protected void registerControl(String name, Control c) { static public void registerControl(String name, Control c) {
s_nameToControl.put(name, c); s_nameToControl.put(name, c);
s_controlToName.put(c, name); s_controlToName.put(c, name);
} }

View File

@ -0,0 +1,7 @@
package com.metaweb.gridworks.model;
import com.metaweb.gridworks.Jsonizable;
public interface OverlayModel extends Jsonizable {
}

View File

@ -5,11 +5,17 @@ import java.io.LineNumberReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -19,17 +25,30 @@ import com.metaweb.gridworks.ProjectMetadata;
import com.metaweb.gridworks.history.History; import com.metaweb.gridworks.history.History;
import com.metaweb.gridworks.process.ProcessManager; import com.metaweb.gridworks.process.ProcessManager;
import com.metaweb.gridworks.protograph.Protograph; import com.metaweb.gridworks.protograph.Protograph;
import com.metaweb.gridworks.util.ParsingUtilities;
import com.metaweb.gridworks.util.Pool; import com.metaweb.gridworks.util.Pool;
public class Project { public class Project {
final public long id; final static protected Map<String, Class<? extends OverlayModel>>
s_overlayModelClasses = new HashMap<String, Class<? extends OverlayModel>>();
final public List<Row> rows = new ArrayList<Row>();
final public ColumnModel columnModel = new ColumnModel(); static public void registerOverlayModel(String modelName, Class<? extends OverlayModel> klass) {
final public RecordModel recordModel = new RecordModel(); s_overlayModelClasses.put(modelName, klass);
public Protograph protograph; }
final public History history; static {
registerOverlayModel("freebaseProtograph", Protograph.class);
}
final public long id;
final public List<Row> rows = new ArrayList<Row>();
final public ColumnModel columnModel = new ColumnModel();
final public RecordModel recordModel = new RecordModel();
final public Map<String, OverlayModel> overlayModels = new HashMap<String, OverlayModel>();
final public History history;
transient public ProcessManager processManager = new ProcessManager(); transient public ProcessManager processManager = new ProcessManager();
transient private Date _lastSave = new Date(); transient private Date _lastSave = new Date();
@ -78,43 +97,58 @@ public class Project {
protected void saveToWriter(Writer writer, Properties options) throws IOException { protected void saveToWriter(Writer writer, Properties options) throws IOException {
writer.write(GridworksServlet.getVersion()); writer.write('\n'); writer.write(GridworksServlet.getVersion()); writer.write('\n');
writer.write("columnModel=\n"); columnModel.save(writer, options); writer.write("columnModel=\n"); columnModel.save(writer, options);
writer.write("history=\n"); history.save(writer, options); writer.write("history=\n"); history.save(writer, options);
if (protograph != null) {
writer.write("protograph="); protograph.save(writer, options); writer.write('\n'); for (String modelName : overlayModels.keySet()) {
writer.write("overlayModel:");
writer.write(modelName);
writer.write("=");
try {
JSONWriter jsonWriter = new JSONWriter(writer);
overlayModels.get(modelName).write(jsonWriter, options);
} catch (JSONException e) {
e.printStackTrace();
}
writer.write('\n');
} }
writer.write("rowCount="); writer.write(Integer.toString(rows.size())); writer.write('\n'); writer.write("rowCount="); writer.write(Integer.toString(rows.size())); writer.write('\n');
for (Row row : rows) { for (Row row : rows) {
row.save(writer, options); writer.write('\n'); row.save(writer, options); writer.write('\n');
} }
} }
static public Project loadFromReader( static public Project loadFromReader(
LineNumberReader reader, LineNumberReader reader,
long id, long id,
Pool pool Pool pool
) throws Exception { ) throws Exception {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
/* String version = */ reader.readLine(); /* String version = */ reader.readLine();
Project project = new Project(id); Project project = new Project(id);
int maxCellCount = 0; int maxCellCount = 0;
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
int equal = line.indexOf('='); int equal = line.indexOf('=');
CharSequence field = line.subSequence(0, equal); String field = line.substring(0, equal);
String value = line.substring(equal + 1); String value = line.substring(equal + 1);
// backward compatibility
if ("protograph".equals(field)) {
field = "overlayModel:freebaseProtograph";
}
if ("columnModel".equals(field)) { if ("columnModel".equals(field)) {
project.columnModel.load(reader); project.columnModel.load(reader);
} else if ("history".equals(field)) { } else if ("history".equals(field)) {
project.history.load(project, reader); project.history.load(project, reader);
} else if ("protograph".equals(field)) {
project.protograph = Protograph.load(project, value);
} else if ("rowCount".equals(field)) { } else if ("rowCount".equals(field)) {
int count = Integer.parseInt(value); int count = Integer.parseInt(value);
@ -126,6 +160,22 @@ public class Project {
maxCellCount = Math.max(maxCellCount, row.cells.size()); maxCellCount = Math.max(maxCellCount, row.cells.size());
} }
} }
} else if (field.startsWith("overlayModel:")) {
String modelName = field.substring("overlayModel:".length());
if (s_overlayModelClasses.containsKey(modelName)) {
Class<? extends OverlayModel> klass = s_overlayModelClasses.get(modelName);
try {
Method loadMethod = klass.getMethod("load", Project.class, JSONObject.class);
JSONObject obj = ParsingUtilities.evaluateJsonStringToObject(value);
OverlayModel overlayModel = (OverlayModel) loadMethod.invoke(null, project, obj);
project.overlayModels.put(modelName, overlayModel);
} catch (Exception e) {
logger.error("Failed to load overlay model " + modelName);
}
}
} }
} }

View File

@ -34,7 +34,7 @@ public abstract class OperationRegistry {
static final public Map<String, Class<? extends AbstractOperation>> s_opNameToClass = new HashMap<String, Class<? extends AbstractOperation>>(); static final public Map<String, Class<? extends AbstractOperation>> s_opNameToClass = new HashMap<String, Class<? extends AbstractOperation>>();
static final public Map<Class<? extends AbstractOperation>, String> s_opClassToName = new HashMap<Class<? extends AbstractOperation>, String>(); static final public Map<Class<? extends AbstractOperation>, String> s_opClassToName = new HashMap<Class<? extends AbstractOperation>, String>();
static protected void register(String name, Class<? extends AbstractOperation> klass) { static public void register(String name, Class<? extends AbstractOperation> klass) {
s_opNameToClass.put(name, klass); s_opNameToClass.put(name, klass);
s_opClassToName.put(klass, name); s_opClassToName.put(klass, name);
} }

View File

@ -52,7 +52,7 @@ public class SaveProtographOperation extends AbstractOperation {
return new HistoryEntry(historyEntryID, project, description, SaveProtographOperation.this, change); return new HistoryEntry(historyEntryID, project, description, SaveProtographOperation.this, change);
} }
static public class ProtographChange implements Change { static public class ProtographChange implements Change {
final protected Protograph _newProtograph; final protected Protograph _newProtograph;
protected Protograph _oldProtograph; protected Protograph _oldProtograph;
@ -63,14 +63,19 @@ public class SaveProtographOperation extends AbstractOperation {
public void apply(Project project) { public void apply(Project project) {
synchronized (project) { synchronized (project) {
_oldProtograph = project.protograph; _oldProtograph = (Protograph) project.overlayModels.get("freebaseProtograph");
project.protograph = _newProtograph;
project.overlayModels.put("freebaseProtograph", _newProtograph);
} }
} }
public void revert(Project project) { public void revert(Project project) {
synchronized (project) { synchronized (project) {
project.protograph = _oldProtograph; if (_oldProtograph == null) {
project.overlayModels.remove("freebaseProtograph");
} else {
project.overlayModels.put("freebaseProtograph", _oldProtograph);
}
} }
} }

View File

@ -1,6 +1,5 @@
package com.metaweb.gridworks.protograph; package com.metaweb.gridworks.protograph;
import java.io.Writer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
@ -10,11 +9,10 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.Jsonizable; import com.metaweb.gridworks.model.OverlayModel;
import com.metaweb.gridworks.model.Project; import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.util.ParsingUtilities;
public class Protograph implements Jsonizable { public class Protograph implements OverlayModel {
final protected List<Node> _rootNodes = new LinkedList<Node>(); final protected List<Node> _rootNodes = new LinkedList<Node>();
public int getRootNodeCount() { public int getRootNodeCount() {
@ -123,7 +121,7 @@ public class Protograph implements Jsonizable {
o.getString("name") o.getString("name")
); );
} }
public void write(JSONWriter writer, Properties options) throws JSONException { public void write(JSONWriter writer, Properties options) throws JSONException {
writer.object(); writer.object();
writer.key("rootNodes"); writer.array(); writer.key("rootNodes"); writer.array();
@ -135,19 +133,8 @@ public class Protograph implements Jsonizable {
writer.endArray(); writer.endArray();
writer.endObject(); writer.endObject();
} }
public void save(Writer writer, Properties options) {
JSONWriter jsonWriter = new JSONWriter(writer);
try {
write(jsonWriter, options);
} catch (JSONException e) {
e.printStackTrace();
}
}
static public Protograph load(Project project, String s) throws Exception { static public Protograph load(Project project, JSONObject obj) throws Exception {
JSONObject obj = ParsingUtilities.evaluateJsonStringToObject(s);
return reconstruct(obj); return reconstruct(obj);
} }
} }

View File

@ -177,7 +177,7 @@ SchemaAlignmentDialog.prototype._constructFooter = function(footer) {
{ {
onDone: function() { onDone: function() {
DialogSystem.dismissUntil(self._level - 1); DialogSystem.dismissUntil(self._level - 1);
theProject.protograph = protograph; theProject.overlayModels.freebaseProtograph = protograph;
} }
} }
); );

View File

@ -68,4 +68,17 @@ URL.looksLikeUrl = function(s) {
} }
} }
return false; return false;
};
URL.getHostname = function(){
var url = location.href; // entire url including querystring - also: window.location.href;
var baseURL = url.substring(0, url.indexOf('/',7));//7 is the length of http://
return baseURL;
};
URL.urlify = function(str) {
if(!str) {
return '';
}
return escape(str.replace(/\W/g, '_'));
}; };