View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Eric Long <erilong@users.sourceforge.net>,
5    *               Chris Henson <chenson42@users.sourceforge.net>
6    *
7    * This library is free software; you can redistribute it and/or
8    * modify it under the terms of the GNU Lesser General Public
9    * License as published by the Free Software Foundation; either
10   * version 3 of the License, or (at your option) any later version.
11   *
12   * This library is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this library; if not, see
19   * <http://www.gnu.org/licenses/>.
20   */
21  
22  package org.jumpmind.symmetric.load;
23  
24  import java.io.ByteArrayOutputStream;
25  import java.io.IOException;
26  import java.io.OutputStream;
27  import java.io.OutputStreamWriter;
28  import java.math.BigDecimal;
29  import java.text.DecimalFormat;
30  import java.text.SimpleDateFormat;
31  import java.util.Date;
32  import java.util.Map;
33  
34  import org.apache.commons.lang.StringUtils;
35  import org.jumpmind.symmetric.common.Constants;
36  import org.jumpmind.symmetric.common.csv.CsvConstants;
37  import org.jumpmind.symmetric.service.IDataLoaderService;
38  import org.jumpmind.symmetric.service.IIncomingBatchService;
39  import org.jumpmind.symmetric.test.AbstractDatabaseTest;
40  import org.jumpmind.symmetric.test.TestConstants;
41  import org.jumpmind.symmetric.transport.mock.MockTransportManager;
42  import org.junit.Assert;
43  import org.springframework.dao.EmptyResultDataAccessException;
44  
45  import com.csvreader.CsvWriter;
46  
47  public abstract class AbstractDataLoaderTest extends AbstractDatabaseTest {
48  
49      protected final static String TEST_TABLE = "test_dataloader_table";
50  
51      protected final static String[] TEST_KEYS = { "id" };
52  
53      protected final static String[] TEST_COLUMNS = { "id", "string_value", "string_required_value", "char_value",
54              "char_required_value", "date_value", "time_value", "boolean_value", "integer_value", "decimal_value",
55              "double_value"};
56  
57      protected static int batchId = 10000;
58  
59      protected static int sequenceId = 10000;
60  
61      private IDataLoaderService dataLoaderService;
62  
63      private IIncomingBatchService incomingBatchService;
64  
65      private MockTransportManager transportManager;
66  
67      public AbstractDataLoaderTest() throws Exception {
68      }
69  
70      public AbstractDataLoaderTest(String dbType) {
71          super(dbType);
72      }
73  
74      protected MockTransportManager getTransportManager() {
75          if (transportManager == null) {
76              transportManager = new MockTransportManager();
77          }
78          return transportManager;
79      }
80  
81      protected IIncomingBatchService getIncomingBatchService() {
82          if (incomingBatchService == null) {
83              incomingBatchService = (IIncomingBatchService) find(Constants.INCOMING_BATCH_SERVICE);
84          }
85          return incomingBatchService;
86      }
87  
88      protected IDataLoaderService getDataLoaderService() {
89          if (dataLoaderService == null) {
90              dataLoaderService = (IDataLoaderService) find(Constants.DATALOADER_SERVICE);
91              dataLoaderService.setTransportManager(transportManager);
92          }
93          return dataLoaderService;
94      }
95  
96      protected String printDatabase() {
97          return " The database we are testing against is " + database + ".";
98      }
99  
100     @SuppressWarnings("unchecked")
101     public void testSimple(String dmlType, String[] values, String[] expectedValues) throws Exception {
102         ByteArrayOutputStream out = new ByteArrayOutputStream();
103         CsvWriter writer = getWriter(out);
104         writer.writeRecord(new String[] { CsvConstants.NODEID, TestConstants.TEST_CLIENT_EXTERNAL_ID });
105         String nextBatchId = getNextBatchId();
106         writer.writeRecord(new String[] { CsvConstants.BATCH, nextBatchId });
107         writeTable(writer, TEST_TABLE, TEST_KEYS, TEST_COLUMNS);
108         writer.write(dmlType);
109         writer.writeRecord(values, true);
110         writer.writeRecord(new String[] { CsvConstants.COMMIT, nextBatchId });
111         writer.close();
112         load(out);
113         assertTestTableEquals(values[0], expectedValues);
114     }
115 
116     protected CsvWriter getWriter(OutputStream out) {
117         CsvWriter writer = new CsvWriter(new OutputStreamWriter(out), ',');
118         writer.setEscapeMode(CsvWriter.ESCAPE_MODE_BACKSLASH);
119         return writer;
120     }
121 
122     protected abstract void load(ByteArrayOutputStream out) throws Exception;
123 
124     protected void writeTable(CsvWriter writer, String tableName, String[] keys, String[] columns) throws IOException {
125         writer.writeRecord(new String[] { "table", tableName });
126         writer.write("keys");
127         writer.writeRecord(keys);
128         writer.write("columns");
129         writer.writeRecord(columns);
130     }
131 
132     @SuppressWarnings("unchecked")
133     protected void assertTestTableEquals(String testTableId, String[] expectedValues) {
134         String sql = "select " + getSelect(TEST_COLUMNS) + " from " + TEST_TABLE + " where " + getWhere(TEST_KEYS);
135         Map<String, Object> results = null;
136         try {
137             results = getJdbcTemplate().queryForMap(sql, new Object[] { new Long(testTableId) });
138         } catch (EmptyResultDataAccessException e) {
139         }
140         if (expectedValues != null) {
141             expectedValues[1] = translateExpectedString(expectedValues[1], false);
142             expectedValues[2] = translateExpectedString(expectedValues[2], true);
143             expectedValues[3] = translateExpectedCharString(expectedValues[3], 50, false);
144             expectedValues[4] = translateExpectedCharString(expectedValues[4], 50, true);
145         }
146         assertEquals(TEST_COLUMNS, expectedValues, results);
147     }
148 
149     protected void assertEquals(String[] name, String[] expected, Map<String, Object> results) {
150         if (expected == null) {
151             Assert.assertNull("Expected empty results. " + printDatabase(), results);
152         } else {
153             Assert.assertNotNull("Expected non-empty results. " + printDatabase(), results);
154             for (int i = 0; i < expected.length; i++) {
155                 Object resultObj = results.get(name[i]);
156                 String resultValue = null;
157                 if (resultObj instanceof BigDecimal && expected[i].indexOf(".") != -1) {
158                     DecimalFormat df = new DecimalFormat("0.00####################################");
159                     resultValue = df.format(resultObj);
160                 } else if (resultObj instanceof Date) {
161                     SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.0");
162                     resultValue = df.format(resultObj);
163                 } else if (resultObj instanceof Boolean) {
164                     resultValue = ((Boolean) resultObj) ? "1" : "0";
165                 } else if (resultObj instanceof Double) {
166                     resultValue = resultObj.toString();
167                 } else if (resultObj != null) {
168                     resultValue = resultObj.toString();
169                 }
170 
171                 Assert.assertEquals(name[i] + ". " + printDatabase(), expected[i], resultValue);
172             }
173         }
174     }
175 
176     protected String getSelect(String[] columns) {
177         StringBuilder str = new StringBuilder();
178         for (int i = 0; i < columns.length; i++) {
179             str.append(columns[i]).append(i + 1 < columns.length ? ", " : "");
180         }
181         return str.toString();
182     }
183 
184     protected String getWhere(String[] columns) {
185         StringBuilder str = new StringBuilder();
186         for (int i = 0; i < columns.length; i++) {
187             str.append(columns[i]).append(" = ?").append(i + 1 < columns.length ? "," : "");
188         }
189         return str.toString();
190     }
191 
192     protected String translateExpectedString(String value, boolean isRequired) {
193         if (isRequired && (value == null || (value.equals("") && getDbDialect().isEmptyStringNulled()))) {
194             return TableTemplate.REQUIRED_FIELD_NULL_SUBSTITUTE;
195         } else if (value != null && value.equals("") && getDbDialect().isEmptyStringNulled()) {
196             return null;
197         }
198         return value;
199     }
200 
201     protected String translateExpectedCharString(String value, int size, boolean isRequired) {
202         if (isRequired && value == null) {
203             value = TableTemplate.REQUIRED_FIELD_NULL_SUBSTITUTE;
204         }
205         if (value != null && getDbDialect().isCharSpacePadded()) {
206             return StringUtils.rightPad(value, size);
207         } else if (value != null && getDbDialect().isCharSpaceTrimmed()) {
208             return value.replaceFirst(" *$", "");
209         }
210         return value;
211     }
212 
213     protected synchronized String getNextBatchId() {
214         return Integer.toString(++batchId);
215     }
216 
217     protected synchronized String getBatchId() {
218         return Integer.toString(batchId);
219     }
220 
221     protected synchronized String getNextId() {
222         return Integer.toString(++sequenceId);
223     }
224 
225     protected synchronized String getId() {
226         return Integer.toString(sequenceId);
227     }
228 
229 }