001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: /*
021: * Sun Public License Notice
022: *
023: * The contents of this file are subject to the Sun Public License
024: * Version 1.0 (the "License"). You may not use this file except in
025: * compliance with the License. A copy of the License is available at
026: * http://www.sun.com/
027: *
028: * The Original Code is NetBeans. The Initial Developer of the Original
029: * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
030: * Microsystems, Inc. All Rights Reserved.
031: */
032:
033: package org.netbeans.modules.sql.project.dbmodel;
034:
035: import java.sql.DatabaseMetaData;
036: import java.sql.ResultSet;
037: import java.sql.SQLException;
038: import java.util.ArrayList;
039:
040: import java.util.Collections;
041: import java.util.List;
042:
043: //Internationalization
044: import java.util.Locale;
045: import java.text.MessageFormat;
046: import java.util.ResourceBundle;
047:
048: /**
049: * Captures database index metadata associated with a specific database table
050: * column.
051: *
052: * @author Jonathan Giron
053: * @version
054: */
055: public class IndexColumn implements Comparable {
056: private static final String RS_INDEX_NAME = "INDEX_NAME"; // NOI18N
057:
058: private static final String RS_COLUMN_NAME = "COLUMN_NAME"; // NOI18N
059:
060: private static final String RS_NON_UNIQUE = "NON_UNIQUE"; // NOI18N
061:
062: private static final String RS_TYPE = "TYPE"; // NOI18N
063:
064: private static final String RS_ORDINAL = "ORDINAL_POSITION"; // NOI18N
065:
066: private static final String RS_ASC_OR_DESC = "ASC_OR_DESC"; // NOI18N
067:
068: private static final String RS_CARDINALITY = "CARDINALITY"; // NOI18N
069:
070: /* Name of index */
071: private String name;
072:
073: /* Name of column associated with this index */
074: private String columnName;
075:
076: /* Index type: tableIndexClustered, tableIndexHashed, tableIndexOther */
077: private int type;
078:
079: /* Column sequence number within a composite index */
080: private int ordinalPosition;
081:
082: /* Indicates whether index is unique */
083: private boolean unique = false;
084:
085: /* Indicates sort order, if any, of index */
086: private String sortSequence;
087:
088: /* Indicates number of unique values in index */
089: private int cardinality;
090:
091: /**
092: * Creates a List of IndexColumn instances from the given ResultSet.
093: *
094: * @param rs ResultSet containing index metadata as obtained from
095: * DatabaseMetaData
096: * @return List of IndexColumn instances based from metadata in rs'
097: *
098: * @throws SQLException if SQL error occurs while reading in data from
099: * given ResultSet
100: */
101: public static List createIndexList(ResultSet rs)
102: throws SQLException {
103: List indices = Collections.EMPTY_LIST;
104:
105: if (rs != null && rs.next()) {
106: indices = new ArrayList();
107: do {
108: IndexColumn newIndex = new IndexColumn(rs);
109:
110: // Ignore statistics indexes as they are relevant only to the
111: // DB which sourced this metadata.
112: if (newIndex.getType() != DatabaseMetaData.tableIndexStatistic) {
113: indices.add(newIndex);
114: }
115: } while (rs.next());
116: }
117:
118: return indices;
119: }
120:
121: IndexColumn(ResultSet rs) throws SQLException {
122: if (rs == null) {
123: Locale locale = Locale.getDefault();
124: ResourceBundle cMessages = ResourceBundle.getBundle(
125: "com/stc/oracle/builder/Bundle", locale); // NO i18n
126: throw new IllegalArgumentException(cMessages
127: .getString("ERROR_VALID_RS")
128: + "(ERROR_VALID_RS)"); // NOI18N
129: }
130:
131: name = rs.getString(RS_INDEX_NAME);
132: columnName = rs.getString(RS_COLUMN_NAME);
133:
134: unique = !(rs.getBoolean(RS_NON_UNIQUE));
135: type = rs.getShort(RS_TYPE);
136:
137: ordinalPosition = rs.getShort(RS_ORDINAL);
138: sortSequence = rs.getString(RS_ASC_OR_DESC);
139: cardinality = rs.getInt(RS_CARDINALITY);
140: }
141:
142: /**
143: * Creates a new instance of IndexColumn using the given values.
144: *
145: * @param colName name of column
146: * @param indexName name of index
147: * @param indexType index type, as defined in DatabaseMetaData; note that
148: * tableIndexStatistic is not a valid type for IndexColumn
149: * @param colOrder sequence of this column within the (composite) index;
150: * should be 1 for single-column indexes
151: * @param isUnique true if index enforces unique values, false otherwise
152: * @param sortOrder "A" for ascending order, "D" for descending order, null for
153: * no defined sort order
154: * @param indexCardinality count of unique values contained in the index
155: */
156: public IndexColumn(String colName, String indexName,
157: short indexType, short colOrder, boolean isUnique,
158: String sortOrder, int indexCardinality) {
159:
160: Locale locale = Locale.getDefault();
161: ResourceBundle cMessages = ResourceBundle.getBundle(
162: "com/stc/oracle/builder/Bundle", locale); // NO i18n
163:
164: if (colName == null) {
165: throw new IllegalArgumentException(cMessages
166: .getString("ERROR_PARAMETER_NAME")
167: + "(ERROR_PARAMETER_NAME)"); // NOI18N
168: }
169:
170: if (indexType != DatabaseMetaData.tableIndexClustered
171: && indexType != DatabaseMetaData.tableIndexHashed
172: && indexType != DatabaseMetaData.tableIndexOther) {
173: throw new IllegalArgumentException(MessageFormat.format(
174: cMessages.getString("ERROR_INDEX_TYPE"),
175: new Object[] { new Integer(type) })
176: + "(ERROR_INDEX_TYPE)"); // NOI18N
177: }
178:
179: name = indexName;
180: columnName = colName;
181:
182: type = indexType;
183: ordinalPosition = colOrder;
184: unique = isUnique;
185:
186: sortSequence = sortOrder;
187: cardinality = indexCardinality;
188: }
189:
190: public IndexColumn(IndexColumn iCol) {
191:
192: Locale locale = Locale.getDefault();
193: ResourceBundle cMessages = ResourceBundle.getBundle(
194: "com/stc/oracle/builder/Bundle", locale); // NO i18n
195: if (iCol.getColumnName() == null) {
196: throw new IllegalArgumentException(cMessages
197: .getString("ERROR_PARAMETER_NAME")
198: + "(ERROR_PARAMETER_NAME)"); // NOI18N
199: }
200:
201: if (iCol.getType() != DatabaseMetaData.tableIndexClustered
202: && iCol.getType() != DatabaseMetaData.tableIndexHashed
203: && iCol.getType() != DatabaseMetaData.tableIndexOther) {
204: throw new IllegalArgumentException(MessageFormat.format(
205: cMessages.getString("ERROR_INDEX_TYPE"),
206: new Object[] { new Integer(type) })
207: + "(ERROR_INDEX_TYPE)"); // NOI18N
208: }
209:
210: name = iCol.getIndexName();
211: columnName = iCol.getColumnName();
212:
213: type = iCol.getType();
214: ordinalPosition = iCol.getOrdinalPosition();
215: unique = iCol.isUnique();
216:
217: sortSequence = iCol.getSortOrder();
218: cardinality = iCol.getCardinality();
219: }
220:
221: private IndexColumn() {
222: }
223:
224: /**
225: * Gets index name.
226: *
227: * @return index name
228: */
229: public String getIndexName() {
230: return name;
231: }
232:
233: /**
234: * Gets column name.
235: *
236: * @return name of column
237: */
238: public String getColumnName() {
239: return columnName;
240: }
241:
242: /**
243: * Gets index type.
244: *
245: * @return index type, one of DatabaseMetaData.tableIndexClustered,
246: * DatabaseMetaData.tableIndexHashed, or DatabaseMetaData.tableIndexOther
247: *
248: * @see java.sql.DatabaseMetaData.tableIndexClustered
249: * @see java.sql.DatabaseMetaData.tableIndexHashed
250: * @see java.sql.DatabaseMetaData.tableIndexOther
251: */
252: public int getType() {
253: return type;
254: }
255:
256: /**
257: * Indicates whether the index associated with this column is unique.
258: *
259: * @return true if index is unique, false otherwise
260: */
261: public boolean isUnique() {
262: return unique;
263: }
264:
265: /**
266: * Gets ordinal position of this column within a (composite) index.
267: * For an index associated with a single column, this should be 1.
268: *
269: * @return ordinal position of column within the composite index; 1 if
270: */
271: public int getOrdinalPosition() {
272: return ordinalPosition;
273: }
274:
275: /**
276: * Gets sort order, if any, associated with this index.
277: *
278: * @return "A" for ascending, "D" for descending, or null if no sort order
279: * is defined
280: */
281: public String getSortOrder() {
282: return sortSequence;
283: }
284:
285: /**
286: * Gets index cardinality. It represents the number of unique
287: * values associated with the index (for clustered, hashed, or other
288: * index types).
289: *
290: * @return count of unique values in the associated index
291: */
292: public int getCardinality() {
293: return cardinality;
294: }
295:
296: /**
297: * Compares this instance against the given object with respect to some
298: * "natural" ordering. Useful for sorting IndexColumn instances for UI display.
299: *
300: * Note: this class has a natural ordering that is inconsistent with equals.
301: * @param o Object against which this will be compared
302: * @return -1 if this is lesser than o; 0 if this is equal to o; 1 if this
303: * is greater than o
304: */
305: public int compareTo(Object o) {
306: if (o == this ) {
307: return 0;
308: }
309:
310: IndexColumn idx = (IndexColumn) o;
311: if (idx != null) {
312: if (name != null) {
313: return (idx.name != null) ? name.compareTo(idx.name)
314: : -1;
315: } else if (columnName != null) {
316: return (idx.columnName != null) ? columnName
317: .compareTo(idx.columnName) : -1;
318: } else {
319: return 0;
320: }
321: } else {
322: return -1;
323: }
324: }
325: }
|