1 /*
2 * scriptable-dataset (https://github.com/hazendaz/scriptable-dataset)
3 *
4 * Copyright 2011-2024 Hazendaz.
5 *
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of The Apache Software License,
8 * Version 2.0 which accompanies this distribution, and is available at
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Contributors:
12 * Gunnar Morling
13 * Hazendaz (Jeremy Landis).
14 */
15 package de.gmorling.scriptabledataset;
16
17 import java.util.Arrays;
18 import java.util.List;
19 import java.util.Objects;
20
21 import org.apache.commons.lang3.Validate;
22 import org.dbunit.dataset.AbstractDataSet;
23 import org.dbunit.dataset.DataSetException;
24 import org.dbunit.dataset.IDataSet;
25 import org.dbunit.dataset.ITableIterator;
26
27 /**
28 * An implementation of a <a href="http://www.dbunit.org/">DBUnit</a> <code>IDataSet</code>, that allows the use of
29 * script expressions in its fields. In order to use a certain scripting language in a scriptable data set, a
30 * <a href="http://jcp.org/en/jsr/detail?id=223">JSR 223</a> ("Scripting for the Java<sup>TM</sup> Platform")
31 * compatible script engine has to exist for that language.
32 * <p>
33 * Using the <a href="http://jruby.org/">JRuby</a> engine e.g., a scriptable data set file could look like this:
34 *
35 * <pre>
36 * <dataset>
37 * <location num="jruby:12/2" addr="jruby:'Webster Street'.reverse" date="jruby:DateTime::now() - 14"/>
38 * </dataset>
39 * </pre>
40 *
41 * A ScriptableDataSet can be created as follows:
42 *
43 * <pre>
44 * IDataSet wrapped = ...;
45 *
46 * List<ScriptInvocationHandler> handlers = new ArrayList<Class<? extends ScriptInvocationHandler>>();
47 * handlers.add(new JRubyImportAddingInvocationHandler());
48 *
49 * IDataSet scriptableDS = new ScriptableDataSet(
50 * wrapped, new ScriptableDataSetConfig("jruby", "jruby:", handlers));
51 * </pre>
52 *
53 * where
54 * <ul>
55 * <li><b>jruby</b> is the name of a scripting language as understood by {@link javax.script.ScriptEngineManager}</li>
56 * <li><b>jruby:</b> is a prefix, that shall precede fields in that scripting language</li>
57 * <li><b>handlers</b> is an optional list of {@link de.gmorling.scriptabledataset.handlers.ScriptInvocationHandler} s,
58 * that can be used to pre-process scripts (e.g. to add common imports) and post-process scripts (e.g. to convert
59 * results into data types understood by DBUnit).</li>
60 * </ul>
61 */
62 public class ScriptableDataSet extends AbstractDataSet {
63
64 /** The wrapped. */
65 private IDataSet wrapped;
66
67 /** The configurations. */
68 private List<ScriptableDataSetConfig> configurations;
69
70 /**
71 * Creates a new ScriptableDataSet.
72 *
73 * @param wrapped
74 * Another data set to be wrapped by this scriptable data set. Must not be null.
75 * @param configurations
76 * At least one scriptable data set configuration.
77 */
78 public ScriptableDataSet(IDataSet wrapped, ScriptableDataSetConfig... configurations) {
79
80 Objects.requireNonNull(wrapped);
81
82 Objects.requireNonNull(configurations);
83 Validate.noNullElements(configurations);
84 Validate.notEmpty(configurations);
85
86 this.wrapped = wrapped;
87 this.configurations = Arrays.asList(configurations);
88 }
89
90 @Override
91 protected ITableIterator createIterator(boolean reversed) throws DataSetException {
92 return new ScriptableIterator(reversed ? wrapped.reverseIterator() : wrapped.iterator(), configurations);
93 }
94
95 }