View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2004, DbUnit.org
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  
22  package org.dbunit.dataset.yaml;
23  
24  import org.dbunit.database.AmbiguousTableNameException;
25  import org.dbunit.dataset.Column;
26  import org.dbunit.dataset.DataSetException;
27  import org.dbunit.dataset.DefaultTableMetaData;
28  import org.dbunit.dataset.ITableMetaData;
29  import org.dbunit.dataset.datatype.DataType;
30  import org.dbunit.dataset.stream.DefaultConsumer;
31  import org.dbunit.dataset.stream.IDataSetConsumer;
32  import org.dbunit.dataset.stream.IDataSetProducer;
33  import org.yaml.snakeyaml.LoaderOptions;
34  import org.yaml.snakeyaml.Yaml;
35  import org.yaml.snakeyaml.constructor.DuplicateKeyException;
36  
37  import java.io.File;
38  import java.io.FileInputStream;
39  import java.io.IOException;
40  import java.io.InputStream;
41  import java.util.ArrayList;
42  import java.util.LinkedHashMap;
43  import java.util.LinkedHashSet;
44  import java.util.List;
45  import java.util.Map;
46  import java.util.Set;
47  
48  /**
49   * @author Björn Beskow
50   * @version $Revision$ $Date$
51   */
52  
53  public class YamlProducer implements IDataSetProducer
54  {
55  
56      private static final IDataSetConsumer EMPTY_CONSUMER = new DefaultConsumer();
57  
58      /**
59       * The consumer which is responsible for creating the datasets and tables
60       */
61      private IDataSetConsumer _consumer = EMPTY_CONSUMER;
62  
63      private InputStream _inputStream;
64  
65      private Yaml _yaml;
66  
67      public YamlProducer(File file) throws IOException
68      {
69          this(new FileInputStream(file));
70      }
71  
72      public YamlProducer(InputStream inputStream)
73      {
74          this._inputStream = inputStream;
75          LoaderOptions options = new LoaderOptions();
76          options.setAllowDuplicateKeys(false);
77          _yaml = new Yaml(options);
78      }
79  
80      ////////////////////////////////////////////////////////////////////////////
81      // IDataSetProducer interface
82  
83      public void setConsumer(IDataSetConsumer consumer)
84      {
85          _consumer = consumer;
86      }
87  
88      public void produce() throws DataSetException
89      {
90          _consumer.startDataSet();
91          LinkedHashMap<String, Object> dataset;
92          // get the base object tree from the stream
93          try
94          {
95              dataset = (LinkedHashMap<String, Object>) _yaml.load(_inputStream);
96          }
97          catch (DuplicateKeyException e)
98          {
99              String problem = e.getProblem();
100             String duplicateTable = problem.replace("found duplicate key ", "");
101             throw new AmbiguousTableNameException(duplicateTable, e);
102         }
103         // iterate over the tables in the object tree
104         for (String tableName : dataset.keySet())
105         {
106             // get the rows for the table
107             List<Map<String, Object>> rows = (List<Map<String, Object>>) dataset.get(tableName);
108             ITableMetaData meta = getMetaData(tableName, rows);
109             _consumer.startTable(meta);
110             if (rows != null)
111             {
112                 for (Map<String, Object> row : rows)
113                 {
114                     _consumer.row(getRow(meta, row));
115                 }
116             }
117             _consumer.endTable();
118         }
119     }
120 
121 
122     private ITableMetaData getMetaData(String tableName, List<Map<String, Object>> rows)
123     {
124         Set<String> columns = new LinkedHashSet<String>();
125         if (rows != null)
126         {
127             // iterate through the dataset and add the column names to a set
128             for (Map<String, Object> row : rows)
129             {
130                 for (Map.Entry<String, Object> column : row.entrySet())
131                 {
132                     columns.add(column.getKey());
133                 }
134             }
135             List<Column> list = new ArrayList<Column>(columns.size());
136             // create a list of DBUnit columns based on the column name set
137             for (String s : columns)
138             {
139                 list.add(new Column(s, DataType.UNKNOWN));
140             }
141             return new DefaultTableMetaData(tableName, list.toArray(new Column[list.size()]));
142         } else
143         {
144             return new DefaultTableMetaData(tableName, new Column[0]);
145         }
146     }
147 
148     private Object[] getRow(ITableMetaData meta, Map<String, Object> row) throws DataSetException
149     {
150         Object[] result = new Object[meta.getColumns().length];
151         for (int i = 0; i < meta.getColumns().length; i++)
152         {
153             result[i] = row.get(meta.getColumns()[i].getColumnName());
154         }
155         return result;
156     }
157 
158 }