From 15bac748ac23dcaddb60bb757b9c203cb85fa1da Mon Sep 17 00:00:00 2001 From: Kevin Krouse Date: Mon, 2 Mar 2020 21:05:15 -0800 Subject: [PATCH 1/2] Item #6862: provenance loadRun API - include provenance properties in the loadRun response - share serialization of experiment objects in lineage API and loadRun API - add Identifiable.detailsURL --- flow/src/org/labkey/flow/data/FlowDataType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow/src/org/labkey/flow/data/FlowDataType.java b/flow/src/org/labkey/flow/data/FlowDataType.java index 03827afd2a..e18e891396 100644 --- a/flow/src/org/labkey/flow/data/FlowDataType.java +++ b/flow/src/org/labkey/flow/data/FlowDataType.java @@ -146,7 +146,7 @@ public String getName() } @Override - public URLHelper getDetailsURL(ExpData dataObject) + public ActionURL getDetailsURL(ExpData dataObject) { FlowDataObject fdo = FlowDataObject.fromData(dataObject); if (fdo != null) From e7faf0ef504dc477d39d75b21593c4918310e359 Mon Sep 17 00:00:00 2001 From: Kevin Krouse Date: Thu, 26 Mar 2020 17:40:54 -0700 Subject: [PATCH 2/2] - add LABKEY.Experiment.resolve() for resolving an LSID into an object - add QueryRowReference to Identifiable and include it when in lineage and loadRun response - optionally include run steps in LABKEY.Experiment.loadRun() response - optionally include provenance map in LABKEY.Experiment.loadRun() response --- .../flow/data/FlowCompensationControl.java | 10 +++ .../flow/data/FlowCompensationMatrix.java | 10 +++ .../org/labkey/flow/data/FlowDataObject.java | 8 +++ .../org/labkey/flow/data/FlowDataType.java | 72 ++++++++++++------- .../org/labkey/flow/data/FlowExperiment.java | 9 +++ .../org/labkey/flow/data/FlowFCSAnalysis.java | 10 +++ .../src/org/labkey/flow/data/FlowFCSFile.java | 9 +++ flow/src/org/labkey/flow/data/FlowObject.java | 13 +++- .../org/labkey/flow/data/FlowProtocol.java | 8 +++ .../flow/data/FlowProtocolImplementation.java | 11 +++ flow/src/org/labkey/flow/data/FlowRun.java | 8 +++ flow/src/org/labkey/flow/data/FlowScript.java | 10 ++- .../org/labkey/flow/data/FlowWorkspace.java | 7 ++ .../src/org/labkey/flow/query/FlowSchema.java | 3 +- 14 files changed, 158 insertions(+), 30 deletions(-) diff --git a/flow/src/org/labkey/flow/data/FlowCompensationControl.java b/flow/src/org/labkey/flow/data/FlowCompensationControl.java index 6829e06dea..54fc616d2c 100644 --- a/flow/src/org/labkey/flow/data/FlowCompensationControl.java +++ b/flow/src/org/labkey/flow/data/FlowCompensationControl.java @@ -17,6 +17,10 @@ package org.labkey.flow.data; import org.labkey.api.exp.api.ExpData; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; +import org.labkey.flow.query.FlowSchema; +import org.labkey.flow.query.FlowTableType; public class FlowCompensationControl extends FlowWell { @@ -27,4 +31,10 @@ public FlowCompensationControl(ExpData data) { super(data); } + + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), FlowSchema.SCHEMAKEY, FlowTableType.CompensationControls.name(), FieldKey.fromParts("RowId"), getRowId()); + } } diff --git a/flow/src/org/labkey/flow/data/FlowCompensationMatrix.java b/flow/src/org/labkey/flow/data/FlowCompensationMatrix.java index 9f544ef1e7..c7e628a87c 100644 --- a/flow/src/org/labkey/flow/data/FlowCompensationMatrix.java +++ b/flow/src/org/labkey/flow/data/FlowCompensationMatrix.java @@ -20,6 +20,8 @@ import org.labkey.api.data.DbScope; import org.labkey.api.exp.api.ExpData; import org.labkey.api.exp.api.ExperimentService; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.security.User; import org.labkey.api.view.ActionURL; import org.labkey.flow.FlowSettings; @@ -30,6 +32,8 @@ import org.labkey.flow.persist.AttributeSet; import org.labkey.flow.persist.AttributeSetHelper; import org.labkey.flow.persist.FlowDataHandler; +import org.labkey.flow.query.FlowSchema; +import org.labkey.flow.query.FlowTableType; import javax.servlet.http.HttpServletRequest; import java.io.File; @@ -141,6 +145,12 @@ public ActionURL urlDownload() return urlFor(CompensationController.DownloadAction.class); } + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), FlowSchema.SCHEMAKEY, FlowTableType.CompensationMatrices.name(), FieldKey.fromParts("RowId"), getRowId()); + } + public void addParams(Map map) { map.put(FlowParam.compId, getCompId()); diff --git a/flow/src/org/labkey/flow/data/FlowDataObject.java b/flow/src/org/labkey/flow/data/FlowDataObject.java index 5c027ca8d8..ccf4679114 100644 --- a/flow/src/org/labkey/flow/data/FlowDataObject.java +++ b/flow/src/org/labkey/flow/data/FlowDataObject.java @@ -24,6 +24,9 @@ import org.labkey.api.exp.api.ExpProtocolApplication; import org.labkey.api.exp.api.ExpRun; import org.labkey.api.exp.api.ExperimentService; +import org.labkey.api.exp.query.ExpSchema; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; import org.labkey.flow.persist.AttrObject; import org.labkey.flow.persist.AttributeSet; import org.labkey.flow.persist.AttributeSetHelper; @@ -283,4 +286,9 @@ public AttributeSet getAttributeSet(boolean includeGraphBytes) return AttributeSetHelper.fromData(getData(), includeGraphBytes); } + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), ExpSchema.SCHEMA_EXP, ExpSchema.TableType.Data.name(), FieldKey.fromParts("RowId"), getRowId()); + } } diff --git a/flow/src/org/labkey/flow/data/FlowDataType.java b/flow/src/org/labkey/flow/data/FlowDataType.java index e18e891396..85d19090ca 100644 --- a/flow/src/org/labkey/flow/data/FlowDataType.java +++ b/flow/src/org/labkey/flow/data/FlowDataType.java @@ -16,16 +16,20 @@ package org.labkey.flow.data; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.labkey.api.data.Container; import org.labkey.api.exp.Lsid; import org.labkey.api.exp.LsidManager; import org.labkey.api.exp.api.DataType; import org.labkey.api.exp.api.ExpDataRunInput; import org.labkey.api.exp.api.ExperimentService; import org.labkey.api.exp.api.ExpData; +import org.labkey.api.query.QueryRowReference; +import org.labkey.api.security.User; +import org.labkey.api.security.permissions.Permission; import org.labkey.api.settings.AppProps; import org.labkey.api.assay.AssayDataType; -import org.labkey.api.util.URLHelper; import org.labkey.api.view.ActionURL; import org.labkey.flow.persist.ObjectType; @@ -47,33 +51,37 @@ private FlowDataType(String type, String label, ObjectType objType, boolean requ _objType = objType; _requireAttrObject = requireAttrObject; - LsidManager.get().registerHandler(getNamespacePrefix(), new LsidManager.ExpObjectLsidHandler() + LsidManager.get().registerHandler(getNamespacePrefix(), new FlowDataObjectLsidHandler()); + } + + static final class FlowDataObjectLsidHandler implements LsidManager.LsidHandler + { + @Override + public FlowDataObject getObject(Lsid lsid) + { + return FlowDataObject.fromLSID(lsid.toString()); + } + + @Override + public @Nullable ActionURL getDisplayURL(Lsid lsid) { - @Override - public ExpData getObject(Lsid lsid) - { - FlowDataObject fdo = FlowDataObject.fromLSID(lsid.toString()); - if (fdo != null) - return fdo.getData(); - - return null; - } - - @Nullable - @Override - public ActionURL getDisplayURL(Lsid lsid) - { - FlowDataObject fdo = FlowDataObject.fromLSID(lsid.toString()); - if (fdo != null) - { - ActionURL url = fdo.urlShow(); - if (url != null) - return url; - } - - return null; - } - }); + FlowDataObject fdo = getObject(lsid); + return fdo != null ? fdo.urlShow() : null; + } + + @Override + public Container getContainer(Lsid lsid) + { + FlowDataObject fdo = getObject(lsid); + return fdo != null ? fdo.getContainer() : null; + } + + @Override + public boolean hasPermission(Lsid lsid, @NotNull User user, @NotNull Class perm) + { + FlowDataObject fdo = getObject(lsid); + return fdo != null ? fdo.getContainer().hasPermission(user, perm) : null; + } } static final public FlowDataType FCSFile = new FlowDataType("FCSFile", "FCS File", ObjectType.fcsKeywords, true) @@ -164,6 +172,16 @@ public ActionURL getDownloadURL(ExpData dataObject) return null; } + @Override + public @Nullable QueryRowReference getQueryRowReference(ExpData dataObject) + { + FlowDataObject fdo = FlowDataObject.fromData(dataObject); + if (fdo != null) + return fdo.getQueryRowReference(); + + return null; + } + @Override public String getRole() { diff --git a/flow/src/org/labkey/flow/data/FlowExperiment.java b/flow/src/org/labkey/flow/data/FlowExperiment.java index a8a1b86add..606421b3e7 100644 --- a/flow/src/org/labkey/flow/data/FlowExperiment.java +++ b/flow/src/org/labkey/flow/data/FlowExperiment.java @@ -22,11 +22,14 @@ import org.labkey.api.exp.api.ExpExperiment; import org.labkey.api.exp.api.ExpProtocol; import org.labkey.api.exp.api.ExperimentService; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.security.User; import org.labkey.api.view.ActionURL; import org.labkey.flow.controllers.FlowParam; import org.labkey.flow.controllers.run.RunController; import org.labkey.flow.query.FlowSchema; +import org.labkey.flow.query.FlowTableType; import javax.servlet.http.HttpServletRequest; import java.io.File; @@ -241,6 +244,12 @@ public ActionURL urlDownload() throw new UnsupportedOperationException(); } + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), FlowSchema.SCHEMAKEY, FlowTableType.Analyses.name(), FieldKey.fromParts("RowId"), getExperimentId()); + } + public boolean hasRun(File filePath, @Nullable FlowProtocolStep step) { List runs = getRuns(step); diff --git a/flow/src/org/labkey/flow/data/FlowFCSAnalysis.java b/flow/src/org/labkey/flow/data/FlowFCSAnalysis.java index accc462719..b0e203385b 100644 --- a/flow/src/org/labkey/flow/data/FlowFCSAnalysis.java +++ b/flow/src/org/labkey/flow/data/FlowFCSAnalysis.java @@ -17,6 +17,10 @@ package org.labkey.flow.data; import org.labkey.api.exp.api.ExpData; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; +import org.labkey.flow.query.FlowSchema; +import org.labkey.flow.query.FlowTableType; public class FlowFCSAnalysis extends FlowWell { @@ -27,4 +31,10 @@ public FlowFCSAnalysis(ExpData data) { super(data); } + + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), FlowSchema.SCHEMAKEY, FlowTableType.FCSAnalyses.name(), FieldKey.fromParts("RowId"), getRowId()); + } } diff --git a/flow/src/org/labkey/flow/data/FlowFCSFile.java b/flow/src/org/labkey/flow/data/FlowFCSFile.java index c59b1ed98d..6956155bd2 100644 --- a/flow/src/org/labkey/flow/data/FlowFCSFile.java +++ b/flow/src/org/labkey/flow/data/FlowFCSFile.java @@ -18,7 +18,11 @@ import org.labkey.api.data.Container; import org.labkey.api.exp.api.ExpData; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.security.User; +import org.labkey.flow.query.FlowSchema; +import org.labkey.flow.query.FlowTableType; import java.util.ArrayList; import java.util.Date; @@ -98,4 +102,9 @@ public void setFileDate(User user, Date date) throws Exception setProperty(user, FlowProperty.FileDate.getPropertyDescriptor(), date); } + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), FlowSchema.SCHEMAKEY, FlowTableType.FCSFiles.name(), FieldKey.fromParts("RowId"), getRowId()); + } } diff --git a/flow/src/org/labkey/flow/data/FlowObject.java b/flow/src/org/labkey/flow/data/FlowObject.java index 036804e48c..1ac0198cc0 100644 --- a/flow/src/org/labkey/flow/data/FlowObject.java +++ b/flow/src/org/labkey/flow/data/FlowObject.java @@ -16,15 +16,18 @@ package org.labkey.flow.data; +import org.jetbrains.annotations.Nullable; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerManager; import org.labkey.api.data.DataRegion; +import org.labkey.api.exp.Identifiable; import org.labkey.api.exp.Lsid; import org.labkey.api.exp.OntologyManager; import org.labkey.api.exp.PropertyDescriptor; import org.labkey.api.exp.api.DataType; import org.labkey.api.exp.api.ExpObject; import org.labkey.api.exp.property.SystemProperty; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.query.ValidationException; import org.labkey.api.security.User; import org.labkey.api.security.permissions.ReadPermission; @@ -45,7 +48,7 @@ import java.util.LinkedHashMap; import java.util.Map; -abstract public class FlowObject implements Comparable, Serializable +abstract public class FlowObject implements Comparable, Serializable, Identifiable { protected T _expObject; protected String _entityId; @@ -68,6 +71,14 @@ public T getExpObject() abstract public ActionURL urlShow(); abstract public ActionURL urlDownload(); + @Override + public @Nullable ActionURL detailsURL() + { + return urlShow(); + } + + abstract public QueryRowReference getQueryRowReference(); + public String getLSID() { return _expObject.getLSID(); diff --git a/flow/src/org/labkey/flow/data/FlowProtocol.java b/flow/src/org/labkey/flow/data/FlowProtocol.java index e943b7fa3b..bedabc9540 100644 --- a/flow/src/org/labkey/flow/data/FlowProtocol.java +++ b/flow/src/org/labkey/flow/data/FlowProtocol.java @@ -45,12 +45,14 @@ import org.labkey.api.exp.property.ExperimentProperty; import org.labkey.api.exp.query.ExpDataTable; import org.labkey.api.exp.query.ExpMaterialTable; +import org.labkey.api.exp.query.ExpSchema; import org.labkey.api.exp.query.SamplesSchema; import org.labkey.api.gwt.client.model.GWTPropertyDescriptor; import org.labkey.api.pipeline.PipeRoot; import org.labkey.api.pipeline.PipelineService; import org.labkey.api.query.BatchValidationException; import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.query.QueryService; import org.labkey.api.query.QueryUpdateService; import org.labkey.api.query.UserSchema; @@ -225,6 +227,12 @@ public ActionURL urlDownload() throw new UnsupportedOperationException(); } + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), ExpSchema.SCHEMA_EXP, ExpSchema.TableType.Protocols.name(), FieldKey.fromParts("RowId"), getProtocol().getRowId()); + } + public FlowProtocolStep getStep() { return FlowProtocolStep.fromLSID(getContainer(), getLSID()); diff --git a/flow/src/org/labkey/flow/data/FlowProtocolImplementation.java b/flow/src/org/labkey/flow/data/FlowProtocolImplementation.java index 78c3eff2a6..d26e6630b4 100644 --- a/flow/src/org/labkey/flow/data/FlowProtocolImplementation.java +++ b/flow/src/org/labkey/flow/data/FlowProtocolImplementation.java @@ -21,9 +21,14 @@ import org.labkey.api.data.SqlExecutor; import org.labkey.api.exp.api.ExpMaterial; import org.labkey.api.exp.api.ExpProtocol; +import org.labkey.api.exp.api.ExpRun; import org.labkey.api.exp.api.ExperimentService; import org.labkey.api.exp.api.ProtocolImplementation; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.security.User; +import org.labkey.flow.query.FlowSchema; +import org.labkey.flow.query.FlowTableType; import java.util.List; @@ -66,4 +71,10 @@ public void onRunDeleted(Container container, User user) new SqlExecutor(ExperimentService.get().getSchema()).execute(sql); } + + @Override + public QueryRowReference getQueryRowReference(ExpProtocol protocol, ExpRun run) + { + return new QueryRowReference(run.getContainer(), FlowSchema.SCHEMAKEY, FlowTableType.Runs.name(), FieldKey.fromParts("rowId"), run.getRowId()); + } } diff --git a/flow/src/org/labkey/flow/data/FlowRun.java b/flow/src/org/labkey/flow/data/FlowRun.java index 697ac78736..b5fb33d40c 100644 --- a/flow/src/org/labkey/flow/data/FlowRun.java +++ b/flow/src/org/labkey/flow/data/FlowRun.java @@ -31,6 +31,8 @@ import org.labkey.api.exp.api.ExpRun; import org.labkey.api.exp.api.ExpRunAttachmentParent; import org.labkey.api.exp.api.ExperimentService; +import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.query.QueryService; import org.labkey.api.security.User; import org.labkey.api.view.ActionURL; @@ -335,6 +337,12 @@ public ActionURL urlDownload() return urlFor(RunController.DownloadAction.class); } + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), FlowSchema.SCHEMAKEY, FlowTableType.Runs.name(), FieldKey.fromParts("RowId"), getRunId()); + } + public String getLabel() { return getName(); diff --git a/flow/src/org/labkey/flow/data/FlowScript.java b/flow/src/org/labkey/flow/data/FlowScript.java index fb953a6dae..6cf6ff165d 100644 --- a/flow/src/org/labkey/flow/data/FlowScript.java +++ b/flow/src/org/labkey/flow/data/FlowScript.java @@ -26,6 +26,7 @@ import org.labkey.api.exp.api.ExpProtocolApplication; import org.labkey.api.exp.api.ExperimentService; import org.labkey.api.query.FieldKey; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.security.User; import org.labkey.api.view.ActionURL; import org.labkey.flow.analysis.model.PopulationSet; @@ -39,12 +40,13 @@ import org.labkey.flow.persist.FlowDataHandler; import org.labkey.flow.persist.FlowManager; import org.labkey.flow.persist.InputRole; +import org.labkey.flow.query.FlowSchema; +import org.labkey.flow.query.FlowTableType; import org.labkey.flow.script.FlowAnalyzer; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import java.io.File; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -211,6 +213,12 @@ public ActionURL urlDownload() return urlFor(ScriptController.DownloadAction.class); } + @Override + public QueryRowReference getQueryRowReference() + { + return new QueryRowReference(getContainer(), FlowSchema.SCHEMAKEY, FlowTableType.AnalysisScripts.name(), FieldKey.fromParts("RowId"), getRowId()); + } + public String getLabel() { return "Script '" + getName() + "'"; diff --git a/flow/src/org/labkey/flow/data/FlowWorkspace.java b/flow/src/org/labkey/flow/data/FlowWorkspace.java index 31cd83e29c..37357083f2 100644 --- a/flow/src/org/labkey/flow/data/FlowWorkspace.java +++ b/flow/src/org/labkey/flow/data/FlowWorkspace.java @@ -20,6 +20,7 @@ import org.labkey.api.exp.api.ExpData; import org.labkey.api.exp.api.ExperimentService; import org.labkey.api.exp.api.ExperimentUrls; +import org.labkey.api.query.QueryRowReference; import org.labkey.api.security.User; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; @@ -127,4 +128,10 @@ public ActionURL urlDownload() return url; } + @Override + public QueryRowReference getQueryRowReference() + { + // UNDONE: Need a query table for the imported workspaces? + return super.getQueryRowReference(); + } } diff --git a/flow/src/org/labkey/flow/query/FlowSchema.java b/flow/src/org/labkey/flow/query/FlowSchema.java index d35ef06a81..806d7e8edf 100644 --- a/flow/src/org/labkey/flow/query/FlowSchema.java +++ b/flow/src/org/labkey/flow/query/FlowSchema.java @@ -117,6 +117,7 @@ public class FlowSchema extends UserSchema { static public final String SCHEMANAME = "flow"; + static public final SchemaKey SCHEMAKEY = SchemaKey.fromParts("flow"); static public final String SCHEMA_DESCR = "Contains data about flow cytometry experiment runs"; // Column name constants @@ -911,7 +912,7 @@ BaseColumnInfo addFileColumn(String columnAlias) //DetailsURL detailsURL = DetailsURL.fromString("/flow/download.view?dataId=${rowId}", getContainer()); PropertyDescriptor pd = new PropertyDescriptor(); pd.setURL(detailsURL); - ret.setDisplayColumnFactory(new FileLinkDisplayColumn.Factory(pd, getContainer(), SchemaKey.fromParts(FlowSchema.SCHEMANAME), FlowTableType.FCSFiles.name(), FieldKey.fromParts("RowId"))); + ret.setDisplayColumnFactory(new FileLinkDisplayColumn.Factory(pd, getContainer(), SCHEMAKEY, FlowTableType.FCSFiles.name(), FieldKey.fromParts("RowId"))); ret.setURL(detailsURL); ret.setHidden(true); addColumn(ret);