Skip to content

Commit 2fab14e

Browse files
Merge 26.4 to develop
2 parents ec3c84f + 8e58454 commit 2fab14e

7 files changed

Lines changed: 1132 additions & 3 deletions

File tree

api/src/org/labkey/api/study/actions/ParticipantVisitResolverChooser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value)
168168
return ret2;
169169
}
170170
),
171-
disabledInput ? InputBuilder.hidden().name(_typeInputName).value(finalSelected.getName()).appendTo(out) : null
171+
disabledInput ? InputBuilder.hidden().name(_typeInputName).value(finalSelected.getName()).getHtmlString() : null
172172
)
173173
).appendTo(out);
174174
}
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
package org.labkey.api.workflow;
2+
3+
import com.fasterxml.jackson.annotation.JsonIgnore;
4+
import org.apache.commons.lang3.StringUtils;
5+
import org.json.JSONArray;
6+
import org.json.JSONObject;
7+
import org.labkey.api.data.CreatedModified;
8+
import org.labkey.api.exp.api.ExpProtocol;
9+
import org.labkey.api.exp.api.ExperimentService;
10+
import org.labkey.api.exp.api.SampleTypeService;
11+
import org.labkey.api.util.GUID;
12+
13+
import java.util.ArrayList;
14+
import java.util.Collections;
15+
import java.util.HashSet;
16+
import java.util.LinkedHashMap;
17+
import java.util.List;
18+
import java.util.Map;
19+
import java.util.Set;
20+
21+
public abstract class Action extends CreatedModified
22+
{
23+
public static final String ASSAY_TYPES_KEY = "assayTypes";
24+
public static final String NUM_PER_PARENT_KEY = "numPerParent";
25+
protected Long _rowId;
26+
protected int _ordinal;
27+
protected GUID _containerId;
28+
protected String _name;
29+
protected boolean _isUpdatable = false;
30+
protected Long _taskId;
31+
protected WorkflowService.ActionType _type;
32+
protected JSONObject _inputParameters;
33+
34+
35+
public Long getRowId()
36+
{
37+
return _rowId;
38+
}
39+
40+
public void setRowId(Long rowId)
41+
{
42+
_rowId = rowId;
43+
}
44+
45+
public GUID getContainerId()
46+
{
47+
return _containerId;
48+
}
49+
50+
public void setContainerId(GUID containerId)
51+
{
52+
_containerId = containerId;
53+
}
54+
55+
public String getName()
56+
{
57+
return _name;
58+
}
59+
60+
public void setName(String name)
61+
{
62+
_name = name;
63+
}
64+
65+
public int getOrdinal()
66+
{
67+
return _ordinal;
68+
}
69+
70+
public void setOrdinal(int ordinal)
71+
{
72+
_ordinal = ordinal;
73+
}
74+
75+
public boolean getIsUpdatable()
76+
{
77+
return _isUpdatable;
78+
}
79+
80+
public void setIsUpdatable(boolean updatable)
81+
{
82+
_isUpdatable = updatable;
83+
}
84+
85+
public Long getTaskId()
86+
{
87+
return _taskId;
88+
}
89+
90+
public void setTaskId(Long taskId)
91+
{
92+
_taskId = taskId;
93+
}
94+
95+
public WorkflowService.ActionType getType()
96+
{
97+
return _type;
98+
}
99+
100+
public void setType(WorkflowService.ActionType type)
101+
{
102+
_type = type;
103+
}
104+
105+
public JSONObject getInputParameters()
106+
{
107+
return _inputParameters;
108+
}
109+
110+
public void setInputParameters(JSONObject inputParameters)
111+
{
112+
_inputParameters = inputParameters;
113+
}
114+
115+
@JsonIgnore
116+
public List<String> validateInputParameters(int ordinal)
117+
{
118+
String prefix = "Action #" + ordinal + ": ";
119+
if (_type == WorkflowService.ActionType.AssayImport)
120+
{
121+
if (_inputParameters != null && _inputParameters.has(ASSAY_TYPES_KEY))
122+
{
123+
try
124+
{
125+
JSONArray assayTypes = _inputParameters.getJSONArray(ASSAY_TYPES_KEY);
126+
// When assay types are updatable, there may be none provided. Usually that means the inputParameters will
127+
// be empty or null, but it also works if the assay types array is empty.
128+
if (assayTypes.isEmpty())
129+
return Collections.emptyList();
130+
131+
Set<Object> invalidAssayIds = new HashSet<>();
132+
assayTypes.toList().forEach(assayId ->
133+
{
134+
try
135+
{
136+
int protocolId = (assayId instanceof String) ? Integer.valueOf((String) assayId) : (Integer) assayId;
137+
ExpProtocol assay = ExperimentService.get().getExpProtocol(protocolId);
138+
if (null == assay)
139+
invalidAssayIds.add(protocolId);
140+
}
141+
catch (Exception e)
142+
{
143+
invalidAssayIds.add(assayId);
144+
}
145+
});
146+
if (!invalidAssayIds.isEmpty())
147+
return List.of(prefix + "invalid assay IDs " + invalidAssayIds + ".");
148+
}
149+
catch (Exception e)
150+
{
151+
return List.of(prefix + ASSAY_TYPES_KEY + " must be an array.");
152+
}
153+
}
154+
155+
}
156+
else if (_type == WorkflowService.ActionType.AliquotSamples)
157+
{
158+
if (_inputParameters == null || !_inputParameters.has(NUM_PER_PARENT_KEY))
159+
return List.of(prefix + NUM_PER_PARENT_KEY + " is required for action of type " + _type + ".");
160+
else
161+
{
162+
try {
163+
int numPerParent = _inputParameters.getInt(NUM_PER_PARENT_KEY);
164+
if (numPerParent < 0)
165+
return List.of(prefix + NUM_PER_PARENT_KEY + " cannot be negative.");
166+
}
167+
catch (Exception e) {
168+
return List.of(prefix + NUM_PER_PARENT_KEY + " must be an integer.");
169+
}
170+
}
171+
}
172+
else
173+
{
174+
if (_inputParameters == null || _inputParameters.isEmpty())
175+
return List.of(prefix + "data about sample types and sample counts per parent is required for action of type " + _type + ".");
176+
if (_type == WorkflowService.ActionType.PoolSamples && _inputParameters.length() > 1)
177+
return List.of(prefix + "only one sample type can be specified for action of type " + _type + ".");
178+
SampleTypeService sampleTypeService = SampleTypeService.get();
179+
Set<String> invalidSampleTypeIds = new HashSet<>();
180+
List<Object> invalidCounts = new ArrayList<>();
181+
182+
_inputParameters.keys().forEachRemaining(id -> {
183+
try
184+
{
185+
if (sampleTypeService.getSampleType(Long.valueOf(id)) == null)
186+
invalidSampleTypeIds.add(id);
187+
}
188+
catch (NumberFormatException e)
189+
{
190+
invalidSampleTypeIds.add(id);
191+
}
192+
Object countObj = _inputParameters.get(id);
193+
if ((countObj instanceof String))
194+
try
195+
{
196+
if (Integer.parseInt((String) countObj) < 0)
197+
invalidCounts.add(countObj);
198+
}
199+
catch (NumberFormatException e)
200+
{
201+
invalidCounts.add(countObj);
202+
}
203+
else if (countObj instanceof Integer)
204+
{
205+
if (((Integer) countObj) < 0)
206+
invalidCounts.add(countObj);
207+
}
208+
else
209+
invalidCounts.add(countObj);
210+
});
211+
List<String> messages = new ArrayList<>();
212+
if (!invalidSampleTypeIds.isEmpty())
213+
messages.add(prefix + "invalid sample type IDs " + invalidSampleTypeIds + ".");
214+
if (!invalidCounts.isEmpty())
215+
messages.add(prefix + "invalid sample count values " + invalidCounts + ".");
216+
return messages;
217+
}
218+
return Collections.emptyList();
219+
}
220+
221+
@Override
222+
public boolean equals(Object o)
223+
{
224+
if (this == o) return true;
225+
if (o == null || getClass() != o.getClass()) return false;
226+
Action action = (Action) o;
227+
228+
// GitHub Issue 799: Workflow Automation: Attempting to add a sample filter on an existing template errors
229+
// Migration script generated action.name, but they are currently not used. Allow name to be changed to null or empty string.
230+
if (!java.util.Objects.equals(_name, action._name) && !StringUtils.isEmpty(action.getName()))
231+
return false;
232+
233+
return _isUpdatable == action._isUpdatable &&
234+
_ordinal == action._ordinal &&
235+
java.util.Objects.equals(_rowId, action._rowId) &&
236+
java.util.Objects.equals(_taskId, action._taskId) &&
237+
java.util.Objects.equals(_type, action._type) &&
238+
java.util.Objects.equals(
239+
_inputParameters == null ? null : _inputParameters.toString(),
240+
action._inputParameters == null ? null : action._inputParameters.toString()
241+
);
242+
}
243+
244+
public Map<String, Object> toAuditDetailMap()
245+
{
246+
Map<String, Object> map = new LinkedHashMap<>();
247+
map.put("rowId", _rowId);
248+
map.put("name", _name);
249+
map.put("ordinal", _ordinal);
250+
map.put("isUpdatable", _isUpdatable);
251+
map.put("taskId", _taskId);
252+
if (_type != null)
253+
map.put("type", _type.name());
254+
if (_inputParameters != null)
255+
map.put("inputParameters", _inputParameters.toString());
256+
return map;
257+
}
258+
259+
public abstract Task getTask();
260+
}

0 commit comments

Comments
 (0)