Skip to content

Commit aea2aca

Browse files
committed
ScriptInfo: use SJEP for more robust attr parsing
SJEP version 3.0.0 includes improved support for "group" operators, including parentheses, square brackets and curly braces. And its default expression evaluator aggregates groups into List objects, which can be easily consumed by the ScriptInfo attribute parser. Closes #156.
1 parent dfed65f commit aea2aca

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,16 @@
116116

117117
<properties>
118118
<scijava.jvm.test.version>1.8</scijava.jvm.test.version>
119+
<scijava-expression-parser.version>3.0.0</scijava-expression-parser.version>
119120
</properties>
120121

121122
<dependencies>
123+
<!-- SciJava dependencies -->
124+
<dependency>
125+
<groupId>org.scijava</groupId>
126+
<artifactId>scijava-expression-parser</artifactId>
127+
</dependency>
128+
122129
<!-- Third-party dependencies -->
123130
<dependency>
124131
<groupId>com.googlecode.gentyref</groupId>

src/main/java/org/scijava/script/ScriptInfo.java

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@
3838
import java.io.Reader;
3939
import java.io.StringReader;
4040
import java.text.SimpleDateFormat;
41+
import java.util.Arrays;
42+
import java.util.Collections;
4143
import java.util.Date;
4244
import java.util.HashMap;
45+
import java.util.List;
4346
import java.util.Map;
4447

4548
import javax.script.ScriptException;
@@ -56,6 +59,8 @@
5659
import org.scijava.module.DefaultMutableModuleItem;
5760
import org.scijava.module.ModuleException;
5861
import org.scijava.plugin.Parameter;
62+
import org.scijava.sjep.Variable;
63+
import org.scijava.sjep.eval.DefaultEvaluator;
5964
import org.scijava.util.DigestUtils;
6065
import org.scijava.util.FileUtils;
6166

@@ -337,11 +342,11 @@ private void parseParam(final String param) throws ScriptException {
337342
if (rParen < lParen) {
338343
throw new ScriptException("Invalid parameter: " + param);
339344
}
340-
if (lParen < 0) parseParam(param, parseAttrs(""));
345+
if (lParen < 0) parseParam(param, parseAttrs("()"));
341346
else {
342347
final String cutParam =
343348
param.substring(0, lParen) + param.substring(rParen + 1);
344-
final String attrs = param.substring(lParen + 1, rParen);
349+
final String attrs = param.substring(lParen, rParen + 1);
345350
parseParam(cutParam, parseAttrs(attrs));
346351
}
347352
}
@@ -374,20 +379,39 @@ private void parseParam(final String param,
374379
private HashMap<String, Object> parseAttrs(final String attrs)
375380
throws ScriptException
376381
{
377-
// TODO: We probably want to use a real CSV parser.
378-
final HashMap<String, Object> attrsMap = new HashMap<String, Object>();
379-
for (final String token : attrs.split(",")) {
380-
if (token.isEmpty()) continue;
381-
final int equals = token.indexOf("=");
382-
if (equals < 0) throw new ScriptException("Invalid attribute: " + token);
383-
final String key = token.substring(0, equals).trim();
384-
String value = token.substring(equals + 1).trim();
385-
if (value.startsWith("\"") && value.endsWith("\"")) {
386-
value = value.substring(1, value.length() - 1);
382+
// NB: Parse the attributes using the SciJava Expression Parser.
383+
final DefaultEvaluator e = new DefaultEvaluator();
384+
try {
385+
final Object result = e.evaluate(attrs);
386+
if (result == null) throw new ScriptException("Unparseable attributes");
387+
final List<?> list;
388+
if (result instanceof List) list = (List<?>) result;
389+
else if (result instanceof Variable) {
390+
list = Collections.singletonList(result);
391+
}
392+
else {
393+
throw new ScriptException("Unexpected attributes type: " +
394+
result.getClass().getName());
395+
}
396+
397+
final HashMap<String, Object> attrsMap = new HashMap<String, Object>();
398+
for (final Object o : list) {
399+
if (o instanceof Variable) {
400+
final Variable v = (Variable) o;
401+
attrsMap.put(v.getToken(), e.value(v));
402+
}
403+
else {
404+
throw new ScriptException("Invalid attribute: " + o);
405+
}
387406
}
388-
attrsMap.put(key, value);
407+
return attrsMap;
408+
}
409+
catch (final IllegalArgumentException exc) {
410+
final ScriptException se = new ScriptException(
411+
"Error parsing attributes");
412+
se.initCause(exc);
413+
throw se;
389414
}
390-
return attrsMap;
391415
}
392416

393417
private boolean isIOType(final String token) {

0 commit comments

Comments
 (0)