0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.mashup.db.model.impl;
0042:
0043: import com.sun.sql.framework.exception.BaseException;
0044: import java.io.File;
0045: import java.util.ArrayList;
0046: import java.util.Collections;
0047: import java.util.HashMap;
0048: import java.util.HashSet;
0049: import java.util.Iterator;
0050: import java.util.LinkedHashMap;
0051: import java.util.List;
0052: import java.util.Map;
0053: import java.util.Set;
0054: import java.util.SortedSet;
0055: import java.util.TreeSet;
0056:
0057: import org.netbeans.modules.mashup.db.common.Property;
0058: import org.netbeans.modules.mashup.db.common.PropertyKeys;
0059: import org.netbeans.modules.mashup.db.model.FlatfileDBColumn;
0060: import org.netbeans.modules.mashup.db.model.FlatfileDBTable;
0061: import org.netbeans.modules.sql.framework.model.DBColumn;
0062: import org.netbeans.modules.sql.framework.common.utils.TagParserUtility;
0063: import org.netbeans.modules.sql.framework.model.impl.PrimaryKeyImpl;
0064: import org.w3c.dom.Element;
0065: import org.w3c.dom.Node;
0066: import org.w3c.dom.NodeList;
0067: import net.java.hulp.i18n.Logger;
0068: import com.sun.sql.framework.utils.StringUtil;
0069: import org.netbeans.modules.etl.logger.Localizer;
0070: import org.netbeans.modules.etl.logger.LogUtil;
0071: import org.netbeans.modules.sql.framework.model.DBTable;
0072: import org.netbeans.modules.sql.framework.model.SQLDBColumn;
0073: import org.netbeans.modules.sql.framework.model.SQLDBTable;
0074: import org.netbeans.modules.sql.framework.model.impl.AbstractDBTable;
0075:
0076: /**
0077: * Reference implementation for interface org.netbeans.modules.etl.model.DBTable
0078: *
0079: * @author Jonathan Giron
0080: * @author Girish Patil
0081: * @author Ahimanikya Satapathy
0082: * @version $Revision$
0083: */
0084: public class FlatfileDBTableImpl extends AbstractDBTable implements
0085: FlatfileDBTable, Cloneable, Comparable {
0086:
0087: /** Constants used in XML tags * */
0088: private static final String ATTR_ENCODING = "encoding";
0089: private static final String ATTR_FILE_NAME = "fileName";
0090: private static final String ATTR_NAME = "name";
0091: private static final String ATTR_PARENT = "parent";
0092: /* Constant: character indicating end of ORGANIZATION property clause */
0093: private static final String END_PROPS_DELIMITER = ")";
0094: private static final String END_QUOTE_SPACE = "\" ";
0095: private static final String EQUAL_START_QUOTE = "=\"";
0096: private static transient final Logger mLogger = LogUtil
0097: .getLogger(FlatfileDBTableImpl.class.getName());
0098: private static transient final Localizer mLoc = Localizer.get();
0099: /* Log4J category string */
0100: private static final String LOG_CATEGORY = FlatfileDBTableImpl.class
0101: .getName();
0102: /* Constant: separator between key-value properties in ORGANIZATION clause */
0103: private static final String PROP_SEPARATOR = ", ";
0104: /* Constant: keyword signaling start of properties clause */
0105: private static final String PROPS_KEYWORD = "ORGANIZATION"; // NOI18N
0106: /* Constant: character indicating start of ORGANIZATION property clause */
0107: private static final String START_PROPS_DELIMITER = "(";
0108: private static final String TAB = "\t";
0109: private static final String TAG_STCDB_COLUMN = "stcdbColumn";
0110: // private static final String TAG_STCDB_COLUMN = "FlatfileColumn";
0111: private static final String TAG_STCDB_TABLE = "stcdbTable";
0112: // private static final String TAG_STCDB_TABLE = "FlatfileTable";
0113: /**
0114: * Holds property keys which are only used by the wizard and will cause errors in
0115: * Axion during validation of table properties.
0116: */
0117: private static final Set WIZARD_ONLY_PROPERTIES = new HashSet();
0118:
0119: static {
0120: WIZARD_ONLY_PROPERTIES.add("DEFAULTSQLTYPE");
0121: WIZARD_ONLY_PROPERTIES.add("FILEPATH");
0122: WIZARD_ONLY_PROPERTIES.add("FIELDCOUNT");
0123: }
0124: /* Encoding of file contents, e.g., utf-8, cp500, etc. */
0125: private String encoding = "";
0126: /* Sample file name (no path) */
0127: private String fileName = "";
0128: /* Path to sample file locally */
0129: private transient String localPath = File.separator;
0130: private String parserType;
0131: /* Parse configurator for this flatfile */
0132: private Map properties;
0133:
0134: /* No-arg constructor; initializes Collections-related member variables. */
0135: public FlatfileDBTableImpl() {
0136: super ();
0137: columns = new LinkedHashMap<String, DBColumn>();
0138: properties = new HashMap();
0139: }
0140:
0141: /**
0142: * Creates a new instance of FlatfileDBTableImpl, cloning the contents of the given
0143: * DBTable implementation instance.
0144: *
0145: * @param src DBTable instance to be cloned
0146: */
0147: public FlatfileDBTableImpl(DBTable src) {
0148: this ();
0149:
0150: if (src == null) {
0151: throw new IllegalArgumentException(
0152: "Must supply non-null DBTable instance for src param.");
0153: }
0154:
0155: copyFrom(src);
0156: }
0157:
0158: /**
0159: * Creates a new instance of FlatfileDBTableImpl, cloning the contents of the given
0160: * FlatfileDBTable implementation instance.
0161: *
0162: * @param src FlatfileDBTable instance to be cloned
0163: */
0164: public FlatfileDBTableImpl(FlatfileDBTable src) {
0165: this ();
0166:
0167: if (src == null) {
0168: throw new IllegalArgumentException(
0169: "Must supply non-null FlatfileDBTable instance for src param.");
0170: }
0171:
0172: copyFrom(src);
0173: }
0174:
0175: public FlatfileDBTableImpl(String aName) {
0176: this ();
0177: this .name = (aName != null) ? aName.trim() : null;
0178: }
0179:
0180: /*
0181: * Implementation of DBTable interface.
0182: */
0183: /**
0184: * Creates a new instance of FlatfileDBTableImpl with the given name.
0185: *
0186: * @param aName name of new DBTable instance
0187: * @param aSchema schema of new DBTable instance; may be null
0188: * @param aCatalog catalog of new DBTable instance; may be null
0189: */
0190: public FlatfileDBTableImpl(String aName, String aSchema,
0191: String aCatalog) {
0192: this ();
0193: this .name = (aName != null) ? aName.trim() : null;
0194: }
0195:
0196: /**
0197: * Adds a DBColumn instance to this table.
0198: *
0199: * @param theColumn column to be added.
0200: * @param ignoreDupCols ignore or throw exception when column with same name being added.
0201: * @return true if successful. false if failed.
0202: */
0203: private boolean addColumn(SQLDBColumn theColumn,
0204: boolean ignoreDupCols) {
0205: if (theColumn != null) {
0206: if ((!ignoreDupCols)
0207: && (columns.containsKey(theColumn.getName()))) {
0208: throw new IllegalArgumentException("Column "
0209: + theColumn.getName() + " already exist.");
0210: }
0211: theColumn.setParent(this );
0212: this .columns.put(theColumn.getName(), theColumn);
0213: return true;
0214: }
0215:
0216: return false;
0217: }
0218:
0219: /**
0220: * Adds a DBColumn instance to this table.
0221: *
0222: * @param theColumn column to be added.
0223: * @return true if successful. false if failed.
0224: */
0225: @Override
0226: public boolean addColumn(SQLDBColumn theColumn) {
0227: return addColumn(theColumn, false);
0228: }
0229:
0230: /**
0231: * Clone a deep copy of DBTable.
0232: *
0233: * @return a copy of DBTable.
0234: */
0235: @Override
0236: public Object clone() {
0237: try {
0238: FlatfileDBTableImpl table = (FlatfileDBTableImpl) super
0239: .clone();
0240: table.columns = new LinkedHashMap();
0241: table.deepCopyReferences(this );
0242:
0243: return table;
0244: } catch (CloneNotSupportedException e) {
0245: throw new InternalError(e.toString());
0246: }
0247: }
0248:
0249: /**
0250: * Compares DBTable with another object for lexicographical ordering. Null objects and
0251: * those DBTables with null names are placed at the end of any ordered collection
0252: * using this method.
0253: *
0254: * @param refObj Object to be compared.
0255: * @return -1 if the column name is less than obj to be compared. 0 if the column name
0256: * is the same. 1 if the column name is greater than obj to be compared.
0257: */
0258: @Override
0259: public int compareTo(Object refObj) {
0260: if (refObj == null) {
0261: return -1;
0262: }
0263:
0264: if (refObj == this ) {
0265: return 0;
0266: }
0267:
0268: String refName = (parentDBModel != null) ? parentDBModel
0269: .getFullyQualifiedTableName((DBTable) refObj)
0270: : ((DBTable) refObj).getName();
0271: String myName = (parentDBModel != null) ? parentDBModel
0272: .getFullyQualifiedTableName(this ) : name;
0273: return (myName != null) ? myName.compareTo(refName)
0274: : (refName != null) ? 1 : -1;
0275: }
0276:
0277: /**
0278: * Performs deep copy of contents of given DBTable. We deep copy (that is, the method
0279: * clones all child objects such as columns) because columns have a parent-child
0280: * relationship that must be preserved internally.
0281: *
0282: * @param source DBTable providing contents to be copied.
0283: */
0284: @Override
0285: public void copyFrom(DBTable source) {
0286: if (source == null) {
0287: throw new IllegalArgumentException(
0288: "Must supply non-null ref for source");
0289: } else if (source == this ) {
0290: return;
0291: }
0292:
0293: name = source.getName();
0294: description = source.getDescription();
0295:
0296: deepCopyReferences(source);
0297: }
0298:
0299: /**
0300: * Performs deep copy of contents of given FlatfileDBTable. We deep copy (that is, the
0301: * method clones all child objects such as columns) because columns have a
0302: * parent-child relationship that must be preserved internally.
0303: *
0304: * @param source FlatfileDBTable providing contents to be copied.
0305: */
0306: public void copyFrom(FlatfileDBTable source) {
0307: copyFrom((DBTable) source);
0308: if (source instanceof FlatfileDBTableImpl) {
0309: FlatfileDBTableImpl impl = (FlatfileDBTableImpl) source;
0310: encoding = impl.encoding;
0311: fileName = impl.fileName;
0312: name = impl.name;
0313:
0314: deepCopyReferences(impl);
0315: }
0316: }
0317:
0318: /**
0319: * Convenience class to create FlatfileDBColumnImpl instance (with the given column
0320: * name, data source name, JDBC type, scale, precision, and nullable), and add it to
0321: * this FlatfileDBTableImpl instance.
0322: *
0323: * @param columnName Column name
0324: * @param jdbcType JDBC type defined in SQL.Types
0325: * @param scale Scale
0326: * @param precision Precision
0327: * @param isPK true if part of primary key, false otherwise
0328: * @param isFK true if part of foreign key, false otherwise
0329: * @param isIndexed true if indexed, false otherwise
0330: * @param nullable Nullable
0331: * @return new FlatfileDBColumnImpl instance
0332: */
0333: public FlatfileDBColumn createColumn(String columnName,
0334: int jdbcType, int scale, int precision, boolean isPK,
0335: boolean isFK, boolean isIndexed, boolean nullable) {
0336: FlatfileDBColumn impl = new FlatfileDBColumnImpl(columnName,
0337: jdbcType, scale, precision, isPK, isFK, isIndexed,
0338: nullable);
0339: impl.setParent(this );
0340: this .columns.put(columnName, impl);
0341: return impl;
0342: }
0343:
0344: /**
0345: * Overrides default implementation to return value based on memberwise comparison.
0346: *
0347: * @param obj Object against which we compare this instance
0348: * @return true if obj is functionally identical to this ETLTable instance; false
0349: * otherwise
0350: */
0351: @Override
0352: public boolean equals(Object obj) {
0353: boolean result = false;
0354:
0355: // Check for reflexivity first.
0356: if (this == obj) {
0357: return true;
0358: }
0359:
0360: // Check for castability (also deals with null instance)
0361: boolean response = false;
0362: if (obj instanceof FlatfileDBTable) {
0363: FlatfileDBTableImpl aTable = (FlatfileDBTableImpl) obj;
0364: String aTableName = aTable.getName();
0365: // DatabaseModel aTableParent = aTable.getParent();
0366: Map aTableColumns = aTable.getColumns();
0367:
0368: result = (aTableName != null && name != null && name
0369: .equals(aTableName));
0370: // && (parent != null && aTableParent != null && parent.equals(aTableParent));
0371:
0372: if (columns != null && aTableColumns != null) {
0373: Set objCols = aTableColumns.keySet();
0374: Set myCols = columns.keySet();
0375:
0376: // Must be identical (no subsetting), hence the pair of tests.
0377: result &= myCols.containsAll(objCols)
0378: && objCols.containsAll(myCols);
0379: } else if (!(columns == null && aTableColumns == null)) {
0380: result = false;
0381: }
0382: response &= (encoding != null) ? encoding
0383: .equals(aTable.encoding)
0384: : (aTable.encoding == null);
0385: response &= (fileName != null) ? fileName
0386: .equals(aTable.fileName)
0387: : (aTable.fileName == null);
0388:
0389: }
0390:
0391: return result & response;
0392: }
0393:
0394: /**
0395: * @see org.netbeans.modules.model.database.DBTable#getCatalog
0396: */
0397: @Override
0398: public String getCatalog() {
0399: return "";
0400: }
0401:
0402: /**
0403: * Gets the Create Statement SQL for creating table for a flat file
0404: *
0405: * @return SQL for this Flatfile with getTableName()
0406: */
0407: public String getCreateStatementSQL() {
0408: return getCreateStatementSQL(this ) + getFlatfilePropertiesSQL();
0409: }
0410:
0411: /**
0412: * Gets the SQL create statement to create a text table representing this flatfile.
0413: *
0414: * @param table to use in synthesizing the create statement; if null,
0415: * the current table name yielded by getName() will be used
0416: * @return SQL statement to create a text table representing the contents of this
0417: * flatfile
0418: */
0419: public String getCreateStatementSQL(SQLDBTable table) {
0420: String tableName = table.getName();
0421: List<String> pkList = new ArrayList<String>();
0422: Iterator it = table.getColumns().values().iterator();
0423: StringBuilder buffer = new StringBuilder(100);
0424: buffer.append("CREATE EXTERNAL TABLE IF NOT EXISTS \"").append(
0425: tableName).append("\" (");
0426: // NOI18N
0427: int i = 0;
0428: while (it.hasNext()) {
0429: FlatfileDBColumn colDef = (FlatfileDBColumn) it.next();
0430: if (i++ != 0) {
0431: buffer.append(", ");
0432: }
0433: buffer.append(colDef.getCreateStatementSQL());
0434: if (colDef.isPrimaryKey()) {
0435: pkList.add(colDef.getName());
0436: }
0437: }
0438: if (pkList.size() > 0) {
0439: StringBuilder pkbuffer = new StringBuilder(20);
0440: pkbuffer.append(", PRIMARY KEY( ");
0441: it = pkList.iterator();
0442: int j = 0;
0443: while (it.hasNext()) {
0444: if (j++ != 0) {
0445: buffer.append(", ");
0446: }
0447: pkbuffer.append((String) it.next());
0448: }
0449: pkbuffer.append(") ");
0450: buffer.append(pkbuffer.toString());
0451: }
0452:
0453: buffer.append(")");
0454: return buffer.toString();
0455: }
0456:
0457: /**
0458: * Gets the SQL create statement to create a text table representing this flatfile.
0459: *
0460: * @param table to use in synthesizing the create statement; if null,
0461: * the current table name yielded by getName() will be used
0462: * @return SQL statement to create a text table representing the contents of this
0463: * flatfile
0464: */
0465: public static String getCreateStatementSQL(SQLDBTable table,
0466: String generatedName) {
0467: String tableName = table.getName();
0468: List<String> pkList = new ArrayList<String>();
0469: Iterator it = table.getColumns().values().iterator();
0470: StringBuilder buffer = new StringBuilder(100);
0471: buffer.append("CREATE EXTERNAL TABLE \"").append(generatedName)
0472: .append("\" (");
0473: // NOI18N
0474: int i = 0;
0475: while (it.hasNext()) {
0476: FlatfileDBColumn colDef = (FlatfileDBColumn) it.next();
0477: if (i++ != 0) {
0478: buffer.append(", ");
0479: }
0480: buffer.append(colDef.getCreateStatementSQL());
0481: if (colDef.isPrimaryKey()) {
0482: pkList.add(colDef.getName());
0483: }
0484: }
0485: if (pkList.size() > 0) {
0486: StringBuilder pkbuffer = new StringBuilder(20);
0487: pkbuffer.append(", PRIMARY KEY( ");
0488: it = pkList.iterator();
0489: int j = 0;
0490: while (it.hasNext()) {
0491: if (j++ != 0) {
0492: buffer.append(", ");
0493: }
0494: pkbuffer.append((String) it.next());
0495: }
0496: pkbuffer.append(") ");
0497: buffer.append(pkbuffer.toString());
0498: }
0499:
0500: buffer.append(")");
0501: return buffer.toString();
0502: }
0503:
0504: /**
0505: * Gets the SQL create statement to create a text table representing this flatfile.
0506: *
0507: * @return SQL statement to create a text table representing the contents of this
0508: * flatfile
0509: */
0510: public String getCreateStatementSQL(String directory,
0511: String theTableName, String runtimeName,
0512: boolean isDynamicFilePath, boolean createDataFileIfNotExist) {
0513: String sql = null;
0514: try {
0515: if (runtimeName != null && runtimeName.trim().length() != 0) {
0516: setOrPutProperty(FlatfileDBTable.PROP_FILENAME, "$"
0517: + runtimeName);
0518: /**
0519: if (isDynamicFilePath) {
0520: setOrPutProperty(FlatfileDBTable.PROP_FILENAME, "$" + runtimeName);
0521: } else {
0522: // NOTE: DO NOT USE java.io.File to generate the file path,
0523: // as getCanonicalPath() is platform-centric and will hard-code
0524: // platform-specific root-drive info (e.g., "C:" for M$-Window$)
0525: // where it's inappropriate.
0526: setOrPutProperty(FlatfileDBTable.PROP_FILENAME, getFullFilePath(directory, "$" + runtimeName));
0527: }**/
0528: } else {
0529: setOrPutProperty(FlatfileDBTable.PROP_FILENAME,
0530: getFullFilePath(directory, fileName));
0531: }
0532:
0533: setOrPutProperty(FlatfileDBTable.PROP_CREATE_IF_NOT_EXIST,
0534: new Boolean(createDataFileIfNotExist));
0535: sql = this .getCreateStatementSQL(this , theTableName)
0536: + this .getFlatfilePropertiesSQL();
0537: } catch (Exception e) {
0538: mLogger.errorNoloc(mLoc.t(
0539: "PRSR061: Failed to set the file path.{0}",
0540: LOG_CATEGORY), e);
0541: }
0542: return sql;
0543: }
0544:
0545: public String getDropStatementSQL() {
0546: return getDropStatementSQL(this );
0547: }
0548:
0549: public static String getDropStatementSQL(String generatedTableName) {
0550: StringBuilder buffer = new StringBuilder(
0551: "DROP TABLE IF EXISTS \"");
0552: // NOI18N
0553: return buffer.append(generatedTableName).append("\"")
0554: .toString();
0555: }
0556:
0557: /**
0558: * Gets the SQL Drop statement to drop the text table representing this flatfile.
0559: *
0560: * @param table table to use in synthesizing the drop statement; if null,
0561: * uses the value yielded by getName()
0562: * @return SQLstatement to drop a text table representing the contents of this
0563: * flatfile
0564: */
0565: public static String getDropStatementSQL(SQLDBTable table) {
0566: String tableName = table.getName();
0567: StringBuilder buffer = new StringBuilder(
0568: "DROP TABLE IF EXISTS \"");
0569: // NOI18N
0570: return buffer.append(tableName).append("\"").toString();
0571: }
0572:
0573: /**
0574: * Gets the encoding scheme.
0575: *
0576: * @return encoding scheme
0577: */
0578: public String getEncodingScheme() {
0579: return encoding;
0580: }
0581:
0582: /**
0583: * Gets the file name.
0584: *
0585: * @return file name
0586: */
0587: public String getFileName() {
0588: return fileName;
0589: }
0590:
0591: public String getFlatfilePropertiesSQL() {
0592: StringBuilder buf = new StringBuilder(100);
0593:
0594: // Create local copy of Map whose elements can be removed without
0595: // affecting the master copy.
0596: Map localProps = new HashMap(properties);
0597:
0598: // Now emit key-value pairs in the localProps Map.
0599: Iterator iter = localProps.values().iterator();
0600: if (!iter.hasNext()) {
0601: return "";
0602: }
0603:
0604: buf.append(" " + PROPS_KEYWORD + " "); // NOI18N
0605: buf.append(START_PROPS_DELIMITER); // NOI18N
0606:
0607: int i = 0;
0608: while (iter.hasNext()) {
0609: Property aProp = (Property) iter.next();
0610:
0611: // Don't write out properties which are meant only for use inside the wizard.
0612: if (WIZARD_ONLY_PROPERTIES.contains(aProp.getName()
0613: .toUpperCase())
0614: || aProp.getName().toUpperCase().startsWith(
0615: FlatfileDBTable.PROP_WIZARD)) {
0616: continue;
0617: }
0618:
0619: if (parserType != null) {
0620: if (((!(parserType.equals(PropertyKeys.WEB) || parserType
0621: .equals(PropertyKeys.RSS))) && aProp.getName()
0622: .equals(PropertyKeys.URL))
0623: || (((parserType.equals(PropertyKeys.WEB) || parserType
0624: .equals(PropertyKeys.RSS))) && aProp
0625: .getName()
0626: .equals(PropertyKeys.FILENAME))) {
0627: continue;
0628: }
0629: }
0630:
0631: if (!aProp.isValid()) {
0632: if (aProp.isRequired()) {
0633: return ""; // Required property is invalid; fail.
0634: }
0635: mLogger
0636: .infoNoloc(mLoc
0637: .t(
0638: "PRSR062: Value for property {0}is invalid:{1}; skipping.",
0639: aProp.getName(), aProp
0640: .getValue()));
0641: continue; // Log and skip this parameter.
0642: }
0643:
0644: if (i++ != 0) {
0645: buf.append(PROP_SEPARATOR);
0646: }
0647:
0648: buf.append(aProp.getKeyValuePair());
0649: }
0650:
0651: buf.append(END_PROPS_DELIMITER); // NOI18N
0652:
0653: return buf.toString();
0654: }
0655:
0656: /**
0657: * Gets local path to sample file.
0658: *
0659: * @return path (in local workstation file system) to file, excluding the filename.
0660: */
0661: public String getLocalFilePath() {
0662: return localPath;
0663: }
0664:
0665: /**
0666: * Gets parse type, if any, associated with this flatfile. To set this type, call
0667: * setParseConfigurator with an appropriate ParseConfigurator instance from the
0668: * ParseConfiguratorFactory.
0669: *
0670: * @return String representing parse type, or null if none has been defined for this
0671: * flatfile.
0672: */
0673: public String getParserType() {
0674: return parserType;
0675: }
0676:
0677: public Map getProperties() {
0678: return (properties != null) ? properties
0679: : Collections.EMPTY_MAP;
0680: }
0681:
0682: /**
0683: * Gets property string associated with the given name.
0684: *
0685: * @param key property key
0686: * @return property associated with propName, or null if no such property exists.
0687: */
0688: public String getProperty(String key) {
0689: Property aProp = (Property) properties.get(key);
0690: return (aProp != null) ? (aProp.getValue() != null) ? aProp
0691: .getValue().toString() : null : null;
0692: }
0693:
0694: /**
0695: * @see org.netbeans.modules.model.database.DBTable#getSchema
0696: */
0697: @Override
0698: public String getSchema() {
0699: return "";
0700: }
0701:
0702: /**
0703: * Gets the SQL select statement to retrieve a result set displaying this file's
0704: * contents, using the given value as a limit to the number of rows returned.
0705: *
0706: * @param rowCount number of rows to display; 0 returns all available rows
0707: * @return SQL statement to select the contents of this file in the column order
0708: * specified by this instance's FlatfileFields.
0709: */
0710: public String getSelectStatementSQL(int rows) {
0711: if (rows < 0) {
0712: throw new IllegalArgumentException(
0713: "Must supply non-negative int value for parameter rows.");
0714: }
0715:
0716: StringBuilder buffer = new StringBuilder(100);
0717: buffer.append("SELECT ");
0718:
0719: Iterator it = getColumnList().iterator();
0720: int i = 0;
0721: while (it.hasNext()) {
0722: FlatfileDBColumn colDef = (FlatfileDBColumn) it.next();
0723: if (i++ != 0) {
0724: buffer.append(", ");
0725: }
0726:
0727: buffer.append("\"").append(colDef.getName()).append("\"");
0728: }
0729:
0730: buffer.append(" FROM ").append("\"").append(getTableName())
0731: .append("\"");
0732:
0733: if (rows > 0) {
0734: buffer.append(" LIMIT ").append(rows);
0735: }
0736:
0737: return buffer.toString();
0738: }
0739:
0740: /**
0741: * Gets the table name.
0742: *
0743: * @return Table name
0744: */
0745: public String getTableName() {
0746: return this .getName();
0747: }
0748:
0749: /**
0750: * Overrides default implementation to compute hashCode value for those members used
0751: * in equals() for comparison.
0752: *
0753: * @return hash code for this object
0754: * @see java.lang.Object#hashCode
0755: */
0756: @Override
0757: public int hashCode() {
0758: int myHash = (name != null) ? name.hashCode() : 0;
0759: // myHash += (parent != null) ? parent.hashCode() : 0;
0760:
0761: // Include hashCodes of all column names.
0762: if (columns != null) {
0763: myHash += columns.keySet().hashCode();
0764: }
0765: myHash += (encoding != null) ? encoding.hashCode() : 0;
0766: myHash += (fileName != null) ? fileName.hashCode() : 0;
0767:
0768: return myHash;
0769: }
0770:
0771: @Override
0772: public void parseXML(Element xmlElement) throws BaseException {
0773: // In order to be compliant with lagacy JIBX generated XML, following structure
0774: // needs to be adhered to.
0775: // <pre>
0776: // <FlatfileTable name="PQ_EMPLOYEE_CSV" encoding="US-ASCII ....
0777: // <map size="11">
0778: // <entry key="LNAME">
0779: // <FlatfileColumn name="LNAME" fieldName="LNAME" .../>
0780: // </entry>
0781: // </map>
0782: // <map size="8">
0783: // <entry key="LOADTYPE">Delimited</entry>
0784: // <entry key="ROWSTOSKIP">0</entry> ....
0785: // </map>
0786: // </FlatfileTable>
0787: // </pre>
0788: Map attrs = TagParserUtility.getNodeAttributes(xmlElement);
0789: this .name = (String) attrs.get(ATTR_NAME);
0790: this .encoding = (String) attrs.get(ATTR_ENCODING);
0791: this .fileName = (String) attrs.get(ATTR_FILE_NAME);
0792:
0793: // Get child "map" elements.
0794: NodeList childNodes = xmlElement.getElementsByTagName("map");
0795: parseColumns((Element) (childNodes.item(0)));
0796: parseProperties((Element) (childNodes.item(1)));
0797: upgradeProperties();
0798: setPK();
0799: }
0800:
0801: /**
0802: *Set defaults for any new property added in the UI property sheet
0803: *for flatfile db creation
0804: **/
0805: private void upgradeProperties() {
0806: if (!properties.containsKey(PropertyKeys.TRIMWHITESPACE)) {
0807: setOrPutProperty(PropertyKeys.TRIMWHITESPACE, "true");
0808: }
0809: }
0810:
0811: /**
0812: * Sets the encoding scheme.
0813: *
0814: * @param newEncoding encoding scheme
0815: */
0816: public void setEncodingScheme(String newEncoding) {
0817: encoding = newEncoding;
0818: }
0819:
0820: /**
0821: * Sets the file name.
0822: *
0823: * @param newName new file name
0824: */
0825: public void setFileName(String newName) {
0826: fileName = newName;
0827: setOrPutProperty(PropertyKeys.FILENAME, newName);
0828: }
0829:
0830: /**
0831: * Sets local path to sample file.
0832: *
0833: * @param localFile File representing path to sample file. If localFile represents the
0834: * file itself, only the directory path will be stored.
0835: */
0836: public void setLocalFilePath(File localFile) {
0837: localPath = (localFile.isFile()) ? localFile.getParentFile()
0838: .getAbsolutePath() : localFile.getAbsolutePath();
0839: }
0840:
0841: public void setOrPutProperty(String key, Object value) {
0842: if (value != null && !setProperty(key, value)) {
0843: Property prop = new Property(key, value.getClass(), true);
0844: prop.setValue(value);
0845: properties.put(key, prop);
0846: }
0847: }
0848:
0849: /**
0850: * Sets MutableParseConfigurator instance associated with this flatfile.
0851: *
0852: * @param newConfig new MutableParseConfigurator to associate
0853: */
0854: public void setParseType(String type) {
0855: parserType = type;
0856: setOrPutProperty(PropertyKeys.LOADTYPE, type);
0857: }
0858:
0859: public void setProperties(Map newProps) {
0860: if (newProps != null) {
0861: properties = newProps;
0862: }
0863: }
0864:
0865: /**
0866: * Sets the property associated with the given String key to the given value.
0867: *
0868: * @param key key whose associated value is sought
0869: * @param value to associate with key
0870: */
0871: public boolean setProperty(String key, Object value) {
0872: Property aProp = (Property) properties.get(key);
0873: if (aProp != null && key.equals(aProp.getName())) {
0874: aProp.setValue(value);
0875: return true;
0876: }
0877: return false;
0878: }
0879:
0880: /**
0881: * Overrides default implementation to return fully-qualified name of this DBTable
0882: * (including name of parent DatabaseModel).
0883: *
0884: * @return table name.
0885: */
0886: @Override
0887: public String toString() {
0888: StringBuilder buf = new StringBuilder(50);
0889:
0890: if (parentDBModel != null) {
0891: buf.append(parentDBModel.getModelName());
0892: buf.append(":");
0893: buf.append(parentDBModel.getFullyQualifiedTableName(this ));
0894: } else {
0895: buf.append(getName());
0896: }
0897:
0898: return buf.toString();
0899: }
0900:
0901: /**
0902: * Marshall this object to XML string.
0903: *
0904: * @param prefix
0905: * @return XML string
0906: */
0907: @Override
0908: public String toXMLString(String prefix) throws BaseException {
0909: StringBuilder sb = new StringBuilder();
0910: if (prefix == null) {
0911: prefix = "";
0912: }
0913:
0914: sb.append(prefix);
0915: sb.append("<");
0916: sb.append(TAG_STCDB_TABLE);
0917: sb.append(getAttributeNameValues());
0918: sb.append(">\n");
0919: sb.append(getXMLColumnMap(prefix + TAB));
0920: sb.append(getXMLTableProperties(prefix + TAB));
0921: sb.append(prefix);
0922: sb.append("</");
0923: sb.append(TAG_STCDB_TABLE);
0924: sb.append(">\n");
0925:
0926: return sb.toString();
0927: }
0928:
0929: public void updateProperties(Map newProps) {
0930: if (newProps != null) {
0931: Iterator iter = newProps.keySet().iterator();
0932: while (iter.hasNext()) {
0933: String key = (String) iter.next();
0934: Object value = newProps.get(key);
0935: setOrPutProperty(key, value);
0936: }
0937: }
0938: }
0939:
0940: // use for test purpose only
0941: void setTableDefinition(Map props) {
0942: this .properties = props;
0943: }
0944:
0945: /**
0946: * Perform deep copy of columns.
0947: *
0948: * @param source ETLTable whose columns are to be copied.
0949: */
0950: @Override
0951: protected void deepCopyReferences(DBTable source) {
0952: if (source != null && source != this ) {
0953: columns.clear();
0954: Iterator iter = source.getColumnList().iterator();
0955:
0956: // Must do deep copy to ensure correct parent-child relationship.
0957: while (iter.hasNext()) {
0958: addColumn(new FlatfileDBColumnImpl((DBColumn) iter
0959: .next()));
0960: }
0961: }
0962: }
0963:
0964: protected void parseColumns(Element mapNode) throws BaseException {
0965: NodeList entryNodeList = mapNode.getElementsByTagName("entry");
0966: NodeList columnNodeList = null;
0967: Element entry = null;
0968: Element columnElement = null;
0969: String key = null;
0970: FlatfileDBColumn column = null;
0971:
0972: int length = entryNodeList.getLength();
0973: for (int i = 0; i < length; i++) {
0974: entry = (Element) entryNodeList.item(i);
0975: key = TagParserUtility.getNodeAttributeValue(entry, "key");
0976: column = new FlatfileDBColumnImpl();
0977: columnNodeList = entry
0978: .getElementsByTagName(TAG_STCDB_COLUMN);
0979: columnElement = (Element) columnNodeList.item(0);
0980: column.setParent(this );
0981: column.parseXML(columnElement);
0982: columns.put(key, column);
0983: }
0984: }
0985:
0986: protected void parseProperties(Element mapNode) {
0987: // <map size="8">
0988: // <entry key="LOADTYPE">Delimited</entry>
0989: // <entry key="ROWSTOSKIP">0</entry> ...
0990: // </map>
0991: NodeList entryNodeList = mapNode.getElementsByTagName("entry");
0992: Element entry = null;
0993: String key = null;
0994: String value = null;
0995:
0996: int length = entryNodeList.getLength();
0997: for (int i = 0; i < length; i++) {
0998: entry = (Element) entryNodeList.item(i);
0999: key = TagParserUtility.getNodeAttributeValue(entry, "key");
1000: Node node = entry.getChildNodes().item(0);
1001: value = (node != null) ? node.getNodeValue() : "";
1002: this .setOrPutProperty(key, StringUtil
1003: .unescapeControlChars(value));
1004: }
1005: }
1006:
1007: private String getAttributeNameValues() {
1008: StringBuilder sb = new StringBuilder(" ");
1009: sb.append(ATTR_NAME);
1010: sb.append(EQUAL_START_QUOTE);
1011: sb.append(this .name);
1012: sb.append(END_QUOTE_SPACE);
1013:
1014: sb.append(ATTR_ENCODING);
1015: sb.append(EQUAL_START_QUOTE);
1016: sb.append(this .encoding);
1017: sb.append(END_QUOTE_SPACE);
1018:
1019: sb.append(ATTR_FILE_NAME);
1020: sb.append(EQUAL_START_QUOTE);
1021: sb.append(this .fileName);
1022: sb.append(END_QUOTE_SPACE);
1023:
1024: sb.append(ATTR_PARENT);
1025: sb.append(EQUAL_START_QUOTE);
1026: sb.append(this .parentDBModel.getModelName());
1027: sb.append("\"");
1028: return sb.toString();
1029: }
1030:
1031: /**
1032: * @param directory
1033: * @param runtimeName
1034: * @return
1035: */
1036: private String getFullFilePath(String directory, String filename) {
1037: StringBuilder fullpath = new StringBuilder(50);
1038: fullpath.append((StringUtil.isNullString(directory)) ? ""
1039: : directory);
1040:
1041: char separator = '/';
1042: if (directory.indexOf('\\') != -1) {
1043: separator = '\\';
1044: }
1045:
1046: // Append a separator to the end of full path if directory doesn't
1047: // already end with it.
1048: if (!directory.endsWith(Character.toString(separator))) {
1049: fullpath.append(separator);
1050: }
1051: fullpath.append(filename);
1052:
1053: return fullpath.toString().trim();
1054: }
1055:
1056: private String getXMLColumnMap(String prefix) throws BaseException {
1057: StringBuilder sb = new StringBuilder(prefix);
1058: sb.append("<map size=\"");
1059: sb.append(this .columns.size());
1060: sb.append("\">\n");
1061: sb.append(getXMLColumnMapEntries(prefix + TAB));
1062: sb.append(prefix);
1063: sb.append("</map>\n");
1064: return sb.toString();
1065: }
1066:
1067: private String getXMLColumnMapEntries(String prefix)
1068: throws BaseException {
1069: StringBuilder sb = new StringBuilder();
1070: FlatfileDBColumn column = null;
1071: if ((this .columns != null) && (this .columns.size() > 0)) {
1072: Iterator itr = columns.keySet().iterator();
1073: String key = null;
1074: while (itr.hasNext()) {
1075: key = (String) itr.next();
1076: column = (FlatfileDBColumn) columns.get(key);
1077: sb.append(prefix);
1078: sb.append("<entry key=\"");
1079: sb.append(key);
1080: sb.append("\">\n");
1081: sb.append(column.toXMLString(prefix + TAB));
1082: sb.append(prefix);
1083: sb.append("</entry>\n");
1084: }
1085: }
1086:
1087: return sb.toString();
1088: }
1089:
1090: private String getXMLTableProperties(String prefix) {
1091: StringBuilder sb = new StringBuilder();
1092: sb.append(prefix);
1093: sb.append("<map size=\"");
1094: if ((this .properties != null) && (this .properties.size() > 0)) {
1095: sb.append(this .properties.size());
1096: sb.append("\">\n");
1097:
1098: Iterator itr = properties.keySet().iterator();
1099: String key = null;
1100: String val = null;
1101: String entryPrefix = prefix + TAB;
1102: while (itr.hasNext()) {
1103: key = (String) itr.next();
1104: val = getProperty(key);
1105: sb.append(entryPrefix);
1106: sb.append("<entry key=\"");
1107: sb.append(key);
1108: sb.append("\">");
1109: sb.append(StringUtil.escapeControlChars(val));
1110: sb.append("</entry>\n");
1111: }
1112: } else {
1113: sb.append("0\">\n");
1114: }
1115:
1116: sb.append(prefix);
1117: sb.append("</map>\n");
1118:
1119: return sb.toString();
1120: }
1121:
1122: private void setPK() {
1123: List pkList = new ArrayList();
1124: SortedSet fields = new TreeSet(this .columns.values());
1125: Iterator it = fields.iterator();
1126: FlatfileDBColumn colDef = null;
1127:
1128: while (it.hasNext()) {
1129: colDef = (FlatfileDBColumn) it.next();
1130: if (colDef.isPrimaryKey()) {
1131: pkList.add(colDef.getName());
1132: }
1133: }
1134:
1135: if (pkList.size() > 0) {
1136: this .primaryKey = new PrimaryKeyImpl("pk" + this .name,
1137: pkList);
1138: }
1139: }
1140:
1141: @Override
1142: public String toXMLString(String prefix, boolean tableOnly)
1143: throws BaseException {
1144: return toXMLString(prefix, true);
1145: }
1146:
1147: @Override
1148: protected String getElementTagName() {
1149: throw new UnsupportedOperationException("Not supported yet.");
1150: }
1151:
1152: protected void parseChildren(NodeList childNodeList)
1153: throws BaseException {
1154: throw new UnsupportedOperationException("Not supported yet.");
1155: }
1156: }
|