001: /*
002: * ProducerFactory.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.db.importer;
013:
014: import java.io.File;
015: import java.util.List;
016: import workbench.db.ColumnIdentifier;
017: import workbench.db.TableIdentifier;
018: import workbench.db.WbConnection;
019: import workbench.gui.dialogs.dataimport.ImportOptions;
020: import workbench.gui.dialogs.dataimport.TextImportOptions;
021: import workbench.gui.dialogs.dataimport.XmlImportOptions;
022: import workbench.interfaces.ImportFileParser;
023: import workbench.sql.wbcommands.CommandTester;
024: import workbench.sql.wbcommands.CommonArgs;
025: import workbench.sql.wbcommands.CommonArgs;
026: import workbench.sql.wbcommands.WbImport;
027: import workbench.util.StringUtil;
028: import workbench.util.ValueConverter;
029:
030: /**
031: * A factory for RowDataProducer to import text or XML files.
032: *
033: * @author support@sql-workbench.net
034: */
035: public class ProducerFactory {
036: public static final int IMPORT_TEXT = 0;
037: public static final int IMPORT_XML = 1;
038: private int importType = -1;
039: private TextImportOptions textOptions;
040: private XmlImportOptions xmlOptions;
041: private ImportOptions generalOptions;
042: private File inputFile;
043: private List<ColumnIdentifier> inputColumns;
044: private TableIdentifier table;
045: private RowDataProducer producer;
046: private ImportFileParser fileParser;
047: private WbConnection connection;
048: private int batchSize = -1;
049:
050: public ProducerFactory(File inputFile) {
051: this .setInputFile(inputFile);
052: }
053:
054: public void setBatchSize(int size) {
055: this .batchSize = (size > 0 ? size : -1);
056: }
057:
058: public void setConnection(WbConnection conn) {
059: if (this .connection != conn) {
060: this .producer = null;
061: }
062: this .connection = conn;
063: }
064:
065: public void setGeneralOptions(ImportOptions options) {
066: this .generalOptions = options;
067: }
068:
069: public void setTextOptions(TextImportOptions options) {
070: this .textOptions = options;
071: }
072:
073: public TextImportOptions getTextOptions() {
074: return this .textOptions;
075: }
076:
077: public XmlImportOptions getXmlOptions() {
078: return this .xmlOptions;
079: }
080:
081: public void setXmlOptions(XmlImportOptions options) {
082: this .xmlOptions = options;
083: }
084:
085: public void setImporterOptions(DataImporter importer) {
086: importer.setMode(generalOptions.getMode());
087: }
088:
089: public void setType(int type) {
090: if (type == IMPORT_TEXT)
091: this .setImportTypeText();
092: else if (type == IMPORT_XML)
093: this .setImportTypeXml();
094: else
095: throw new IllegalArgumentException(
096: "Not a valid import type!");
097: }
098:
099: public boolean isTextImport() {
100: return this .importType == IMPORT_TEXT;
101: }
102:
103: public boolean isXmlImport() {
104: return this .importType == IMPORT_XML;
105: }
106:
107: public void setImportTypeText() {
108: this .importType = IMPORT_TEXT;
109: this .producer = null;
110: }
111:
112: public void setImportTypeXml() {
113: this .importType = IMPORT_XML;
114: this .producer = null;
115: }
116:
117: private void setInputFile(File inputFilename) {
118: this .inputFile = inputFilename;
119: this .inputColumns = null;
120: this .producer = null;
121: this .fileParser = null;
122: }
123:
124: public void setTargetTable(TableIdentifier tableId) {
125: this .table = tableId;
126: if (this .table == null)
127: return;
128: if (this .producer == null)
129: getProducer();
130: fileParser.setTableName(tableId.getTableExpression());
131: }
132:
133: public RowDataProducer getProducer() {
134: if (this .producer == null) {
135: if (this .importType == IMPORT_TEXT)
136: createTextFileParser();
137: else if (this .importType == IMPORT_XML)
138: createXmlFileParser();
139: }
140: return this .producer;
141: }
142:
143: /**
144: * Return the list of columns defined in the file
145: */
146: public List<ColumnIdentifier> getFileColumns() {
147: if (this .inputColumns == null) {
148: getProducer();
149: this .inputColumns = fileParser.getColumnsFromFile();
150: }
151: return this .inputColumns;
152: }
153:
154: public void setImportColumns(List<ColumnIdentifier> cols)
155: throws Exception {
156: if (this .producer == null)
157: getProducer();
158: this .fileParser.setColumns(cols);
159: }
160:
161: private void createTextFileParser() {
162: TextFileParser parser = new TextFileParser(inputFile);
163: parser.setEncoding(this .generalOptions.getEncoding());
164: parser.setContainsHeader(this .textOptions.getContainsHeader());
165: parser.setQuoteChar(this .textOptions.getTextQuoteChar());
166: parser.setDecodeUnicode(this .textOptions.getDecode());
167: parser.setDelimiter(this .textOptions.getTextDelimiter());
168: parser.setConnection(this .connection);
169:
170: ValueConverter converter = new ValueConverter();
171: converter.setDefaultDateFormat(this .generalOptions
172: .getDateFormat());
173: converter.setDefaultTimestampFormat(this .generalOptions
174: .getTimestampFormat());
175: String dec = this .textOptions.getDecimalChar();
176: if (dec != null)
177: converter.setDecimalCharacter(dec.charAt(0));
178: parser.setValueConverter(converter);
179:
180: if (this .table != null) {
181: parser.setTableName(this .table.getTableExpression());
182: }
183: this .inputColumns = null;
184: this .producer = parser;
185: this .fileParser = parser;
186: }
187:
188: public File getSourceFile() {
189: return this .inputFile;
190: }
191:
192: private void createXmlFileParser() {
193: XmlDataFileParser parser = new XmlDataFileParser(inputFile);
194: parser.setEncoding(this .generalOptions.getEncoding());
195: //parser.setUseVerboseFormat(this.xmlOptions.getUseVerboseXml());
196: this .inputColumns = null;
197: this .producer = parser;
198: this .fileParser = parser;
199: }
200:
201: /**
202: * Appends text import options to the passed sql command
203: */
204: private void appendTextOptions(StringBuilder command,
205: StringBuilder indent) {
206: if (this .textOptions == null)
207: return;
208: appendArgument(command, WbImport.ARG_CONTAINSHEADER,
209: textOptions.getContainsHeader(), indent);
210: appendArgument(command, WbImport.ARG_DECODE, textOptions
211: .getDecode(), indent);
212: String delim = textOptions.getTextDelimiter();
213: if ("\t".equals(delim))
214: delim = "\\t";
215:
216: appendArgument(command, CommonArgs.ARG_DATE_FORMAT,
217: generalOptions.getDateFormat(), indent);
218: appendArgument(command, CommonArgs.ARG_TIMESTAMP_FORMAT,
219: generalOptions.getTimestampFormat(), indent);
220: appendArgument(command, CommonArgs.ARG_DELIM,
221: "'" + delim + "'", indent);
222: appendArgument(command, WbImport.ARG_QUOTE, textOptions
223: .getTextQuoteChar(), indent);
224: appendArgument(command, CommonArgs.ARG_DECCHAR, textOptions
225: .getDecimalChar(), indent);
226: appendArgument(command, WbImport.ARG_FILECOLUMNS,
227: this .fileParser.getColumns(), indent);
228: }
229:
230: private void appendArgument(StringBuilder result, String arg,
231: boolean value, StringBuilder indent) {
232: appendArgument(result, arg, Boolean.toString(value), indent);
233: }
234:
235: private void appendArgument(StringBuilder result, String arg,
236: String value, StringBuilder indent) {
237: if (!StringUtil.isEmptyString(value)) {
238: result.append(indent);
239: result.append('-');
240: result.append(arg);
241: result.append('=');
242:
243: if (value.indexOf('-') > -1 || value.indexOf(";") > -1)
244: result.append('"');
245: else if ("\"".equals(value))
246: result.append('\'');
247: else if ("\'".equals(value))
248: result.append('\"');
249:
250: result.append(value);
251:
252: if (value.indexOf('-') > -1 || value.indexOf(";") > -1)
253: result.append('"');
254: else if ("\"".equals(value))
255: result.append('\'');
256: else if ("\'".equals(value))
257: result.append('\"');
258: }
259: }
260:
261: /**
262: * Generates a WB SQL command from the current import
263: * settings
264: */
265: public String getWbCommand() {
266: StringBuilder result = new StringBuilder(150);
267: StringBuilder indent = new StringBuilder();
268: indent.append('\n');
269: for (int i = 0; i < WbImport.VERB.length(); i++)
270: indent.append(' ');
271: indent.append(' ');
272: CommandTester ct = new CommandTester();
273: String verb = ct.formatVerb(WbImport.VERB);
274: result.append(verb + " -" + WbImport.ARG_FILE + "=");
275: String filename = inputFile.getAbsolutePath();
276: if (filename.indexOf('-') > -1)
277: result.append('"');
278: result.append(StringUtil.replace(filename, "\\", "/"));
279: if (filename.indexOf('-') > -1)
280: result.append('"');
281: result.append(indent);
282: result.append('-');
283: result.append(WbImport.ARG_TYPE);
284: result.append('=');
285: if (this .isXmlImport()) {
286: result.append("xml");
287: } else {
288: result.append("text");
289: }
290:
291: appendArgument(result, WbImport.ARG_TARGETTABLE, this .table
292: .getTableName(), indent);
293: appendArgument(result, CommonArgs.ARG_ENCODING,
294: this .generalOptions.getEncoding(), indent);
295: appendArgument(result, WbImport.ARG_MODE, this .generalOptions
296: .getMode(), indent);
297: if (this .batchSize > 0) {
298: appendArgument(result, CommonArgs.ARG_BATCHSIZE, Integer
299: .toString(this .batchSize), indent);
300: }
301: appendTextOptions(result, indent);
302:
303: result.append("\n;");
304:
305: return result.toString();
306: }
307:
308: }
|