Skip to content

Commit be19df4

Browse files
authored
Migrate to new JSONObject/JSONArray (#155)
1 parent b4d64e6 commit be19df4

File tree

54 files changed

+2578
-186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2578
-186
lines changed
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
/*
2+
* Copyright (c) 2016-2019 LabKey Corporation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.labkey.api.ldk.table;
17+
18+
import org.apache.commons.lang3.StringUtils;
19+
import org.jetbrains.annotations.NotNull;
20+
import org.labkey.api.data.AbstractTableInfo;
21+
import org.labkey.api.data.ColumnInfo;
22+
import org.labkey.api.data.CompareType;
23+
import org.labkey.api.data.Container;
24+
import org.labkey.api.data.ContainerFilter;
25+
import org.labkey.api.data.SchemaTableInfo;
26+
import org.labkey.api.data.SimpleFilter;
27+
import org.labkey.api.data.Table;
28+
import org.labkey.api.data.TableSelector;
29+
import org.labkey.api.dataiterator.DataIterator;
30+
import org.labkey.api.dataiterator.DataIteratorBuilder;
31+
import org.labkey.api.dataiterator.DataIteratorContext;
32+
import org.labkey.api.dataiterator.SimpleTranslator;
33+
import org.labkey.api.query.DuplicateKeyException;
34+
import org.labkey.api.query.FieldKey;
35+
import org.labkey.api.query.InvalidKeyException;
36+
import org.labkey.api.query.QueryUpdateService;
37+
import org.labkey.api.query.QueryUpdateServiceException;
38+
import org.labkey.api.query.SimpleQueryUpdateService;
39+
import org.labkey.api.query.SimpleUserSchema;
40+
import org.labkey.api.query.UserSchema;
41+
import org.labkey.api.query.ValidationException;
42+
import org.labkey.api.security.User;
43+
44+
import java.sql.SQLException;
45+
import java.util.Arrays;
46+
import java.util.Collections;
47+
import java.util.HashMap;
48+
import java.util.HashSet;
49+
import java.util.List;
50+
import java.util.Map;
51+
import java.util.Set;
52+
import java.util.concurrent.Callable;
53+
54+
/**
55+
* User: bimber
56+
* Date: 4/2/13
57+
* Time: 2:54 PM
58+
*/
59+
abstract public class AbstractDataDefinedTable extends CustomPermissionsTable
60+
{
61+
protected String _pk;
62+
63+
protected String _filterColumn;
64+
protected String _filterValue;
65+
protected String _valueColumn;
66+
67+
public AbstractDataDefinedTable(UserSchema schema, SchemaTableInfo table, ContainerFilter cf, String filterColumn, String valueColumn, String tableName, String filterValue)
68+
{
69+
super(schema, table, cf);
70+
_filterColumn = filterColumn;
71+
_filterValue = filterValue;
72+
_valueColumn = valueColumn;
73+
74+
setName(tableName);
75+
setTitle(tableName);
76+
}
77+
78+
@Override
79+
public CustomPermissionsTable init()
80+
{
81+
super.init();
82+
83+
ColumnInfo col = getRealTable().getColumn(_filterColumn);
84+
addCondition(col, _filterValue); //enforce only showing rows from this category
85+
86+
List<String> pks = getRealTable().getPkColumnNames();
87+
assert pks.size() > 0;
88+
_pk = pks.get(0);
89+
90+
var valueCol = getMutableColumn(_valueColumn);
91+
assert valueCol != null;
92+
93+
valueCol.setKeyField(true);
94+
valueCol.setNullable(false);
95+
getMutableColumn(_pk).setKeyField(false);
96+
97+
ColumnInfo filterCol = getColumn(_filterColumn);
98+
assert filterCol != null;
99+
100+
removeColumn(filterCol);
101+
102+
return this;
103+
}
104+
105+
@Override
106+
protected void addTableURLs()
107+
{
108+
setInsertURL(AbstractTableInfo.LINK_DISABLER);
109+
setUpdateURL(AbstractTableInfo.LINK_DISABLER);
110+
setDeleteURL(AbstractTableInfo.LINK_DISABLER);
111+
setImportURL(AbstractTableInfo.LINK_DISABLER);
112+
}
113+
114+
/**
115+
* @return A set of the allowable
116+
*/
117+
protected Set<String> getDistinctValues()
118+
{
119+
SimpleFilter filter = new SimpleFilter(FieldKey.fromString(_filterColumn), _filterValue, CompareType.EQUAL);
120+
filter.addCondition(FieldKey.fromParts("Container"), getContainer().getEntityId().toString());
121+
TableSelector ts = new TableSelector(_rootTable, Collections.singleton(_valueColumn), filter, null);
122+
String[] existing = ts.getArray(String.class);
123+
124+
return new HashSet<>(Arrays.asList(existing));
125+
}
126+
127+
@Override
128+
public QueryUpdateService getUpdateService()
129+
{
130+
return new UpdateService(this);
131+
}
132+
133+
protected class UpdateService extends SimpleQueryUpdateService
134+
{
135+
private final ValuesManager _vm;
136+
137+
public UpdateService(SimpleUserSchema.SimpleTable ti)
138+
{
139+
super(ti, ti.getRealTable());
140+
141+
_vm = new ValuesManager();
142+
}
143+
144+
@Override
145+
protected Map<String, Object> getRow(User user, Container container, Map<String, Object> keys) throws InvalidKeyException, QueryUpdateServiceException, SQLException
146+
{
147+
if (!keys.containsKey(_pk) || keys.get(_pk) == null)
148+
{
149+
SimpleFilter filter = new SimpleFilter(FieldKey.fromString(_valueColumn), keys.get(_valueColumn), CompareType.EQUAL);
150+
TableSelector ts = new TableSelector(getQueryTable(), Collections.singleton(_pk), filter, null);
151+
Object[] results = ts.getArray(Object.class);
152+
if (results.length == 0)
153+
throw new InvalidKeyException("Existing row not found for value: " + keys.get(_valueColumn));
154+
else if (results.length > 1)
155+
throw new InvalidKeyException("More than one existing row found for value: " + keys.get(_valueColumn));
156+
157+
keys.put(_pk, results[0]);
158+
}
159+
160+
return super.getRow(user, container, keys);
161+
}
162+
163+
//NOTE: this code should never be called, now that we have migrated to DIB
164+
@Override
165+
protected Map<String, Object> insertRow(User user, Container container, Map<String, Object> row) throws DuplicateKeyException, ValidationException, QueryUpdateServiceException, SQLException
166+
{
167+
row.put(_filterColumn, _filterValue);
168+
169+
String value = (String)row.get(_valueColumn);
170+
if (value != null && _vm.testIfRowExists(value))
171+
throw new ValidationException("There is already a record in the table " + getName() + " where " + _valueColumn + " equals " + value);
172+
173+
return super.insertRow(user, container, row);
174+
}
175+
176+
@Override
177+
protected Map<String, Object> updateRow(User user, Container container, Map<String, Object> row, @NotNull Map<String, Object> oldRow) throws InvalidKeyException, ValidationException, QueryUpdateServiceException, SQLException
178+
{
179+
String oldValue = (String)oldRow.get(_valueColumn);
180+
String newValue = (String)row.get(_valueColumn);
181+
182+
if (newValue != null && !oldValue.equals(newValue) && _vm.testIfRowExists(newValue))
183+
throw new ValidationException("There is already a record in the table " + getName() + " where " + _valueColumn + " equals " + newValue);
184+
185+
if (!oldValue.equals(newValue))
186+
_vm.uncacheValue(oldValue);
187+
188+
row.put(_filterColumn, _filterValue);
189+
return super.updateRow(user, container, row, oldRow);
190+
}
191+
192+
@Override
193+
protected int truncateRows(User user, Container container)
194+
{
195+
SimpleFilter filter = new SimpleFilter(FieldKey.fromString(_filterColumn), _filterValue, CompareType.EQUAL);
196+
return Table.delete(getDbTable(), filter);
197+
}
198+
199+
}
200+
201+
protected class ValuesManager
202+
{
203+
private final Set<String> _distinctValues;
204+
205+
public ValuesManager()
206+
{
207+
_distinctValues = getDistinctValues();
208+
}
209+
210+
public void uncacheValue(String value)
211+
{
212+
_distinctValues.remove(value);
213+
}
214+
215+
public boolean testIfRowExists(String value)
216+
{
217+
boolean ret = _distinctValues.contains(value);
218+
219+
if (!_distinctValues.contains(value))
220+
_distinctValues.add(value);
221+
222+
return ret;
223+
}
224+
}
225+
226+
@Override
227+
public DataIteratorBuilder persistRows(DataIteratorBuilder data, DataIteratorContext context)
228+
{
229+
data = new _DataIteratorBuilder(data, context);
230+
return super.persistRows(data, context);
231+
}
232+
233+
protected class _DataIteratorBuilder implements DataIteratorBuilder
234+
{
235+
final DataIteratorBuilder _in;
236+
237+
public _DataIteratorBuilder(@NotNull DataIteratorBuilder in, DataIteratorContext unused)
238+
{
239+
_in = in;
240+
}
241+
242+
public _DataIteratorBuilder(@NotNull DataIteratorBuilder in)
243+
{
244+
_in = in;
245+
}
246+
247+
@Override
248+
public DataIterator getDataIterator(DataIteratorContext context)
249+
{
250+
DataIterator input = _in.getDataIterator(context);
251+
if (null == input)
252+
return null; // Can happen if context has errors
253+
254+
final SimpleTranslator it = new SimpleTranslator(input, context);
255+
configureTranslator(input, it, context);
256+
257+
return it;
258+
}
259+
260+
protected void configureTranslator(DataIterator input, final SimpleTranslator it, final DataIteratorContext context)
261+
{
262+
final Map<String, Integer> inputColMap = new HashMap<>();
263+
for (int idx = 1; idx <= input.getColumnCount(); idx++)
264+
{
265+
ColumnInfo col = input.getColumnInfo(idx);
266+
if (StringUtils.equalsIgnoreCase(_filterColumn, col.getName()))
267+
{
268+
inputColMap.put(_filterColumn, idx);
269+
continue;
270+
}
271+
272+
if (StringUtils.equalsIgnoreCase(_valueColumn, col.getName()))
273+
{
274+
inputColMap.put(_valueColumn, idx);
275+
continue;
276+
}
277+
278+
it.addColumn(idx);
279+
}
280+
281+
//always set the value for the filterCol
282+
ColumnInfo incrementCol = getRealTable().getColumn(_filterColumn);
283+
it.addColumn(incrementCol, new Callable()
284+
{
285+
@Override
286+
public Object call()
287+
{
288+
return _filterValue;
289+
}
290+
});
291+
292+
//enforce uniqueness for values
293+
final ValuesManager vm = new ValuesManager();
294+
ColumnInfo valueCol = getRealTable().getColumn(_valueColumn);
295+
it.addColumn(valueCol, new Callable()
296+
{
297+
@Override
298+
public Object call()
299+
{
300+
String value = (String)it.getInputColumnValue(inputColMap.get(_valueColumn));
301+
if (value == null)
302+
{
303+
context.getErrors().addRowError(new ValidationException("Missing value for column: " + _valueColumn));
304+
}
305+
306+
if (vm.testIfRowExists(value))
307+
{
308+
context.getErrors().addRowError(new ValidationException("There is already a record in the table " + getName() + " where " + _valueColumn + " equals " + value));
309+
}
310+
311+
return value;
312+
}
313+
});
314+
}
315+
}
316+
}

0 commit comments

Comments
 (0)