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 script) {
108
109 for (Entry<String, ScriptEngine> oneEntry : enginesByPrefix.entrySet()) {
110
111 String prefix = oneEntry.getKey();
112
113
114 if (script.startsWith(prefix)) {
115
116 ScriptEngine engine = oneEntry.getValue();
117 script = script.substring(prefix.length());
118
119 List<ScriptInvocationHandler> handlers = handlersByPrefix.get(oneEntry.getKey());
120
121
122 for (ScriptInvocationHandler handler : handlers) {
123 script = handler.preInvoke(script);
124 }
125
126 logger.debug("Executing script: {}", script);
127
128
129 try {
130 theValue = engine.eval(script);
131 } catch (ScriptException e) {
132 throw new RuntimeException(e);
133 }
134
135
136 Collections.reverse(handlers);
137 for (ScriptInvocationHandler handler : handlers) {
138 theValue = handler.postInvoke(theValue);
139 }
140 }
141 }
142 }
143
144 return theValue;
145 }
146
147
148
149
150
151
152
153
154
155
156 private List<ScriptInvocationHandler> getAllHandlers(ScriptableDataSetConfig config) {
157
158 List<ScriptInvocationHandler> theValue = new ArrayList<>(
159 StandardHandlerConfig.getStandardHandlersByLanguage(config.getLanguageName()));
160
161
162 theValue.addAll(config.getHandlers());
163
164 return theValue;
165 }
166 }