View Javadoc
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> (&quot;Scripting for the Java<sup>TM</sup> Platform&quot;)
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   * &lt;dataset&gt;
37   *     &lt;location num=&quot;jruby:12/2&quot; addr=&quot;jruby:'Webster Street'.reverse&quot; date=&quot;jruby:DateTime::now() - 14&quot;/&gt;
38   * &lt;/dataset&gt;
39   * </pre>
40   *
41   * A ScriptableDataSet can be created as follows:
42   *
43   * <pre>
44   * IDataSet wrapped = ...;
45   *
46   * List&lt;ScriptInvocationHandler&gt; handlers = new ArrayList&lt;Class&lt;? extends ScriptInvocationHandler&gt;&gt;();
47   * handlers.add(new JRubyImportAddingInvocationHandler());
48   *
49   * IDataSet scriptableDS = new ScriptableDataSet(
50   *      wrapped, new ScriptableDataSetConfig(&quot;jruby&quot;, &quot;jruby:&quot;, 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  }