Coverage Report - liquibase.change.core.LoadDataChange
 
Classes in this File Line Coverage Branch Coverage Complexity
LoadDataChange
76%
86/113
48%
30/62
3.182
 
 1  
 package liquibase.change.core;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.io.InputStream;
 5  
 import java.io.InputStreamReader;
 6  
 import java.util.ArrayList;
 7  
 import java.util.List;
 8  
 
 9  
 import liquibase.change.AbstractChange;
 10  
 import liquibase.change.ChangeMetaData;
 11  
 import liquibase.change.ChangeWithColumns;
 12  
 import liquibase.change.CheckSum;
 13  
 import liquibase.change.ColumnConfig;
 14  
 import liquibase.database.Database;
 15  
 import liquibase.exception.UnexpectedLiquibaseException;
 16  
 import liquibase.resource.ResourceAccessor;
 17  
 import liquibase.statement.SqlStatement;
 18  
 import liquibase.statement.core.InsertStatement;
 19  
 import liquibase.util.StringUtils;
 20  
 import liquibase.util.csv.CSVReader;
 21  
 
 22  
 public class LoadDataChange extends AbstractChange implements ChangeWithColumns {
 23  
 
 24  
     private String schemaName;
 25  
     private String tableName;
 26  
     private String file;
 27  49
     private String encoding = null;
 28  49
     private String separator = liquibase.util.csv.opencsv.CSVReader.DEFAULT_SEPARATOR + "";
 29  49
     private String quotchar = liquibase.util.csv.opencsv.CSVReader.DEFAULT_QUOTE_CHARACTER + "";
 30  
 
 31  49
     private List<LoadDataColumnConfig> columns = new ArrayList<LoadDataColumnConfig>();
 32  
 
 33  
     public LoadDataChange() {
 34  18
         super("loadData", "Load Data", ChangeMetaData.PRIORITY_DEFAULT);
 35  18
     }
 36  
 
 37  
     protected LoadDataChange(String changeName, String changeDescription) {
 38  31
         super(changeName, changeDescription, ChangeMetaData.PRIORITY_DEFAULT);
 39  31
     }
 40  
 
 41  
     public String getSchemaName() {
 42  22
         return schemaName;
 43  
     }
 44  
 
 45  
     public void setSchemaName(String schemaName) {
 46  12
         this.schemaName = StringUtils.trimToNull(schemaName);
 47  12
     }
 48  
 
 49  
     public String getTableName() {
 50  24
         return tableName;
 51  
     }
 52  
 
 53  
     public void setTableName(String tableName) {
 54  14
         this.tableName = tableName;
 55  14
     }
 56  
 
 57  
     public String getFile() {
 58  18
         return file;
 59  
     }
 60  
 
 61  
     public void setFile(String file) {
 62  16
         this.file = file;
 63  16
     }
 64  
 
 65  
     public String getEncoding() {
 66  10
         return encoding;
 67  
     }
 68  
 
 69  
     public void setEncoding(String encoding) {
 70  1
         this.encoding = encoding;
 71  1
     }
 72  
 
 73  
     public String getSeparator() {
 74  0
         return separator;
 75  
     }
 76  
 
 77  
     public void setSeparator(String separator) {
 78  2
         this.separator = separator;
 79  2
     }
 80  
 
 81  
     public String getQuotchar() {
 82  0
         return quotchar;
 83  
     }
 84  
 
 85  
     public void setQuotchar(String quotchar) {
 86  1
         this.quotchar = quotchar;
 87  1
     }
 88  
 
 89  
     @Override
 90  
     public void addColumn(ColumnConfig column) {
 91  2
         columns.add((LoadDataColumnConfig) column);
 92  2
     }
 93  
 
 94  
     @Override
 95  
     public List<ColumnConfig> getColumns() {
 96  0
         return (List<ColumnConfig>) (List) columns;
 97  
     }
 98  
 
 99  
     @Override
 100  
     public SqlStatement[] generateStatements(Database database) {
 101  10
         CSVReader reader = null;
 102  
         try {
 103  10
             reader = getCSVReader();
 104  
 
 105  10
             String[] headers = reader.readNext();
 106  10
             if (headers == null) {
 107  0
                 throw new UnexpectedLiquibaseException("Data file " + getFile() + " was empty");
 108  
             }
 109  
 
 110  10
             List<SqlStatement> statements = new ArrayList<SqlStatement>();
 111  10
             String[] line = null;
 112  10
             int lineNumber = 0;
 113  
 
 114  30
             while ((line = reader.readNext()) != null) {
 115  20
                 lineNumber++;
 116  
 
 117  20
                 if (line.length == 0 || (line.length == 1 && StringUtils.trimToNull(line[0]) == null)) {
 118  0
                     continue; // nothing on this line
 119  
                 }
 120  20
                 InsertStatement insertStatement = this.createStatement(getSchemaName(), getTableName());
 121  64
                 for (int i = 0; i < headers.length; i++) {
 122  44
                     String columnName = null;
 123  44
                     if (i >= line.length) {
 124  0
                         throw new UnexpectedLiquibaseException("CSV Line " + lineNumber + " has only " + (i - 1)
 125  
                                 + " columns, the header has " + headers.length);
 126  
                     }
 127  
 
 128  44
                     Object value = line[i];
 129  
 
 130  44
                     ColumnConfig columnConfig = getColumnConfig(i, headers[i]);
 131  44
                     if (columnConfig != null) {
 132  4
                         columnName = columnConfig.getName();
 133  
 
 134  4
                         if (value.toString().equalsIgnoreCase("NULL")) {
 135  0
                             value = "NULL";
 136  4
                         } else if (columnConfig.getType() != null) {
 137  4
                             ColumnConfig valueConfig = new ColumnConfig();
 138  4
                             if (columnConfig.getType().equalsIgnoreCase("BOOLEAN")) {
 139  2
                                 valueConfig.setValueBoolean(Boolean.parseBoolean(value.toString().toLowerCase()));
 140  2
                             } else if (columnConfig.getType().equalsIgnoreCase("NUMERIC")) {
 141  2
                                 valueConfig.setValueNumeric(value.toString());
 142  0
                             } else if (columnConfig.getType().toLowerCase().contains("date")
 143  
                                     || columnConfig.getType().toLowerCase().contains("time")) {
 144  0
                                 valueConfig.setValueDate(value.toString());
 145  0
                             } else if (columnConfig.getType().equalsIgnoreCase("STRING")) {
 146  0
                                 valueConfig.setValue(value.toString());
 147  0
                             } else if (columnConfig.getType().equalsIgnoreCase("COMPUTED")) {
 148  0
                                 valueConfig.setValue(value.toString());
 149  
                             } else {
 150  0
                                 throw new UnexpectedLiquibaseException("loadData type of " + columnConfig.getType()
 151  
                                         + " is not supported.  Please use BOOLEAN, NUMERIC, DATE, STRING, or COMPUTED");
 152  
                             }
 153  4
                             value = valueConfig.getValueObject();
 154  
                         }
 155  
                     }
 156  
 
 157  44
                     if (columnName == null) {
 158  44
                         columnName = headers[i];
 159  
                     }
 160  
 
 161  44
                     insertStatement.addColumnValue(columnName, value);
 162  
                 }
 163  20
                 statements.add(insertStatement);
 164  20
             }
 165  
 
 166  10
             return statements.toArray(new SqlStatement[statements.size()]);
 167  0
         } catch (IOException e) {
 168  0
             throw new RuntimeException(e);
 169  
         } finally {
 170  10
             if (null != reader) {
 171  
                 try {
 172  10
                     reader.close();
 173  0
                 } catch (IOException e) {
 174  
                     ;
 175  20
                 }
 176  
             }
 177  
         }
 178  
     }
 179  
 
 180  
     protected CSVReader getCSVReader() throws IOException {
 181  10
         ResourceAccessor opener = getResourceAccessor();
 182  10
         if (opener == null) {
 183  0
             throw new UnexpectedLiquibaseException("No file opener specified for " + getFile());
 184  
         }
 185  10
         InputStream stream = opener.getResourceAsStream(getFile());
 186  10
         if (stream == null) {
 187  0
             throw new UnexpectedLiquibaseException("Data file " + getFile() + " was not found");
 188  
         }
 189  
 
 190  
         InputStreamReader streamReader;
 191  10
         if (getEncoding() == null) {
 192  10
             streamReader = new InputStreamReader(stream);
 193  
         } else {
 194  0
             streamReader = new InputStreamReader(stream, getEncoding());
 195  
         }
 196  
 
 197  
         char quotchar;
 198  10
         if (0 == this.quotchar.length()) {
 199  
             // hope this is impossible to have a field surrounded with non ascii char 0x01
 200  0
             quotchar = '\1';
 201  
         } else {
 202  10
             quotchar = this.quotchar.charAt(0);
 203  
         }
 204  
 
 205  10
         CSVReader reader = new CSVReader(streamReader, separator.charAt(0), quotchar);
 206  
 
 207  10
         return reader;
 208  
     }
 209  
 
 210  
     protected InsertStatement createStatement(String schemaName, String tableName) {
 211  8
         return new InsertStatement(schemaName, tableName);
 212  
     }
 213  
 
 214  
     protected ColumnConfig getColumnConfig(int index, String header) {
 215  44
         for (LoadDataColumnConfig config : columns) {
 216  14
             if (config.getIndex() != null && config.getIndex().equals(index)) {
 217  0
                 return config;
 218  
             }
 219  14
             if (config.getHeader() != null && config.getHeader().equalsIgnoreCase(header)) {
 220  4
                 return config;
 221  
             }
 222  
 
 223  10
             if (config.getName() != null && config.getName().equalsIgnoreCase(header)) {
 224  0
                 return config;
 225  
             }
 226  
         }
 227  40
         return null;
 228  
     }
 229  
 
 230  
     @Override
 231  
     public String getConfirmationMessage() {
 232  2
         return "Data loaded from " + getFile() + " into " + getTableName();
 233  
     }
 234  
 
 235  
     @Override
 236  
     public CheckSum generateCheckSum() {
 237  6
         InputStream stream = null;
 238  
         try {
 239  6
             stream = getResourceAccessor().getResourceAsStream(getFile());
 240  6
             if (stream == null) {
 241  0
                 throw new RuntimeException(getFile() + " could not be found");
 242  
             }
 243  6
             return CheckSum.compute(stream);
 244  0
         } catch (IOException e) {
 245  0
             throw new RuntimeException(e);
 246  
         } finally {
 247  6
             if (stream != null) {
 248  
                 try {
 249  6
                     stream.close();
 250  0
                 } catch (IOException e) {
 251  
                     ;
 252  12
                 }
 253  
             }
 254  
         }
 255  
     }
 256  
 }