Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bot] Fast-forward for 24.10.0 #5954

Merged
merged 15 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/src/org/labkey/api/ApiModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.labkey.api.assay.AssayFileWriter;
import org.labkey.api.assay.AssayResultsFileWriter;
import org.labkey.api.assay.ReplacedRunFilter;
import org.labkey.api.assay.sample.MaterialInputRoleComparator;
import org.labkey.api.attachments.AttachmentService;
import org.labkey.api.attachments.ImageServlet;
import org.labkey.api.attachments.LookAndFeelResourceType;
Expand Down Expand Up @@ -480,6 +481,7 @@ public void registerServlets(ServletContext servletCtx)
LabKeyCollectors.TestCase.class,
MapLoader.MapLoaderTestCase.class,
MarkdownService.TestCase.class,
MaterialInputRoleComparator.TestCase.class,
MimeMap.TestCase.class,
ModuleHtmlView.TestCase.class,
ModuleXml.TestCase.class,
Expand Down
120 changes: 14 additions & 106 deletions api/src/org/labkey/api/assay/AbstractAssayProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import org.labkey.api.data.DetailsColumn;
import org.labkey.api.data.DisplayColumn;
import org.labkey.api.data.ImportAliasable;
import org.labkey.api.data.RemapCache;
import org.labkey.api.data.RuntimeSQLException;
import org.labkey.api.data.SQLFragment;
import org.labkey.api.data.SimpleFilter;
Expand All @@ -52,7 +51,6 @@
import org.labkey.api.exp.LsidManager;
import org.labkey.api.exp.ObjectProperty;
import org.labkey.api.exp.OntologyManager;
import org.labkey.api.exp.PropertyColumn;
import org.labkey.api.exp.PropertyDescriptor;
import org.labkey.api.exp.PropertyType;
import org.labkey.api.exp.XarContext;
Expand Down Expand Up @@ -139,6 +137,7 @@
import java.util.Set;
import java.util.function.Supplier;

import static java.util.Collections.emptyList;
import static org.labkey.api.data.CompareType.IN;
import static org.labkey.api.util.PageFlowUtil.jsString;

Expand Down Expand Up @@ -1182,17 +1181,22 @@ public Class<? extends Controller> getDesignerAction()

/**
* Adds the materials as inputs to the run as a whole, plus as inputs for the "work" node for the run.
* @param materialInputs Map of materials to roles. If role is null, a generic role of "Sample N" will be used.
* @param materialInputs Map of materials to roles. If role is null, a generic role of "Sample" will be used.
*/
public static void addInputMaterials(ExpRun expRun, User user, Map<ExpMaterial, String> materialInputs)
{
if (materialInputs.isEmpty())
return;

for (ExpProtocolApplication protApp : expRun.getProtocolApplications())
{
if (!protApp.getApplicationType().equals(ExpProtocol.ApplicationType.ExperimentRunOutput))
if (!ExpProtocol.ApplicationType.ExperimentRunOutput.equals(protApp.getApplicationType()))
{
Map<ExpMaterial, String> newInputs = new LinkedHashMap<>(materialInputs);
for (ExpMaterial material : protApp.getInputMaterials())
newInputs.remove(material);

Map<String, Set<Integer>> inputGroups = new HashMap<>();
for (Map.Entry<ExpMaterial, String> entry : newInputs.entrySet())
{
ExpMaterial newInput = entry.getKey();
Expand All @@ -1202,8 +1206,12 @@ public static void addInputMaterials(ExpRun expRun, User user, Map<ExpMaterial,
ExpSampleType st = newInput.getSampleType();
role = st != null ? st.getName() : "Sample";
}
protApp.addMaterialInput(user, newInput, role);

inputGroups.computeIfAbsent(role, r -> new HashSet<>()).add(newInput.getRowId());
}

for (var entry : inputGroups.entrySet())
protApp.addMaterialInputs(user, entry.getValue(), entry.getKey(), null);
}
}
}
Expand Down Expand Up @@ -1462,7 +1470,7 @@ private static String createPropertyURI(ExpProtocol protocol, String propertySuf
@Override
public List<AssayDataType> getRelatedDataTypes()
{
return Collections.emptyList();
return emptyList();
}

public void setMaxFileInputs(int maxFileInputs)
Expand Down Expand Up @@ -2110,104 +2118,4 @@ private void updateResultFiles(FilteredTable assayResultTable, List<ExpRun> runs
}
}
}

// Issue 51316: While this issue is being addressed this feature has been disabled.
private final static boolean ENABLE_UPDATE_PROPERTY_LINEAGE = false;

@Override
public void updatePropertyLineage(
Container container,
User user,
TableInfo table,
ExpRun run,
Map<String, Object> newRow,
Map<String, Object> oldRow,
boolean isRunProperties,
@NotNull RemapCache cache,
@NotNull Map<Integer, ExpMaterial> materialsCache
) throws ValidationException
{
if (!ENABLE_UPDATE_PROPERTY_LINEAGE)
return;

Domain domain = table.getDomain();
if (domain == null || newRow == null || oldRow == null)
return;

Set<Integer> removedMaterialInputs = new HashSet<>();
Map<ExpMaterial, String> addedMaterialInputs = new HashMap<>();

// There can be multiple columns within a row that are lineage-backed material lookups.
// Coalesce these material input updates across columns.
for (var entry : newRow.entrySet())
{
Object newValue = entry.getValue();
Object oldValue = oldRow.get(entry.getKey());
if (newValue == oldValue)
continue;

ColumnInfo column = table.getColumn(entry.getKey());

if (column != null && (!isRunProperties || column instanceof PropertyColumn))
{
DomainProperty dp = domain.getPropertyByURI(column.getPropertyURI());
if (dp == null)
continue;

ExpSampleType sampleType = ExperimentService.get().getLookupSampleType(dp, container, user);
if (sampleType != null || ExperimentService.get().isLookupToMaterials(dp))
{
String inputRole = AssayService.get().getPropertyInputLineageRole(dp);

// Remove material inputs with the same role
for (var materialEntry : run.getMaterialInputs().entrySet())
{
if (inputRole.equalsIgnoreCase(materialEntry.getValue()))
{
// Issue 51316: Resolve the original material input rowId for this column
Integer originalRowId = null;
if (oldValue instanceof Integer _originalRowId)
originalRowId = _originalRowId;
else if (oldValue != null)
{
ExpMaterial originalMaterial = ExperimentService.get().findExpMaterial(container, user, oldValue, sampleType, cache, materialsCache);
if (originalMaterial != null)
originalRowId = originalMaterial.getRowId();
}

if (originalRowId != null && originalRowId == materialEntry.getKey().getRowId())
removedMaterialInputs.add(originalRowId);
}
}

ExpMaterial newInputMaterial = ExperimentService.get().findExpMaterial(container, user, newValue, sampleType, cache, materialsCache);
if (newInputMaterial != null)
{
// Prevent direct cycles
if (run.getMaterialOutputs().contains(newInputMaterial))
throw new ValidationException(String.format("Material \"%s\" is already marked as an output of this run and cannot be used as an input.", newInputMaterial.getName()));

addedMaterialInputs.put(newInputMaterial, inputRole);
}
}
}
}

if (!removedMaterialInputs.isEmpty())
{
var pa = run.getInputProtocolApplication();
if (pa != null)
pa.removeMaterialInputs(user, removedMaterialInputs);
}

if (!addedMaterialInputs.isEmpty())
{
var pa = run.getInputProtocolApplication();
if (pa != null)
{
for (var entry : addedMaterialInputs.entrySet())
pa.addMaterialInput(user, entry.getKey(), entry.getValue());
}
}
}
}
11 changes: 6 additions & 5 deletions api/src/org/labkey/api/assay/AbstractAssayTsvDataHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.jetbrains.annotations.Nullable;
import org.json.JSONArray;
import org.labkey.api.assay.plate.AssayPlateMetadataService;
import org.labkey.api.assay.sample.AssaySampleLookupContext;
import org.labkey.api.collections.CaseInsensitiveHashMap;
import org.labkey.api.collections.CaseInsensitiveHashSet;
import org.labkey.api.collections.Sets;
Expand Down Expand Up @@ -730,15 +731,15 @@ else if (pd.getName().equalsIgnoreCase(AbstractAssayProvider.TARGET_STUDY_PROPER
}
else
{
ExpSampleType st = ExperimentService.get().getLookupSampleType(pd, container, user);
if (st != null)
var sampleLookup = AssaySampleLookupContext.checkSampleLookup(container, user, pd);
if (sampleLookup.expSampleType() != null)
{
if (pd.getPropertyType().getJdbcType().isText())
lookupToSampleTypeByName.put(pd, st);
lookupToSampleTypeByName.put(pd, sampleLookup.expSampleType());
else
lookupToSampleTypeById.put(pd, st);
lookupToSampleTypeById.put(pd, sampleLookup.expSampleType());
}
else if (ExperimentService.get().isLookupToMaterials(pd))
else if (sampleLookup.isLookup())
{
if (pd.getPropertyType().getJdbcType().isText())
lookupToAllSamplesByName.add(pd);
Expand Down
21 changes: 4 additions & 17 deletions api/src/org/labkey/api/assay/AssayProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,13 @@
import org.labkey.api.assay.pipeline.AssayRunAsyncContext;
import org.labkey.api.data.Container;
import org.labkey.api.data.ContainerFilter;
import org.labkey.api.data.RemapCache;
import org.labkey.api.data.TableInfo;
import org.labkey.api.exp.ExperimentException;
import org.labkey.api.exp.Handler;
import org.labkey.api.exp.Lsid;
import org.labkey.api.exp.ObjectProperty;
import org.labkey.api.exp.XarContext;
import org.labkey.api.exp.api.ExpData;
import org.labkey.api.exp.api.ExpExperiment;
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.IAssayDomainType;
Expand Down Expand Up @@ -381,21 +378,11 @@ default boolean canRename()
}

/**
* Some assay implementations support experiment lineage representation of run/result property values.
* This can be called during the update of a run/result to ensure the associated lineage is updated when
* associated run/result property values change.
* Declares if an assay provider type supports having sample lookups in
* run/result domains persisted as material inputs to runs.
*/
default void updatePropertyLineage(
Container container,
User user,
TableInfo table,
ExpRun run,
Map<String, Object> newRow,
Map<String, Object> olRow,
boolean isRunProperties,
@NotNull RemapCache cache,
@NotNull Map<Integer, ExpMaterial> materialsCache
) throws ValidationException
default boolean supportsSampleLookupsAsMaterialInputs()
{
return false;
}
}
7 changes: 4 additions & 3 deletions api/src/org/labkey/api/assay/DefaultAssayRunCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.labkey.api.assay.actions.AssayRunUploadForm;
import org.labkey.api.assay.pipeline.AssayRunAsyncContext;
import org.labkey.api.assay.pipeline.AssayUploadPipelineJob;
import org.labkey.api.assay.sample.AssaySampleLookupContext;
import org.labkey.api.data.ColumnInfo;
import org.labkey.api.data.Container;
import org.labkey.api.data.ContainerManager;
Expand Down Expand Up @@ -621,12 +622,12 @@ protected void addInputMaterials(

// Lookup must point at "Samples.*", "exp.materials.*", or "exp.Materials"
DomainProperty dp = entry.getKey();
ExpSampleType st = ExperimentService.get().getLookupSampleType(dp, context.getContainer(), context.getUser());
if (st == null && !ExperimentService.get().isLookupToMaterials(dp))
var sampleLookup = AssaySampleLookupContext.checkSampleLookup(context.getContainer(), context.getUser(), dp);
if (!sampleLookup.isLookup())
continue;

String role = AssayService.get().getPropertyInputLineageRole(dp);
addMaterials(context, inputMaterials, Map.of(value, role), st, cache, materialCache);
addMaterials(context, inputMaterials, Map.of(value, role), sampleLookup.expSampleType(), cache, materialCache);
}
}

Expand Down
Loading
Loading