From f5fc44e24e8e5398b1de3cac4f41f2feb70b7924 Mon Sep 17 00:00:00 2001 From: David Huynh Date: Tue, 6 Jul 2010 00:14:07 +0000 Subject: [PATCH] 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 --- .../gridworks/ClientSideResourceManager.java | 34 ++++--- .../metaweb/gridworks/GridworksServlet.java | 75 +++++++++++----- .../commands/project/ExportRowsCommand.java | 4 + .../commands/project/GetModelsCommand.java | 16 ++-- .../ProtographTransposeExporter.java | 8 +- .../com/metaweb/gridworks/expr/Binder.java | 13 +++ .../gridworks/expr/ExpressionUtils.java | 16 ++++ .../gel/ControlFunctionRegistry.java | 4 +- .../metaweb/gridworks/model/OverlayModel.java | 7 ++ .../com/metaweb/gridworks/model/Project.java | 90 ++++++++++++++----- .../operations/OperationRegistry.java | 2 +- .../operations/SaveProtographOperation.java | 15 ++-- .../gridworks/protograph/Protograph.java | 21 +---- .../scripts/protograph/schema-alignment.js | 2 +- main/webapp/modules/core/scripts/util/url.js | 13 +++ 15 files changed, 233 insertions(+), 87 deletions(-) create mode 100644 main/src/com/metaweb/gridworks/expr/Binder.java create mode 100644 main/src/com/metaweb/gridworks/model/OverlayModel.java diff --git a/main/src/com/metaweb/gridworks/ClientSideResourceManager.java b/main/src/com/metaweb/gridworks/ClientSideResourceManager.java index 39001c316..e193cd9b9 100644 --- a/main/src/com/metaweb/gridworks/ClientSideResourceManager.java +++ b/main/src/com/metaweb/gridworks/ClientSideResourceManager.java @@ -7,11 +7,16 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import edu.mit.simile.butterfly.ButterflyModule; import edu.mit.simile.butterfly.MountPoint; public class ClientSideResourceManager { + final static Logger logger = LoggerFactory.getLogger("gridworks_clientSideResourceManager"); + static public class ClientSideResourceBundle { final protected Set _pathSet = new HashSet(); final protected List _pathList = new ArrayList(); @@ -33,6 +38,10 @@ public class ClientSideResourceManager { for (String path : paths) { 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)) { bundle._pathSet.add(fullPath); bundle._pathList.add(fullPath); @@ -52,16 +61,21 @@ public class ClientSideResourceManager { } static protected String resolve(ButterflyModule module, String path) { - StringBuffer sb = new StringBuffer(); - MountPoint mountPoint = module.getMountPoint(); - - boolean slashed = path.startsWith("/"); - char[] mountPointChars = mountPoint.getMountPoint().toCharArray(); - - sb.append(mountPointChars, 0, slashed ? mountPointChars.length - 1 : mountPointChars.length); - sb.append(path); - - return sb.toString(); + if (mountPoint != null) { + String mountPointPath = mountPoint.getMountPoint(); + if (mountPointPath != null) { + StringBuffer sb = new StringBuffer(); + + boolean slashed = path.startsWith("/"); + char[] mountPointChars = mountPointPath.toCharArray(); + + sb.append(mountPointChars, 0, slashed ? mountPointChars.length - 1 : mountPointChars.length); + sb.append(path); + + return sb.toString(); + } + } + return null; } } diff --git a/main/src/com/metaweb/gridworks/GridworksServlet.java b/main/src/com/metaweb/gridworks/GridworksServlet.java index 580309a3b..b2ad70a88 100644 --- a/main/src/com/metaweb/gridworks/GridworksServlet.java +++ b/main/src/com/metaweb/gridworks/GridworksServlet.java @@ -28,6 +28,8 @@ public class GridworksServlet extends Butterfly { private static final String JAVAX_SERVLET_CONTEXT_TEMPDIR = "javax.servlet.context.tempdir"; + static private GridworksServlet s_singleton; + static final private Map commands = new HashMap(); // timer for periodically saving projects @@ -112,7 +114,7 @@ public class GridworksServlet extends Butterfly { {"mqlwrite", "com.metaweb.gridworks.commands.freebase.MQLWriteCommand"}, {"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() { @@ -138,6 +140,8 @@ public class GridworksServlet extends Butterfly { @Override public void init() throws ServletException { super.init(); + + s_singleton = this; logger.trace("> initialize"); @@ -249,29 +253,39 @@ public class GridworksServlet extends Butterfly { for (String[] command : commandNames) { String commandName = command[0]; String className = command[1]; - logger.debug("Loading command " + commandName + " class: " + 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); + status |= registerOneCommand(commandName, className); } 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. * @@ -281,11 +295,14 @@ public class GridworksServlet extends Butterfly { * object implementing the command * @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)) { return false; } + + commandObject.init(this); commands.put(name, commandObject); + return true; } @@ -293,5 +310,19 @@ public class GridworksServlet extends Butterfly { protected boolean unregisterCommand(String verb) { 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); + } } diff --git a/main/src/com/metaweb/gridworks/commands/project/ExportRowsCommand.java b/main/src/com/metaweb/gridworks/commands/project/ExportRowsCommand.java index 21dc91bdd..cb369e3e4 100644 --- a/main/src/com/metaweb/gridworks/commands/project/ExportRowsCommand.java +++ b/main/src/com/metaweb/gridworks/commands/project/ExportRowsCommand.java @@ -38,6 +38,10 @@ public class ExportRowsCommand extends Command { s_formatToExporter.put("mqlwrite", new MqlwriteLikeExporter()); } + static public void registerExporter(String format, Exporter exporter) { + s_formatToExporter.put(format, exporter); + } + @SuppressWarnings("unchecked") static public Properties getRequestParameters(HttpServletRequest request) { Properties options = new Properties(); diff --git a/main/src/com/metaweb/gridworks/commands/project/GetModelsCommand.java b/main/src/com/metaweb/gridworks/commands/project/GetModelsCommand.java index 9f56a0cad..221e95257 100644 --- a/main/src/com/metaweb/gridworks/commands/project/GetModelsCommand.java +++ b/main/src/com/metaweb/gridworks/commands/project/GetModelsCommand.java @@ -13,6 +13,7 @@ import org.json.JSONWriter; import com.metaweb.gridworks.commands.Command; import com.metaweb.gridworks.expr.MetaParser; import com.metaweb.gridworks.expr.MetaParser.LanguageInfo; +import com.metaweb.gridworks.model.OverlayModel; import com.metaweb.gridworks.model.Project; public class GetModelsCommand extends Command { @@ -32,12 +33,17 @@ public class GetModelsCommand extends Command { writer.object(); writer.key("columnModel"); project.columnModel.write(writer, options); writer.key("recordModel"); project.recordModel.write(writer, options); - writer.key("protograph"); - if (project.protograph == null) { - writer.value(null); - } else { - project.protograph.write(writer, options); + + writer.key("overlayModels"); writer.object(); + for (String modelName : project.overlayModels.keySet()) { + OverlayModel overlayModel = project.overlayModels.get(modelName); + if (overlayModel != null) { + writer.key(modelName); + + project.overlayModels.get(modelName).write(writer, options); + } } + writer.endObject(); writer.key("scripting"); writer.object(); for (String languagePrefix : MetaParser.getLanguagePrefixes()) { diff --git a/main/src/com/metaweb/gridworks/exporters/ProtographTransposeExporter.java b/main/src/com/metaweb/gridworks/exporters/ProtographTransposeExporter.java index ba2e5d103..73214f900 100644 --- a/main/src/com/metaweb/gridworks/exporters/ProtographTransposeExporter.java +++ b/main/src/com/metaweb/gridworks/exporters/ProtographTransposeExporter.java @@ -36,12 +36,12 @@ abstract public class ProtographTransposeExporter implements Exporter { public void export(Project project, Properties options, Engine engine, Writer writer) throws IOException { - if (project.protograph != null) { - Protograph protograph = project.protograph; - + Protograph protograph = (Protograph) project.overlayModels.get("freebaseProtograph"); + if (protograph != null) { 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(); } diff --git a/main/src/com/metaweb/gridworks/expr/Binder.java b/main/src/com/metaweb/gridworks/expr/Binder.java new file mode 100644 index 000000000..0efa169ba --- /dev/null +++ b/main/src/com/metaweb/gridworks/expr/Binder.java @@ -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); +} diff --git a/main/src/com/metaweb/gridworks/expr/ExpressionUtils.java b/main/src/com/metaweb/gridworks/expr/ExpressionUtils.java index 48f56e72d..bf4f17246 100644 --- a/main/src/com/metaweb/gridworks/expr/ExpressionUtils.java +++ b/main/src/com/metaweb/gridworks/expr/ExpressionUtils.java @@ -4,14 +4,22 @@ import java.io.Serializable; import java.util.Calendar; import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Properties; +import java.util.Set; import com.metaweb.gridworks.model.Cell; import com.metaweb.gridworks.model.Project; import com.metaweb.gridworks.model.Row; public class ExpressionUtils { + static protected Set s_binders = new HashSet(); + + static public void registerBinder(Binder binder) { + s_binders.add(binder); + } + static public Properties createBindings(Project project) { Properties bindings = new Properties(); @@ -20,6 +28,10 @@ public class ExpressionUtils { bindings.put("project", project); + for (Binder binder : s_binders) { + binder.initializeBindings(bindings, project); + } + return bindings; } @@ -45,6 +57,10 @@ public class ExpressionUtils { bindings.put("value", cell.value); } } + + for (Binder binder : s_binders) { + binder.bind(bindings, row, rowIndex, columnName, cell); + } } static public boolean isError(Object o) { diff --git a/main/src/com/metaweb/gridworks/gel/ControlFunctionRegistry.java b/main/src/com/metaweb/gridworks/gel/ControlFunctionRegistry.java index f634ad3d3..cc038d05e 100644 --- a/main/src/com/metaweb/gridworks/gel/ControlFunctionRegistry.java +++ b/main/src/com/metaweb/gridworks/gel/ControlFunctionRegistry.java @@ -103,12 +103,12 @@ public class ControlFunctionRegistry { 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_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_controlToName.put(c, name); } diff --git a/main/src/com/metaweb/gridworks/model/OverlayModel.java b/main/src/com/metaweb/gridworks/model/OverlayModel.java new file mode 100644 index 000000000..d32b451ff --- /dev/null +++ b/main/src/com/metaweb/gridworks/model/OverlayModel.java @@ -0,0 +1,7 @@ +package com.metaweb.gridworks.model; + +import com.metaweb.gridworks.Jsonizable; + +public interface OverlayModel extends Jsonizable { + +} diff --git a/main/src/com/metaweb/gridworks/model/Project.java b/main/src/com/metaweb/gridworks/model/Project.java index 840d8499b..6dd98a137 100644 --- a/main/src/com/metaweb/gridworks/model/Project.java +++ b/main/src/com/metaweb/gridworks/model/Project.java @@ -5,11 +5,17 @@ import java.io.LineNumberReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,17 +25,30 @@ import com.metaweb.gridworks.ProjectMetadata; import com.metaweb.gridworks.history.History; import com.metaweb.gridworks.process.ProcessManager; import com.metaweb.gridworks.protograph.Protograph; +import com.metaweb.gridworks.util.ParsingUtilities; import com.metaweb.gridworks.util.Pool; public class Project { - final public long id; - - final public List rows = new ArrayList(); - final public ColumnModel columnModel = new ColumnModel(); - final public RecordModel recordModel = new RecordModel(); - public Protograph protograph; - - final public History history; + final static protected Map> + s_overlayModelClasses = new HashMap>(); + + static public void registerOverlayModel(String modelName, Class klass) { + s_overlayModelClasses.put(modelName, klass); + } + + static { + registerOverlayModel("freebaseProtograph", Protograph.class); + } + + final public long id; + final public List rows = new ArrayList(); + + final public ColumnModel columnModel = new ColumnModel(); + final public RecordModel recordModel = new RecordModel(); + final public Map overlayModels = new HashMap(); + + final public History history; + transient public ProcessManager processManager = new ProcessManager(); transient private Date _lastSave = new Date(); @@ -78,43 +97,58 @@ public class Project { protected void saveToWriter(Writer writer, Properties options) throws IOException { writer.write(GridworksServlet.getVersion()); writer.write('\n'); - + writer.write("columnModel=\n"); columnModel.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'); for (Row row : rows) { row.save(writer, options); writer.write('\n'); } } - + static public Project loadFromReader( LineNumberReader reader, long id, Pool pool ) throws Exception { long start = System.currentTimeMillis(); - + /* String version = */ reader.readLine(); - + Project project = new Project(id); int maxCellCount = 0; - + String line; while ((line = reader.readLine()) != null) { int equal = line.indexOf('='); - CharSequence field = line.subSequence(0, equal); + String field = line.substring(0, equal); String value = line.substring(equal + 1); - + + // backward compatibility + if ("protograph".equals(field)) { + field = "overlayModel:freebaseProtograph"; + } + if ("columnModel".equals(field)) { project.columnModel.load(reader); } else if ("history".equals(field)) { project.history.load(project, reader); - } else if ("protograph".equals(field)) { - project.protograph = Protograph.load(project, value); } else if ("rowCount".equals(field)) { int count = Integer.parseInt(value); @@ -126,6 +160,22 @@ public class Project { maxCellCount = Math.max(maxCellCount, row.cells.size()); } } + } else if (field.startsWith("overlayModel:")) { + String modelName = field.substring("overlayModel:".length()); + if (s_overlayModelClasses.containsKey(modelName)) { + Class 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); + } + } } } diff --git a/main/src/com/metaweb/gridworks/operations/OperationRegistry.java b/main/src/com/metaweb/gridworks/operations/OperationRegistry.java index 3dc7e5578..6a8690cdb 100644 --- a/main/src/com/metaweb/gridworks/operations/OperationRegistry.java +++ b/main/src/com/metaweb/gridworks/operations/OperationRegistry.java @@ -34,7 +34,7 @@ public abstract class OperationRegistry { static final public Map> s_opNameToClass = new HashMap>(); static final public Map, String> s_opClassToName = new HashMap, String>(); - static protected void register(String name, Class klass) { + static public void register(String name, Class klass) { s_opNameToClass.put(name, klass); s_opClassToName.put(klass, name); } diff --git a/main/src/com/metaweb/gridworks/operations/SaveProtographOperation.java b/main/src/com/metaweb/gridworks/operations/SaveProtographOperation.java index 8e50a3c99..94063d9bc 100644 --- a/main/src/com/metaweb/gridworks/operations/SaveProtographOperation.java +++ b/main/src/com/metaweb/gridworks/operations/SaveProtographOperation.java @@ -52,7 +52,7 @@ public class SaveProtographOperation extends AbstractOperation { return new HistoryEntry(historyEntryID, project, description, SaveProtographOperation.this, change); } - + static public class ProtographChange implements Change { final protected Protograph _newProtograph; protected Protograph _oldProtograph; @@ -63,14 +63,19 @@ public class SaveProtographOperation extends AbstractOperation { public void apply(Project project) { synchronized (project) { - _oldProtograph = project.protograph; - project.protograph = _newProtograph; + _oldProtograph = (Protograph) project.overlayModels.get("freebaseProtograph"); + + project.overlayModels.put("freebaseProtograph", _newProtograph); } } - + public void revert(Project project) { synchronized (project) { - project.protograph = _oldProtograph; + if (_oldProtograph == null) { + project.overlayModels.remove("freebaseProtograph"); + } else { + project.overlayModels.put("freebaseProtograph", _oldProtograph); + } } } diff --git a/main/src/com/metaweb/gridworks/protograph/Protograph.java b/main/src/com/metaweb/gridworks/protograph/Protograph.java index b4e1f466e..1255fd2a6 100644 --- a/main/src/com/metaweb/gridworks/protograph/Protograph.java +++ b/main/src/com/metaweb/gridworks/protograph/Protograph.java @@ -1,6 +1,5 @@ package com.metaweb.gridworks.protograph; -import java.io.Writer; import java.util.LinkedList; import java.util.List; import java.util.Properties; @@ -10,11 +9,10 @@ import org.json.JSONException; import org.json.JSONObject; 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.util.ParsingUtilities; -public class Protograph implements Jsonizable { +public class Protograph implements OverlayModel { final protected List _rootNodes = new LinkedList(); public int getRootNodeCount() { @@ -123,7 +121,7 @@ public class Protograph implements Jsonizable { o.getString("name") ); } - + public void write(JSONWriter writer, Properties options) throws JSONException { writer.object(); writer.key("rootNodes"); writer.array(); @@ -135,19 +133,8 @@ public class Protograph implements Jsonizable { writer.endArray(); 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 { - JSONObject obj = ParsingUtilities.evaluateJsonStringToObject(s); - + static public Protograph load(Project project, JSONObject obj) throws Exception { return reconstruct(obj); } } diff --git a/main/webapp/modules/core/scripts/protograph/schema-alignment.js b/main/webapp/modules/core/scripts/protograph/schema-alignment.js index 73c3fa4ea..847393de3 100644 --- a/main/webapp/modules/core/scripts/protograph/schema-alignment.js +++ b/main/webapp/modules/core/scripts/protograph/schema-alignment.js @@ -177,7 +177,7 @@ SchemaAlignmentDialog.prototype._constructFooter = function(footer) { { onDone: function() { DialogSystem.dismissUntil(self._level - 1); - theProject.protograph = protograph; + theProject.overlayModels.freebaseProtograph = protograph; } } ); diff --git a/main/webapp/modules/core/scripts/util/url.js b/main/webapp/modules/core/scripts/util/url.js index a067163db..2fce15341 100644 --- a/main/webapp/modules/core/scripts/util/url.js +++ b/main/webapp/modules/core/scripts/util/url.js @@ -68,4 +68,17 @@ URL.looksLikeUrl = function(s) { } } 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, '_')); }; \ No newline at end of file