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;
23  
24  import org.dbunit.database.AmbiguousTableNameException;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  /**
29   * Combines multiple datasets into a single logical dataset.
30   *
31   * @author Manuel Laflamme
32   * @version $Revision$
33   * @since Feb 19, 2002
34   */
35  public class CompositeDataSet extends AbstractDataSet
36  {
37  
38      /**
39       * Logger for this class
40       */
41      private static final Logger logger = LoggerFactory.getLogger(CompositeDataSet.class);
42  
43      private final ITable[] _tables;
44  
45      /**
46       * Creates a composite dataset that combines specified datasets.
47       * Tables having the same name are merged into one table.
48       */
49      public CompositeDataSet(IDataSet[] dataSets) throws DataSetException
50      {
51          this(dataSets, true);
52      }
53  
54      /**
55       * Creates a composite dataset that combines specified datasets.
56       *
57       * @param dataSets
58       *      list of datasets
59       * @param combine
60       *      if <code>true</code>, tables having the same name are merged into
61       *      one table.
62       */
63      public CompositeDataSet(IDataSet[] dataSets, boolean combine)
64              throws DataSetException
65      {
66          this(dataSets, combine, false);
67      }
68      
69      /**
70       * Creates a composite dataset that combines specified datasets.
71       *
72       * @param dataSets
73       *      list of datasets
74       * @param combine
75       *      if <code>true</code>, tables having the same name are merged into
76       *      one table.
77       * @param caseSensitiveTableNames Whether or not table names are handled in a case sensitive
78       * way over all datasets.
79       * @since 2.4.2
80       */
81      public CompositeDataSet(IDataSet[] dataSets, boolean combine, boolean caseSensitiveTableNames)
82              throws DataSetException
83      {
84          super(caseSensitiveTableNames);
85          
86          // Check for duplicates using the OrderedTableNameMap as helper
87          OrderedTableNameMap orderedTableMap = super.createTableNameMap();
88          for (int i = 0; i < dataSets.length; i++)
89          {
90              IDataSet dataSet = dataSets[i];
91              ITableIterator iterator = dataSet.iterator();
92              while(iterator.next())
93              {
94                  addTable(iterator.getTable(), orderedTableMap, combine);
95              }
96          }
97  
98          _tables = (ITable[]) orderedTableMap.orderedValues().toArray(new ITable[0]);
99      }
100 
101     /**
102      * Creates a composite dataset that combines the two specified datasets.
103      * Tables having the same name are merged into one table.
104      */
105     public CompositeDataSet(IDataSet dataSet1, IDataSet dataSet2)
106             throws DataSetException
107     {
108         this(new IDataSet[]{dataSet1, dataSet2});
109     }
110 
111     /**
112      * Creates a composite dataset that combines the two specified datasets.
113      *
114      * @param dataSet1
115      *      first dataset
116      * @param dataSet2
117      *      second dataset
118      * @param combine
119      *      if <code>true</code>, tables having the same name are merged into
120      *      one table.
121      */
122     public CompositeDataSet(IDataSet dataSet1, IDataSet dataSet2, boolean combine)
123             throws DataSetException
124     {
125         this(new IDataSet[]{dataSet1, dataSet2}, combine);
126     }
127 
128     /**
129      * Creates a composite dataset that combines duplicate tables of the specified dataset.
130      *
131      * @param dataSet
132      *      the dataset
133      * @param combine
134      *      if <code>true</code>, tables having the same name are merged into
135      *      one table.
136      * @deprecated This constructor is useless when the combine parameter is
137      * <code>false</code>. Use overload that doesn't have the combine argument. 
138      */
139     public CompositeDataSet(IDataSet dataSet, boolean combine)
140             throws DataSetException
141     {
142         this(new IDataSet[]{dataSet}, combine);
143     }
144 
145     /**
146      * Creates a composite dataset that combines duplicate tables of the specified dataset.
147      *
148      * @param dataSet
149      *      the dataset
150      */
151     public CompositeDataSet(IDataSet dataSet) throws DataSetException
152     {
153         this(new IDataSet[]{dataSet}, true);
154     }
155 
156     /**
157      * Creates a composite dataset that combines tables having identical name.
158      * Tables having the same name are merged into one table.
159      */
160     public CompositeDataSet(ITable[] tables) throws DataSetException
161     {
162         this(tables, false);
163     }
164     
165     /**
166      * Creates a composite dataset that combines tables having identical name.
167      * Tables having the same name are merged into one table.
168      * @param tables The tables to merge to one dataset
169      * @param caseSensitiveTableNames Whether or not table names are handled in a case sensitive
170      * way over all datasets.
171      * @since 2.4.2
172      */
173     public CompositeDataSet(ITable[] tables, boolean caseSensitiveTableNames) throws DataSetException
174     {
175         super(caseSensitiveTableNames);
176         
177         OrderedTableNameMap orderedTableMap = super.createTableNameMap();
178         for (int i = 0; i < tables.length; i++)
179         {
180             addTable(tables[i], orderedTableMap, true);
181         }
182 
183         _tables = (ITable[]) orderedTableMap.orderedValues().toArray(new ITable[0]);
184     }
185 
186     
187     /**
188      * @param newTable
189      * @param tableMap
190      * @param combine
191      * @throws AmbiguousTableNameException Can only occur when the combine flag is set to <code>false</code>.
192      */
193     private void addTable(ITable newTable, OrderedTableNameMap tableMap, boolean combine) 
194     throws AmbiguousTableNameException
195     {
196     	if (logger.isDebugEnabled())
197     	{
198     		logger.debug("addTable(newTable={}, tableList={}, combine={}) - start",
199     				new Object[] { newTable, tableMap, String.valueOf(combine) });
200     	}
201 
202         String tableName = newTable.getTableMetaData().getTableName();
203         
204         // No merge required, simply add new table at then end of the list
205         if (!combine)
206         {
207             tableMap.add(tableName, newTable);
208             return;
209         }
210 
211         // Merge required, search for existing table with the same name
212         ITable existingTable = (ITable) tableMap.get(tableName);
213         if(existingTable != null) {
214             // Found existing table, merge existing and new tables together
215             tableMap.update(tableName, new CompositeTable(existingTable, newTable));
216             return;
217         }
218         else {
219             // No existing table found, add new table at the end of the list
220             tableMap.add(tableName, newTable);
221         }
222     }
223 
224     ////////////////////////////////////////////////////////////////////////////
225     // AbstractDataSet class
226 
227     protected ITableIterator createIterator(boolean reversed)
228             throws DataSetException
229     {
230         if(logger.isDebugEnabled())
231             logger.debug("createIterator(reversed={}) - start", String.valueOf(reversed));
232         
233         return new DefaultTableIterator(_tables, reversed);
234     }
235 }