View Javadoc

1   //$Id: DbDataRestorer.java 282 2007-07-19 22:46:27Z jg_hamburg $
2   /********************************************************************************
3    * DDTUnit, a Datadriven Approach to Unit- and Moduletesting
4    * Copyright (c) 2004, Joerg and Kai Gellien
5    * All rights reserved.
6    *
7    * The Software is provided under the terms of the Common Public License 1.0
8    * as provided with the distribution of DDTUnit in the file cpl-v10.html.
9    * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   *     + Redistributions of source code must retain the above copyright
14   *       notice, this list of conditions and the following disclaimer.
15   *
16   *     + Redistributions in binary form must reproduce the above
17   *       copyright notice, this list of conditions and the following
18   *       disclaimer in the documentation and/or other materials provided
19   *       with the distribution.
20   *
21   *     + Neither the name of the authors or DDTUnit, nor the
22   *       names of its contributors may be used to endorse or promote
23   *       products derived from this software without specific prior
24   *       written permission.
25   *
26   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
30   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   ********************************************************************************/
38  package junitx.ddtunit.data.db;
39  
40  import java.sql.Connection;
41  import java.sql.DriverManager;
42  import java.sql.PreparedStatement;
43  import java.sql.ResultSet;
44  import java.sql.SQLException;
45  import java.util.Properties;
46  import java.util.regex.Matcher;
47  import java.util.regex.Pattern;
48  
49  import junitx.ddtunit.data.DDTTestDataException;
50  import junitx.ddtunit.data.ExceptionAsserter;
51  import junitx.ddtunit.data.IDataSetSerializer;
52  import junitx.ddtunit.data.ObjectAsserter;
53  import junitx.ddtunit.data.TestClusterDataSet;
54  import junitx.ddtunit.data.TestDataSet;
55  import junitx.ddtunit.data.TestGroupDataSet;
56  import junitx.ddtunit.data.TypedObject;
57  import junitx.ddtunit.data.processing.IParser;
58  import junitx.ddtunit.data.processing.parser.ParserImpl;
59  
60  public class DbDataRestorer implements IDataSetSerializer {
61      private static final String LF = System.getProperty("line.separator");
62  
63      private IParser parser;
64  
65      public DbDataRestorer() {
66          this.parser = new ParserImpl();
67      }
68  
69      public TestClusterDataSet restore(String resource, String clusterId) {
70          TestClusterDataSet clusterDataSet = null;
71          Connection connect = createConnection();
72          try {
73              String selectData = "select clusterid, groupid, testid, ogroup"
74                      + ", otype, id, class_type, action, xml from TESTDATA_VIEW "
75                      + "where clusterid=? ";
76              PreparedStatement dbData = connect.prepareStatement(selectData);
77              dbData.setString(1, clusterId);
78              ResultSet resultSet = dbData.executeQuery();
79              clusterDataSet = new TestClusterDataSet(clusterId, null);
80              String oldGroupId = "<<<OldGroupId>>>";
81              String oldTestId = "<<<OldTestId>>>";
82              TestGroupDataSet groupDataSet = null;
83              TestDataSet testDataSet = null;
84              while (resultSet.next()) {
85                  String groupId = resultSet.getString("groupid");
86                  String testId = resultSet.getString("testid");
87                  String oType = resultSet.getString("otype");
88  
89                  String id = resultSet.getString("id");
90                  String type = resultSet.getString("class_type");
91                  String action = resultSet.getString("action");
92                  String xml = resultSet.getString("xml");
93                  if (!oldGroupId.equals(groupId)) {
94                      // on groupid change store old structure and create new
95                      if (groupDataSet != null) {
96                          // every group change adds up in a test change as well
97                          if (testDataSet != null) {
98                              groupDataSet.put(oldTestId, testDataSet);
99                          }
100                         clusterDataSet.put(oldGroupId, groupDataSet);
101                     }
102                     oldGroupId = groupId;
103                     groupDataSet = new TestGroupDataSet(groupId, clusterDataSet);
104                     oldTestId = testId;
105                     testDataSet = new TestDataSet(testId, groupDataSet);
106                     addParsedObject(testDataSet, oType, id, type, action, xml);
107                 } else {
108                     if (!oldTestId.equals(testId)) {
109                         // on testid change store dataset in groupDataSet and
110                         // create new
111                         if (testDataSet != null) {
112                             groupDataSet.put(oldTestId, testDataSet);
113                         }
114                         oldTestId = testId;
115                         testDataSet = new TestDataSet(testId, groupDataSet);
116                     }
117                     addParsedObject(testDataSet, oType, id, type, action, xml);
118                 }
119             }
120             // do not forget the last open entry in the dataset
121             if (testDataSet != null) {
122                 groupDataSet.put(oldTestId, testDataSet);
123                 clusterDataSet.put(oldGroupId, groupDataSet);
124             }
125         } catch (SQLException ex) {
126             throw new DDTTestDataException("Could not access db test data", ex);
127         } finally {
128             if (connect != null) {
129                 try {
130                     connect.close();
131                 } catch (SQLException ex) {
132                     // ignore exception
133                 }
134             }
135         }
136         return clusterDataSet;
137     }
138 
139     /**
140      * Create xml testdata resource for specified clusterId.
141      * 
142      * @param clusterId to create xml resource for
143      * @return StringBuffer representation of xml resource
144      */
145     public StringBuffer createXml(String clusterId) {
146         StringBuffer sb = new StringBuffer();
147         sb
148             .append("<?xml version=\"1.0\" ?>" + LF)
149             .append(
150                 "<ddtunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
151                         + LF)
152             .append(
153                 "  xsi:noNamespaceSchemaLocation=\"http://ddtunit.sourceforge.net/ddtunit.xsd\">"
154                         + LF).append("  <cluster id=\"").append(clusterId)
155             .append("\">" + LF);
156 
157         Connection connect = createConnection();
158         try {
159             String selectData = "select clusterid, groupid, testid, ogroup"
160                     + ", otype, id, class_type, action, xml from TESTDATA_VIEW "
161                     + "where clusterid=? ";
162             PreparedStatement dbData = connect.prepareStatement(selectData);
163             dbData.setString(1, clusterId);
164             ResultSet resultSet = dbData.executeQuery();
165             String oldGroupId = "<<<OldGroupId>>>";
166             String oldTestId = "<<<OldTestId>>>";
167             String oldOGroup = "<<<OldOGroup>>>";
168             boolean startGroups = true;
169             boolean startTests = true;
170             boolean startOGroups = true;
171             while (resultSet.next()) {
172                 String groupId = resultSet.getString("groupid");
173                 String testId = resultSet.getString("testid");
174                 String oType = resultSet.getString("otype");
175                 String oGroup = resultSet.getString("ogroup");
176 
177                 String id = resultSet.getString("id");
178                 String type = resultSet.getString("class_type");
179                 String action = resultSet.getString("action");
180                 String xml = resultSet.getString("xml");
181                 // ----------------------------------------------------
182                 Pattern idPattern = Pattern.compile("id=\"\\w*\"");
183                 Matcher idMatcher = idPattern.matcher(xml);
184                 String replacement = idMatcher
185                     .replaceFirst("id=\"" + id + "\"");
186                 if ("noaction".equals(action)) {
187                     replacement = replacement.replaceFirst("<obj", "<" + oType);
188                 } else {
189                     replacement = replacement.replaceFirst("<obj", "<" + oType
190                             + " action=\"" + action + "\"");
191                 }
192                 // ----------------------------------------------------
193                 replacement = replacement.replaceFirst("obj>", oType + ">");
194                 if (!oldGroupId.equals(groupId)) {
195                     // on groupid change close old structure and open new
196                     if (!startGroups) {
197                         startGroups = false;
198                         sb.append("        </").append(oldOGroup).append(
199                             ">" + LF);
200                         sb.append("      </test>" + LF);
201                         sb.append("    </group>" + LF);
202                     }
203                     sb.append("    <group id=\"").append(groupId).append(
204                         "\">" + LF);
205                     startGroups = false;
206                     oldGroupId = groupId;
207                 }
208                 if (!oldTestId.equals(testId)) {
209                     // on testid change store dataset in groupDataSet and
210                     // create new
211                     if (!startTests) {
212                         startTests = false;
213                         sb.append("        </").append(oldOGroup).append(
214                             ">" + LF);
215                         sb.append("      </test>" + LF);
216                     }
217                     oldTestId = testId;
218                     sb.append("      <test id=\"").append(testId).append(
219                         "\">" + LF);
220                     startTests = false;
221                     startOGroups = true;
222                 }
223                 if (!oldOGroup.equals(oGroup)) {
224                     if (!startOGroups) {
225                         sb.append("        </").append(oldOGroup).append(
226                             ">" + LF);
227                         startOGroups = false;
228                     }
229                     sb.append("        <").append(oGroup).append(">" + LF);
230                     startOGroups = false;
231                     oldOGroup = oGroup;
232                 }
233                 sb.append("          " + replacement + LF);
234             }
235             sb.append("        </").append(oldOGroup).append(">" + LF);
236             sb.append("      </test>" + LF);
237             sb.append("    </group>" + LF);
238             sb.append("  </cluster>" + LF);
239         } catch (SQLException ex) {
240             throw new DDTTestDataException("Could not access db test data", ex);
241         } finally {
242             if (connect != null) {
243                 try {
244                     connect.close();
245                 } catch (SQLException ex) {
246                     // ignore exception
247                 }
248             }
249         }
250         return sb;
251     }
252 
253     private Connection createConnection() {
254         Properties dbProp = new Properties();
255         dbProp.put("userid", "sa");
256         dbProp.put("password", "");
257 
258         try {
259             Class.forName("org.hsqldb.jdbcDriver");
260             Connection connect = DriverManager.getConnection(
261                 "jdbc:hsqldb:hsql://localhost/ddt", dbProp);
262             return connect;
263         } catch (ClassNotFoundException ex) {
264             throw new DDTTestDataException(
265                     "Could not create connection to db repository", ex);
266         } catch (SQLException ex) {
267             throw new DDTTestDataException(
268                     "Could not create connection to db repository", ex);
269         }
270     }
271 
272     /**
273      * Retrieve single object instance from database.
274      * 
275      * @param id used to identify object
276      * @param type of object to retrieve
277      * @return TypedObject created by repository
278      */
279     public TypedObject getObject(String id, String type) {
280         TypedObject tObj = null;
281         Connection connect = createConnection();
282         try {
283             String selectData = "select id, class_type, xml from objects_tab"
284                     + " where id=? and class_type=?";
285             PreparedStatement dbData = connect.prepareStatement(selectData);
286             dbData.setString(1, id);
287             dbData.setString(2, type);
288             ResultSet resultSet = dbData.executeQuery();
289             resultSet.next();
290             String xml = resultSet.getString("xml");
291             tObj = this.parser.parseElement(xml, true);
292         } catch (SQLException ex) {
293             throw new DDTTestDataException(
294                     "Error during access on db testdata", ex);
295         } finally {
296             if (connect != null) {
297                 try {
298                     connect.close();
299                 } catch (SQLException ex) {
300                     // ignore exception
301                 }
302             }
303         }
304         return tObj;
305     }
306 
307     /**
308      * @param testDataSet
309      * @param oType specifies tag type: obj, assert, exception
310      * @param id of object for reference usage
311      * @param type of object used as additional reference attribute
312      * @param xml
313      */
314     private void addParsedObject(TestDataSet testDataSet, String oType,
315             String id, String type, String action, String xml) {
316         TypedObject tObj = this.parser.parseElement(xml, true);
317         tObj.setId(id);
318         tObj.setType(type);
319         if ("obj".equals(oType)) {
320             testDataSet.putObject(id, tObj);
321         } else if ("assert".equals(oType)) {
322             ObjectAsserter asserter = new ObjectAsserter(id, type, action);
323             asserter.setValue(tObj.getValue());
324             testDataSet.putAssert(id, asserter);
325         } else if ("exception".equals(oType)) {
326             ExceptionAsserter asserter = new ExceptionAsserter(id, type, action);
327             asserter.setValue(tObj.getValue());
328             testDataSet.putAssert(id, asserter);
329         } else {
330             throw new DDTTestDataException("Wrong tag type " + oType);
331         }
332     }
333 
334 }