1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package de.gmorling.scriptabledataset;
16
17 import de.gmorling.scriptabledataset.handlers.ScriptInvocationHandler;
18 import de.gmorling.scriptabledataset.handlers.StandardHandlerConfig;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Map.Entry;
26
27 import javax.script.ScriptEngine;
28 import javax.script.ScriptEngineManager;
29 import javax.script.ScriptException;
30
31 import org.dbunit.dataset.DataSetException;
32 import org.dbunit.dataset.ITable;
33 import org.dbunit.dataset.ITableMetaData;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38
39
40 public class ScriptableTable implements ITable {
41
42
43 private final Logger logger = LoggerFactory.getLogger(ScriptableTable.class);
44
45
46 private ITable wrapped;
47
48
49 private Map<String, ScriptEngine> enginesByPrefix = new HashMap<>();
50
51
52 private Map<String, List<ScriptInvocationHandler>> handlersByPrefix = new HashMap<>();
53
54
55
56
57
58
59
60
61
62 public ScriptableTable(ITable wrapped, List<ScriptableDataSetConfig> configurations) {
63
64 this.wrapped = wrapped;
65
66 ScriptEngineManager manager = new ScriptEngineManager();
67
68
69 for (ScriptableDataSetConfig oneConfig : configurations) {
70
71 ScriptEngine engine = manager.getEngineByName(oneConfig.getLanguageName());
72
73 if (engine == null) {
74 throw new RuntimeException(
75 "No scripting engine found for language \"" + oneConfig.getLanguageName() + "\".");
76 }
77 enginesByPrefix.put(oneConfig.getPrefix(), engine);
78
79 List<ScriptInvocationHandler> handlers = getAllHandlers(oneConfig);
80
81 for (ScriptInvocationHandler oneHandler : handlers) {
82 oneHandler.setScriptEngine(engine);
83 }
84
85 handlersByPrefix.put(oneConfig.getPrefix(), handlers);
86
87 logger.info("Registered scripting engine {} for language {}.", engine, oneConfig.getLanguageName());
88 }
89 }
90
91 @Override
92 public int getRowCount() {
93 return wrapped.getRowCount();
94 }
95
96 @Override
97 public ITableMetaData getTableMetaData() {
98 return wrapped.getTableMetaData();
99 }
100
101 @Override
102 public Object getValue(int row, String column) throws DataSetException {
103
104 Object theValue = wrapped.getValue(row, column);
105
106
107 if (theValue instanceof String) {
108 String script = (String) theValue;
109
110 for (Entry<String, ScriptEngine> oneEntry : enginesByPrefix.entrySet()) {
111
112 String prefix = oneEntry.getKey();
113
114
115 if (script.startsWith(prefix)) {
116
117 ScriptEngine engine = oneEntry.getValue();
118 script = script.substring(prefix.length());
119
120 List<ScriptInvocationHandler> handlers = handlersByPrefix.get(oneEntry.getKey());
121
122
123 for (ScriptInvocationHandler handler : handlers) {
124 script = handler.preInvoke(script);
125 }
126
127 logger.debug("Executing script: {}", script);
128
129
130 try {
131 theValue = engine.eval(script);
132 } catch (ScriptException e) {
133 throw new RuntimeException(e);
134 }
135
136
137 Collections.reverse(handlers);
138 for (ScriptInvocationHandler handler : handlers) {
139 theValue = handler.postInvoke(theValue);
140 }
141 }
142 }
143 }
144
145 return theValue;
146 }
147
148
149
150
151
152
153
154
155
156
157 private List<ScriptInvocationHandler> getAllHandlers(ScriptableDataSetConfig config) {
158
159 List<ScriptInvocationHandler> theValue = new ArrayList<>(
160 StandardHandlerConfig.getStandardHandlersByLanguage(config.getLanguageName()));
161
162
163 theValue.addAll(config.getHandlers());
164
165 return theValue;
166 }
167 }