001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.mashup.db.model.impl;
042:
043: import java.sql.Types;
044: import java.util.Map;
045: import org.netbeans.modules.mashup.db.common.SQLUtils;
046: import org.netbeans.modules.mashup.db.model.FlatfileDBColumn;
047: import org.netbeans.modules.mashup.db.model.FlatfileDBTable;
048: import org.netbeans.modules.sql.framework.model.DBColumn;
049: import org.netbeans.modules.sql.framework.common.utils.TagParserUtility;
050: import org.w3c.dom.Element;
051: import net.java.hulp.i18n.Logger;
052: import com.sun.sql.framework.utils.StringUtil;
053: import org.netbeans.modules.etl.logger.Localizer;
054: import org.netbeans.modules.etl.logger.LogUtil;
055: import org.netbeans.modules.sql.framework.model.impl.AbstractDBColumn;
056:
057: /**
058: * Implements FlatfileDBColumn interface.
059: *
060: * @author Jonathan Giron
061: * @author Girish Patil
062: * @author Ahimanikya Satapathy
063: * @version $Revision$
064: */
065: public class FlatfileDBColumnImpl extends AbstractDBColumn implements
066: FlatfileDBColumn, Cloneable, Comparable {
067:
068: /** Constants used in XML tags * */
069: private static final String ATTR_CARDINAL_POSITION = "cardinalPosition";
070: private static final String ATTR_INDEXED = "indexed";
071: private static final String ATTR_IS_FOREIGN_KEY = "isForeignKey";
072: private static final String ATTR_IS_PRIMARY_KEY = "isPrimaryKey";
073: private static final String ATTR_JDBC_TYPE = "jdbcType";
074: private static final String ATTR_NAME = "name";
075: private static final String ATTR_NULLABLE = "nullable";
076: private static final String ATTR_PARENT = "parent";
077: private static final String ATTR_PRECISION = "precision";
078: private static final String ATTR_SCALE = "scale";
079: private static final String END_QUOTE_SPACE = "\" ";
080: private static final String EQUAL_START_QUOTE = "=\"";
081: private static final String LOG_CATEGORY = FlatfileDBColumnImpl.class
082: .getName();
083: private static final String QUOTE = "\"";
084: private static final String TAG_STCDB_COLUMN = "stcdbColumn";
085: /* Cardinal Position */
086: protected int cardinalPosition;
087: private boolean isSelected; // specifies if the column is selected
088: private static transient final Logger mLogger = LogUtil
089: .getLogger(FlatfileDBColumnImpl.class.getName());
090: private static transient final Localizer mLoc = Localizer.get();
091:
092: public FlatfileDBColumnImpl() {
093: super ();
094: }
095:
096: /**
097: * Creates a new instance of FlatfileDBColumnImpl, cloning the contents of the given
098: * DBColumn implementation instance.
099: *
100: * @param src DBColumn instance to be cloned
101: */
102: public FlatfileDBColumnImpl(DBColumn src) {
103: this ();
104: if (src == null) {
105: throw new IllegalArgumentException(
106: "Must supply non-null DBColumn instance for src.");
107: }
108:
109: copyFrom(src);
110: }
111:
112: /**
113: * Constructs a new instance of FlatfileDBColumnImpl using the given parameters and
114: * assuming that the column is not part of a foreign key or primary key, and that it
115: * accepts null values.
116: *
117: * @param colName name of this column
118: * @param sqlJdbcType JDBC type of this column
119: * @param colScale scale of this column
120: * @param colPrecision precision of this column
121: * @param isNullable true if nullable, false otherwise
122: * @see java.sql.Types
123: */
124: public FlatfileDBColumnImpl(String colName, int sqlJdbcType,
125: int colPrecision, int colScale, boolean isNullable) {
126: super (colName, sqlJdbcType, colScale, colPrecision, isNullable);
127: }
128:
129: /**
130: * Constructs a new instance of FlatfileDBColumnImpl using the given parameters.
131: *
132: * @param colName name of this column
133: * @param sqlJdbcType JDBC type of this column
134: * @param colScale scale of this column
135: * @param colPrecision precision of this column
136: * @param isPrimaryKey true if part of a primary key, false otherwise
137: * @param isForeignKey true if part of a foreign key, false otherwise
138: * @param isIndexed true if indexed, false otherwise
139: * @param isNullable true if nullable, false otherwise
140: * @see java.sql.Types
141: */
142: public FlatfileDBColumnImpl(String colName, int sqlJdbcType,
143: int colScale, int colPrecision, boolean isPrimaryKey,
144: boolean isForeignKey, boolean isIndexed, boolean isNullable) {
145: super (colName, sqlJdbcType, colScale, colPrecision,
146: isPrimaryKey, isForeignKey, isIndexed, isNullable);
147: }
148:
149: /**
150: * Clone a deep copy of DBColumn.
151: *
152: * @return a copy of DBColumn.
153: */
154: @Override
155: public Object clone() {
156: try {
157: FlatfileDBColumn column = (FlatfileDBColumn) super .clone();
158:
159: return column;
160: } catch (CloneNotSupportedException e) {
161: throw new InternalError(e.toString());
162: }
163: }
164:
165: /**
166: * Compares DBColumn with another object for lexicographical ordering. Null objects
167: * and those DBColumns with null names are placed at the end of any ordered collection
168: * using this method.
169: *
170: * @param refObj Object to be compared.
171: * @return -1 if this column is before refObj 0 if this column and refObj are in the
172: * same position. 1 if this column name is after refObj
173: * @throws ClassCastException if refObj is not comparable to FlatfileDBColumnImpl
174: */
175: @Override
176: public int compareTo(Object refObj) {
177: if (null == refObj) {
178: return -1;
179: } else if (this == refObj) {
180: return 0;
181: }
182:
183: FlatfileDBColumnImpl col = (FlatfileDBColumnImpl) refObj;
184: return cardinalPosition - col.cardinalPosition;
185: }
186:
187: /**
188: * Sets the various member variables and collections using the given DBColumn instance
189: * as a source object.
190: *
191: * @param source DBColumn from which to obtain values for member variables and
192: * collections
193: */
194: @Override
195: public void copyFrom(DBColumn source) {
196: name = source.getName();
197: jdbcType = source.getJdbcType();
198:
199: scale = source.getScale();
200: precision = source.getPrecision();
201:
202: pkFlag = source.isPrimaryKey();
203: fkFlag = source.isForeignKey();
204: indexed = source.isIndexed();
205: nullable = source.isNullable();
206:
207: cardinalPosition = source.getOrdinalPosition();
208: defaultValue = source.getDefaultValue();
209:
210: try {
211: parent = (FlatfileDBTable) source.getParent();
212: } catch (RuntimeException e) {
213: // TODO log this
214: }
215: }
216:
217: /**
218: * Gets debug output as a String, using the given String as a prefix for each output
219: * line.
220: *
221: * @param prefix String to prepend to each new line of debug output
222: * @return debug output
223: */
224: public String debugOutput(String prefix) {
225: StringBuilder out = new StringBuilder(100);
226:
227: out.append(prefix).append("Column name: " + getName() + "\n");
228: out.append(prefix).append(
229: "Position: " + getOrdinalPosition() + "\n");
230: out.append(prefix).append("JDBC type: " + getJdbcType() + "\n");
231: out.append(prefix).append(
232: "Precision/width: " + getPrecision() + "\n");
233: out.append(prefix).append("Scale: " + getScale() + "\n");
234: out.append(prefix).append("Nullable? " + isNullable() + "\n");
235: out.append(prefix).append("Indexed? " + isIndexed() + "\n");
236: out.append(prefix).append("Selected? " + isSelected() + "\n");
237:
238: return out.toString();
239: }
240:
241: /**
242: * Overrides default implementation to return value based on memberwise comparison.
243: *
244: * @param refObj Object against which we compare this instance
245: * @return true if refObj is functionally identical to this instance; false otherwise
246: */
247: @Override
248: public boolean equals(Object refObj) {
249: if (this == refObj) {
250: return true;
251: }
252:
253: if (!(refObj instanceof FlatfileDBColumn)) {
254: return false;
255: }
256:
257: FlatfileDBColumnImpl refMeta = (FlatfileDBColumnImpl) refObj;
258: boolean result = (name != null) ? name.equals(refMeta.name)
259: : (refMeta.name == null);
260: result &= (jdbcType == refMeta.jdbcType)
261: && (pkFlag == refMeta.pkFlag)
262: && (fkFlag == refMeta.fkFlag)
263: && (indexed == refMeta.indexed)
264: && (nullable == refMeta.nullable)
265: && (getScale() == refMeta.getScale())
266: && (precision == refMeta.precision);
267: result &= (parent != null) ? parent.equals(refMeta.parent)
268: : (refMeta.parent == null);
269: return result;
270: }
271:
272: public int getCardinalPosition() {
273: return this .cardinalPosition;
274: }
275:
276: /**
277: * Gets the SQL create statement to create a column representing this flatfile field.
278: *
279: * @return SQL statement fragment to create of a column representing this field
280: */
281: public String getCreateStatementSQL() {
282: // Default value if jdbcType is unrecognized.
283: int sqlTypeCode = java.sql.Types.VARCHAR;
284:
285: if (SQLUtils.isStdJdbcType(this .jdbcType)) {
286: // Map existing integer and float datatypes to numeric
287: // because AxionDB does not support precision or scale
288: // specifications for those datatypes.
289: switch (jdbcType) {
290: case java.sql.Types.FLOAT:
291: case java.sql.Types.INTEGER:
292: sqlTypeCode = Types.NUMERIC;
293: break;
294: case java.sql.Types.CHAR:
295: sqlTypeCode = Types.VARCHAR;
296: break;
297: default:
298: sqlTypeCode = this .jdbcType;
299: break;
300: }
301: }
302:
303: StringBuilder buffer = new StringBuilder(100);
304: buffer.append("\"").append(this .name).append(END_QUOTE_SPACE);
305: buffer.append(SQLUtils.getStdSqlType(sqlTypeCode));
306:
307: if (this .precision > 0) {
308: switch (sqlTypeCode) {
309: case java.sql.Types.VARCHAR:
310: buffer.append("(").append(this .precision).append(")");
311: break;
312: case java.sql.Types.NUMERIC:
313: int extraLen = ((getScale() == 0) ? 0 : 1) + 1;
314: buffer.append("(").append(this .precision - extraLen);
315: if (getScale() > 0) {
316: buffer.append(", ").append(getScale());
317: }
318: buffer.append(")");
319: break;
320: case java.sql.Types.DATE:
321: case java.sql.Types.TIME:
322: case java.sql.Types.TIMESTAMP:
323: buffer.append("(").append(this .precision).append(")");
324: break;
325: default:
326: // Append nothing.
327: break;
328: }
329: }
330:
331: if (defaultValue != null) {
332: buffer.append(" DEFAULT ");
333: switch (sqlTypeCode) {
334: case java.sql.Types.VARCHAR:
335: case java.sql.Types.DATE:
336: case java.sql.Types.TIME:
337: case java.sql.Types.TIMESTAMP:
338: buffer.append("'").append(defaultValue).append("'");
339: break;
340: default:
341: if (!StringUtil.isNullString(defaultValue)) {
342: buffer.append(defaultValue);
343: }
344: break;
345: }
346: }
347:
348: if (!isNullable() && !isPrimaryKey()) {
349: buffer.append(" NOT NULL");
350: }
351:
352: return buffer.toString();
353: }
354:
355: /**
356: * Gets Map of current properties associated with this field.
357: *
358: * @return unmodifiable Map of current properties.
359: */
360: public Map getProperties() {
361: return ((FlatfileDBTable) this .getParent()).getProperties();
362: }
363:
364: /**
365: * Gets property string associated with the given name.
366: *
367: * @param propName property key
368: * @return property associated with propName, or null if no such property exists.
369: */
370: public String getProperty(String propName) {
371: return ((FlatfileDBTable) this .getParent())
372: .getProperty(propName);
373: }
374:
375: /**
376: * @see org.netbeans.modules.model.database.DBColumn#getScale
377: */
378: @Override
379: public int getScale() {
380: switch (jdbcType) {
381: case Types.NUMERIC:
382: return scale;
383: default:
384: return 0;
385: }
386: }
387:
388: /**
389: * Returns the hashCode for this object.
390: *
391: * @return the hashCode of this object.
392: */
393: @Override
394: public int hashCode() {
395: int myHash = (name != null) ? name.hashCode() : 0;
396: myHash += jdbcType + (10 * getScale()) + (100 * precision);
397:
398: myHash += pkFlag ? 1 : 0;
399: myHash += fkFlag ? 2 : 0;
400: myHash += indexed ? 4 : 0;
401: myHash += nullable ? 8 : 0;
402:
403: myHash += (parent != null) ? parent.hashCode() : 0;
404:
405: return myHash;
406: }
407:
408: /**
409: * Indicates whether column is selected
410: *
411: * @return true if selected, false otherwise
412: */
413: public boolean isSelected() {
414: return isSelected;
415: }
416:
417: @Override
418: public void parseXML(Element xmlElement) {
419: Map attrs = TagParserUtility.getNodeAttributes(xmlElement);
420: String str = null;
421:
422: this .name = (String) attrs.get(ATTR_NAME);
423: str = (String) attrs.get(ATTR_JDBC_TYPE);
424:
425: if (str != null) {
426: try {
427: this .jdbcType = Integer.parseInt(str);
428: } catch (Exception ex) {
429: mLogger.errorNoloc(mLoc.t("PRSR053: LOG_CATEGORY {0}",
430: ATTR_JDBC_TYPE), ex);
431: }
432: }
433:
434: str = (String) attrs.get(ATTR_SCALE);
435: if (str != null) {
436: try {
437: this .scale = Integer.parseInt(str);
438: } catch (Exception ex) {
439: mLogger.errorNoloc(mLoc.t("PRSR054: LOG_CATEGORY {0}",
440: ATTR_SCALE), ex);
441: }
442: }
443:
444: str = (String) attrs.get(ATTR_PRECISION);
445: if (str != null) {
446: try {
447: this .precision = Integer.parseInt(str);
448: } catch (Exception ex) {
449: mLogger.errorNoloc(mLoc.t("PRSR055: LOG_CATEGORY {0}",
450: ATTR_PRECISION), ex);
451: }
452: }
453:
454: str = (String) attrs.get(ATTR_CARDINAL_POSITION);
455: if (str != null) {
456: try {
457: this .cardinalPosition = Integer.parseInt(str);
458: } catch (Exception ex) {
459: mLogger.errorNoloc(mLoc.t("PRSR056: LOG_CATEGORY {0}",
460: ATTR_CARDINAL_POSITION), ex);
461: }
462: }
463:
464: str = (String) attrs.get(ATTR_IS_PRIMARY_KEY);
465: if (str != null) {
466: try {
467: this .pkFlag = Boolean.valueOf(str).booleanValue();
468: } catch (Exception ex) {
469: mLogger.errorNoloc(mLoc.t("PRSR057: LOG_CATEGORY {0}",
470: ATTR_IS_PRIMARY_KEY), ex);
471: }
472: }
473:
474: str = (String) attrs.get(ATTR_IS_FOREIGN_KEY);
475: if (str != null) {
476: try {
477: this .fkFlag = Boolean.valueOf(str).booleanValue();
478: } catch (Exception ex) {
479: mLogger.errorNoloc(mLoc.t("PRSR058: LOG_CATEGORY {0}",
480: ATTR_IS_FOREIGN_KEY), ex);
481: }
482: }
483:
484: str = (String) attrs.get(ATTR_INDEXED);
485: if (str != null) {
486: try {
487: this .indexed = Boolean.valueOf(str).booleanValue();
488: } catch (Exception ex) {
489: mLogger.errorNoloc(mLoc.t("PRSR059: LOG_CATEGORY {0}",
490: ATTR_INDEXED), ex);
491: }
492: }
493:
494: str = (String) attrs.get(ATTR_NULLABLE);
495: if (str != null) {
496: try {
497: this .nullable = Boolean.valueOf(str).booleanValue();
498: } catch (Exception ex) {
499: mLogger.errorNoloc(mLoc.t("PRSR060: LOG_CATEGORY {0}",
500: ATTR_NULLABLE), ex);
501: }
502: }
503: }
504:
505: public void setCardinalPosition(int theCardinalPosition) {
506: this .cardinalPosition = theCardinalPosition;
507: }
508:
509: /**
510: * Sets SQL type code.
511: *
512: * @param newCode SQL code
513: * @throws FlatfileDBException if newCode is not a recognized SQL type code
514: */
515: @Override
516: public void setJdbcType(int newType) {
517: if (SQLUtils.isStdJdbcType(newType)) {
518: jdbcType = newType;
519: } else {
520: // Map legacy JDBC types to values which are acceptable to current
521: // Axion implementation.
522: switch (newType) {
523: case java.sql.Types.FLOAT:
524: case java.sql.Types.INTEGER:
525: jdbcType = java.sql.Types.NUMERIC;
526: break;
527: case java.sql.Types.CHAR:
528: jdbcType = java.sql.Types.VARCHAR;
529: break;
530: case java.sql.Types.DATE:
531: jdbcType = java.sql.Types.TIMESTAMP;
532: break;
533: default:
534: jdbcType = newType;
535: }
536: }
537: }
538:
539: /**
540: * Marshall this object to XML string.
541: *
542: * @param prefix
543: * @return XML string
544: */
545: public String toXMLString(String prefix) {
546: StringBuilder sb = new StringBuilder();
547: sb.append(prefix);
548: sb.append("<");
549: sb.append(TAG_STCDB_COLUMN);
550: sb.append(getAttributeNameValues());
551: sb.append("/>\n");
552: return sb.toString();
553: }
554:
555: private String getAttributeNameValues() {
556: StringBuilder sb = new StringBuilder(" ");
557: sb.append(ATTR_NAME);
558: sb.append(EQUAL_START_QUOTE);
559: sb.append(this .name);
560: sb.append(END_QUOTE_SPACE);
561:
562: sb.append(ATTR_JDBC_TYPE);
563: sb.append(EQUAL_START_QUOTE);
564: sb.append(this .jdbcType);
565: sb.append(END_QUOTE_SPACE);
566:
567: sb.append(ATTR_SCALE);
568: sb.append(EQUAL_START_QUOTE);
569: sb.append(this .scale);
570: sb.append(END_QUOTE_SPACE);
571:
572: sb.append(ATTR_PRECISION);
573: sb.append(EQUAL_START_QUOTE);
574: sb.append(this .precision);
575: sb.append(END_QUOTE_SPACE);
576:
577: sb.append(ATTR_CARDINAL_POSITION);
578: sb.append(EQUAL_START_QUOTE);
579: sb.append(this .cardinalPosition);
580: sb.append(END_QUOTE_SPACE);
581:
582: sb.append(ATTR_IS_PRIMARY_KEY);
583: sb.append(EQUAL_START_QUOTE);
584: sb.append(this .pkFlag);
585: sb.append(END_QUOTE_SPACE);
586:
587: sb.append(ATTR_IS_FOREIGN_KEY);
588: sb.append(EQUAL_START_QUOTE);
589: sb.append(this .fkFlag);
590: sb.append(END_QUOTE_SPACE);
591:
592: sb.append(ATTR_INDEXED);
593: sb.append(EQUAL_START_QUOTE);
594: sb.append(this .indexed);
595: sb.append(END_QUOTE_SPACE);
596:
597: sb.append(ATTR_NULLABLE);
598: sb.append(EQUAL_START_QUOTE);
599: sb.append(this .nullable);
600: sb.append(END_QUOTE_SPACE);
601:
602: sb.append(ATTR_PARENT);
603: sb.append(EQUAL_START_QUOTE);
604: sb.append(this .parent.getName());
605: sb.append(QUOTE);
606:
607: return sb.toString();
608: }
609:
610: protected String getElementTagName() {
611: throw new UnsupportedOperationException("Not supported yet.");
612: }
613: }
|