Skip to content

Commit 057f8d5

Browse files
Restore class, add comment about usage
1 parent 57a1708 commit 057f8d5

1 file changed

Lines changed: 237 additions & 0 deletions

File tree

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
package org.labkey.ldk.query;
2+
3+
import org.apache.commons.lang3.StringUtils;
4+
import org.apache.logging.log4j.Logger;
5+
import org.apache.logging.log4j.LogManager;
6+
import org.jetbrains.annotations.Nullable;
7+
import org.labkey.api.collections.CaseInsensitiveHashMap;
8+
import org.labkey.api.data.ColumnInfo;
9+
import org.labkey.api.data.Container;
10+
import org.labkey.api.data.ContainerManager;
11+
import org.labkey.api.data.SimpleFilter;
12+
import org.labkey.api.data.TableInfo;
13+
import org.labkey.api.data.TableSelector;
14+
import org.labkey.api.query.FieldKey;
15+
import org.labkey.api.query.QueryService;
16+
import org.labkey.api.query.QueryUpdateService;
17+
import org.labkey.api.query.UserSchema;
18+
import org.labkey.api.security.User;
19+
import org.labkey.api.security.UserManager;
20+
import org.labkey.api.util.MemTracker;
21+
import org.labkey.api.util.PageFlowUtil;
22+
import org.springframework.dao.PessimisticLockingFailureException;
23+
24+
import java.sql.SQLException;
25+
import java.util.ArrayList;
26+
import java.util.Collection;
27+
import java.util.HashMap;
28+
import java.util.HashSet;
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.Set;
32+
33+
/**
34+
* Referenced by many trigger scripts.
35+
*/
36+
@SuppressWarnings("unused")
37+
public class LookupValidationHelper
38+
{
39+
private Container _container;
40+
private final User _user;
41+
private final TableInfo _table;
42+
private static final Logger _log = LogManager.getLogger(LookupValidationHelper.class);
43+
44+
private final Map<String, UserSchema> _userSchemaMap = new HashMap<>();
45+
private final Map<String, Map<String, String>> _allowableValueMap = new HashMap<>();
46+
47+
private LookupValidationHelper(String containerId, int userId, String schemaName, String queryName)
48+
{
49+
_container = ContainerManager.getForId(containerId);
50+
if (_container == null)
51+
throw new IllegalArgumentException("Unknown container: " + containerId);
52+
53+
_container = _container.isWorkbook() ? _container.getParent() : _container;
54+
55+
_user = UserManager.getUser(userId);
56+
if (_user == null)
57+
throw new IllegalArgumentException("Unknown user: " + userId);
58+
59+
UserSchema us = getUserSchema(schemaName);
60+
if (us == null)
61+
throw new IllegalArgumentException("Unknown schema: " + schemaName);
62+
63+
_table = us.getTable(queryName);
64+
if (_table == null)
65+
throw new IllegalArgumentException("Unknown table: " + schemaName + "." + queryName);
66+
67+
MemTracker.getInstance().put(this);
68+
}
69+
70+
public static LookupValidationHelper create(String containerId, int userId, String schemaName, String queryName)
71+
{
72+
return new LookupValidationHelper(containerId, userId, schemaName, queryName);
73+
}
74+
75+
private UserSchema getUserSchema(String name)
76+
{
77+
if (_userSchemaMap.containsKey(name))
78+
return _userSchemaMap.get(name);
79+
80+
UserSchema us = QueryService.get().getUserSchema(_user, _container, name);
81+
_userSchemaMap.put(name, us);
82+
83+
return us;
84+
}
85+
86+
/**
87+
* Provides a case-normalized lookup of the passed value. Will return null is the passed value is not found in allowable values
88+
*/
89+
public Object getLookupValue(String value, String fieldName)
90+
{
91+
value = StringUtils.trimToNull(value);
92+
if (value == null)
93+
return value;
94+
95+
ColumnInfo ci = _table.getColumn(FieldKey.fromString(fieldName));
96+
if (ci == null)
97+
throw new IllegalArgumentException("Unknown column: " + fieldName);
98+
99+
Map<String, String> allowable = getAllowableValues(ci);
100+
if (allowable == null)
101+
return null;
102+
103+
return allowable.get(value);
104+
}
105+
106+
public String validateRequiredField(String fieldName, Object value)
107+
{
108+
ColumnInfo ci = _table.getColumn(FieldKey.fromString(fieldName));
109+
if (ci == null)
110+
return null;
111+
112+
//NOTE: some required fields are auto-completed, like LSID or rowIds, so skip them here
113+
if (!ci.isNullable() && ci.isUserEditable() && (value == null || StringUtils.isEmpty(String.valueOf(value))))
114+
return "The field: " + ci.getLabel() + " is required";
115+
116+
return null;
117+
}
118+
119+
private Map<String, String> getAllowableValues(ColumnInfo ci)
120+
{
121+
String name = ci.getName();
122+
if (_allowableValueMap.containsKey(name))
123+
return _allowableValueMap.get(name);
124+
125+
TableInfo fkTableInfo = ci.getFkTableInfo();
126+
if (fkTableInfo == null)
127+
return null;
128+
129+
ColumnInfo targetCol = fkTableInfo.getColumn(ci.getFk().getLookupColumnName());
130+
if (targetCol == null)
131+
return null;
132+
133+
try
134+
{
135+
TableSelector ts = new TableSelector(fkTableInfo, PageFlowUtil.set(targetCol), null, null);
136+
String[] vals = ts.getArray(String.class);
137+
if (vals != null)
138+
{
139+
Map<String, String> map = new CaseInsensitiveHashMap<>();
140+
for (String val : vals)
141+
{
142+
map.put(val, val);
143+
}
144+
_allowableValueMap.put(name, map);
145+
}
146+
else
147+
_allowableValueMap.put(name, null);
148+
149+
return _allowableValueMap.get(name);
150+
}
151+
catch (PessimisticLockingFailureException e)
152+
{
153+
_log.error("PessimisticLockingFailureException in LookupValidationHelper for table: " + _table.getPublicSchemaName() + "." + _table.getPublicName(), e);
154+
throw e;
155+
}
156+
}
157+
158+
public void cascadeUpdate(String targetSchema, String targetTable, String targetField, Object newVal, Object oldVal) throws Exception
159+
{
160+
UserSchema us = QueryService.get().getUserSchema(_user, _container, targetSchema);
161+
if (us == null)
162+
throw new IllegalArgumentException("Unknown schema: " + targetSchema);
163+
164+
TableInfo ti = us.getTable(targetTable);
165+
if (ti == null)
166+
throw new IllegalArgumentException("Unknown table: " + targetTable);
167+
168+
if (ti.getColumn(targetField) == null)
169+
throw new IllegalArgumentException("Unknown column: " + targetField + " in table: " + targetTable);
170+
171+
if (ti.getPkColumnNames().size() != 1)
172+
throw new IllegalArgumentException("Cascade update only supported for columns with single PKs. Problem table was : " + targetTable);
173+
174+
Set<String> pkCols = new HashSet<>(ti.getPkColumnNames());
175+
176+
TableSelector ts = new TableSelector(ti, pkCols, new SimpleFilter(FieldKey.fromString(targetField), oldVal), null);
177+
Collection<Map<String, Object>> pks = ts.getMapCollection();
178+
179+
List<Map<String, Object>> toUpdate = new ArrayList<>();
180+
List<Map<String, Object>> oldPKs = new ArrayList<>();
181+
for (Map<String, Object> oldPk : pks)
182+
{
183+
CaseInsensitiveHashMap<Object> map = new CaseInsensitiveHashMap<>();
184+
map.put(targetField, newVal);
185+
map.putAll(oldPk);
186+
toUpdate.add(map);
187+
188+
oldPKs.add(oldPk);
189+
}
190+
191+
QueryUpdateService qus = ti.getUpdateService();
192+
qus.updateRows(_user, _container, toUpdate, oldPKs, null, new HashMap<>());
193+
}
194+
195+
public boolean verifyNotUsed(String targetSchema, String targetTable, String targetField, Object val, String triggerScriptName) throws SQLException
196+
{
197+
return verifyNotUsed(targetSchema, targetTable, targetField, val, null, triggerScriptName);
198+
}
199+
200+
public boolean verifyNotUsed(String targetSchema, String targetTable, String targetField, Object val, @Nullable String containerPath, String triggerScriptName)
201+
{
202+
Container c = _container;
203+
if (containerPath != null)
204+
{
205+
c = ContainerManager.getForPath(containerPath);
206+
if (c == null)
207+
{
208+
_log.error("Error running '" + triggerScriptName + "' trigger script. Container '{}' not found", containerPath);
209+
return false;
210+
}
211+
}
212+
213+
UserSchema us = QueryService.get().getUserSchema(_user, c, targetSchema);
214+
if (us == null)
215+
{
216+
_log.error("Error running '" + triggerScriptName + "' trigger script. Schema '{}' not found in container '{}'", targetSchema, c.getName());
217+
return false;
218+
}
219+
220+
TableInfo ti = us.getTable(targetTable);
221+
if (ti == null)
222+
{
223+
_log.error("Error running '" + triggerScriptName + "' trigger script. Table '{}' not found in container '{}'", targetTable, c.getName());
224+
return false;
225+
}
226+
227+
if (ti.getColumn(targetField) == null)
228+
{
229+
_log.error("Error running '" + triggerScriptName + "' trigger script. Column '{}' not found in table '{}'", targetField, targetTable);
230+
return false;
231+
}
232+
233+
TableSelector ts = new TableSelector(ti, new SimpleFilter(FieldKey.fromString(targetField), val), null);
234+
235+
return ts.exists();
236+
}
237+
}

0 commit comments

Comments
 (0)