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: *
022: * Copyright 2005 Sun Microsystems, Inc.
023: *
024: * Licensed under the Apache License, Version 2.0 (the "License");
025: * you may not use this file except in compliance with the License.
026: * You may obtain a copy of the License at
027: *
028: * http://www.apache.org/licenses/LICENSE-2.0
029: *
030: * Unless required by applicable law or agreed to in writing, software
031: * distributed under the License is distributed on an "AS IS" BASIS,
032: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
033: * See the License for the specific language governing permissions and
034: * limitations under the License.
035: *
036: */
037: package org.netbeans.modules.jdbcwizard.builder;
038:
039: import java.sql.DatabaseMetaData;
040: import java.sql.ResultSet;
041: import java.sql.SQLException;
042: import java.util.ArrayList;
043:
044: import java.util.Collections;
045: import java.util.List;
046:
047: import java.text.MessageFormat;
048: import java.util.ResourceBundle;
049: import org.openide.util.NbBundle;
050:
051: /**
052: * Captures database index metadata associated with a specific database table column.
053: *
054: * @author
055: */
056: public class IndexColumn implements Comparable {
057: private static final String RS_INDEX_NAME = "INDEX_NAME"; // NOI18N
058:
059: private static final String RS_COLUMN_NAME = "COLUMN_NAME"; // NOI18N
060:
061: private static final String RS_NON_UNIQUE = "NON_UNIQUE"; // NOI18N
062:
063: private static final String RS_TYPE = "TYPE"; // NOI18N
064:
065: private static final String RS_ORDINAL = "ORDINAL_POSITION"; // NOI18N
066:
067: private static final String RS_ASC_OR_DESC = "ASC_OR_DESC"; // NOI18N
068:
069: private static final String RS_CARDINALITY = "CARDINALITY"; // NOI18N
070:
071: /* Name of index */
072: private String name;
073:
074: /* Name of column associated with this index */
075: private String columnName;
076:
077: /* Index type: tableIndexClustered, tableIndexHashed, tableIndexOther */
078: private int type;
079:
080: /* Column sequence number within a composite index */
081: private int ordinalPosition;
082:
083: /* Indicates whether index is unique */
084: private boolean unique = false;
085:
086: /* Indicates sort order, if any, of index */
087: private String sortSequence;
088:
089: /* Indicates number of unique values in index */
090: private int cardinality;
091:
092: /**
093: * Creates a List of IndexColumn instances from the given ResultSet.
094: *
095: * @param rs ResultSet containing index metadata as obtained from DatabaseMetaData
096: * @return List of IndexColumn instances based from metadata in rs'
097: * @throws SQLException if SQL error occurs while reading in data from given ResultSet
098: */
099: public static List createIndexList(final ResultSet rs)
100: throws SQLException {
101: List indices = Collections.EMPTY_LIST;
102:
103: if (rs != null && rs.next()) {
104: indices = new ArrayList();
105: do {
106: final IndexColumn newIndex = new IndexColumn(rs);
107:
108: // Ignore statistics indexes as they are relevant only to the
109: // DB which sourced this metadata.
110: if (newIndex.getType() != DatabaseMetaData.tableIndexStatistic) {
111: indices.add(newIndex);
112: }
113: } while (rs.next());
114: }
115:
116: return indices;
117: }
118:
119: IndexColumn(final ResultSet rs) throws SQLException {
120: if (rs == null) {
121: // Locale locale = Locale.getDefault();
122: // ResourceBundle cMessages =
123: // ResourceBundle.getBundle("com/sun/jbi/ui/devtool/jdbc/builder/Bundle", locale); // NO
124: // i18n
125: final ResourceBundle cMessages = NbBundle
126: .getBundle(IndexColumn.class);// NO i18n
127: throw new IllegalArgumentException(cMessages
128: .getString("ERROR_VALID_RS")
129: + "(ERROR_VALID_RS)"); // NOI18N
130: }
131:
132: this .name = rs.getString(IndexColumn.RS_INDEX_NAME);
133: this .columnName = rs.getString(IndexColumn.RS_COLUMN_NAME);
134:
135: this .unique = !rs.getBoolean(IndexColumn.RS_NON_UNIQUE);
136: this .type = rs.getShort(IndexColumn.RS_TYPE);
137:
138: this .ordinalPosition = rs.getShort(IndexColumn.RS_ORDINAL);
139: this .sortSequence = rs.getString(IndexColumn.RS_ASC_OR_DESC);
140: this .cardinality = rs.getInt(IndexColumn.RS_CARDINALITY);
141: }
142:
143: /**
144: * Creates a new instance of IndexColumn using the given values.
145: *
146: * @param colName name of column
147: * @param indexName name of index
148: * @param indexType index type, as defined in DatabaseMetaData; note that tableIndexStatistic is
149: * not a valid type for IndexColumn
150: * @param colOrder sequence of this column within the (composite) index; should be 1 for
151: * single-column indexes
152: * @param isUnique true if index enforces unique values, false otherwise
153: * @param sortOrder "A" for ascending order, "D" for descending order, null for no defined sort
154: * order
155: * @param indexCardinality count of unique values contained in the index
156: */
157: public IndexColumn(final String colName, final String indexName,
158: final short indexType, final short colOrder,
159: final boolean isUnique, final String sortOrder,
160: final int indexCardinality) {
161:
162: final ResourceBundle cMessages = NbBundle
163: .getBundle(IndexColumn.class);// NO i18n
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(this .type) })
176: + "(ERROR_INDEX_TYPE)"); // NOI18N
177: }
178:
179: this .name = indexName;
180: this .columnName = colName;
181:
182: this .type = indexType;
183: this .ordinalPosition = colOrder;
184: this .unique = isUnique;
185:
186: this .sortSequence = sortOrder;
187: this .cardinality = indexCardinality;
188: }
189:
190: public IndexColumn(final IndexColumn iCol) {
191:
192: final ResourceBundle cMessages = NbBundle
193: .getBundle(IndexColumn.class);// NO i18n
194: if (iCol.getColumnName() == null) {
195: throw new IllegalArgumentException(cMessages
196: .getString("ERROR_PARAMETER_NAME")
197: + "(ERROR_PARAMETER_NAME)"); // NOI18N
198: }
199:
200: if (iCol.getType() != DatabaseMetaData.tableIndexClustered
201: && iCol.getType() != DatabaseMetaData.tableIndexHashed
202: && iCol.getType() != DatabaseMetaData.tableIndexOther) {
203: throw new IllegalArgumentException(MessageFormat.format(
204: cMessages.getString("ERROR_INDEX_TYPE"),
205: new Object[] { new Integer(this .type) })
206: + "(ERROR_INDEX_TYPE)"); // NOI18N
207: }
208:
209: this .name = iCol.getIndexName();
210: this .columnName = iCol.getColumnName();
211:
212: this .type = iCol.getType();
213: this .ordinalPosition = iCol.getOrdinalPosition();
214: this .unique = iCol.isUnique();
215:
216: this .sortSequence = iCol.getSortOrder();
217: this .cardinality = iCol.getCardinality();
218: }
219:
220: private IndexColumn() {
221: }
222:
223: /**
224: * Gets index name.
225: *
226: * @return index name
227: */
228: public String getIndexName() {
229: return this .name;
230: }
231:
232: /**
233: * Gets column name.
234: *
235: * @return name of column
236: */
237: public String getColumnName() {
238: return this .columnName;
239: }
240:
241: /**
242: * Gets index type.
243: *
244: * @return index type, one of DatabaseMetaData.tableIndexClustered,
245: * DatabaseMetaData.tableIndexHashed, or DatabaseMetaData.tableIndexOther
246: * @see java.sql.DatabaseMetaData.tableIndexClustered
247: * @see java.sql.DatabaseMetaData.tableIndexHashed
248: * @see java.sql.DatabaseMetaData.tableIndexOther
249: */
250: public int getType() {
251: return this .type;
252: }
253:
254: /**
255: * Indicates whether the index associated with this column is unique.
256: *
257: * @return true if index is unique, false otherwise
258: */
259: public boolean isUnique() {
260: return this .unique;
261: }
262:
263: /**
264: * Gets ordinal position of this column within a (composite) index. For an index associated with
265: * a single column, this should be 1.
266: *
267: * @return ordinal position of column within the composite index; 1 if
268: */
269: public int getOrdinalPosition() {
270: return this .ordinalPosition;
271: }
272:
273: /**
274: * Gets sort order, if any, associated with this index.
275: *
276: * @return "A" for ascending, "D" for descending, or null if no sort order is defined
277: */
278: public String getSortOrder() {
279: return this .sortSequence;
280: }
281:
282: /**
283: * Gets index cardinality. It represents the number of unique values associated with the index
284: * (for clustered, hashed, or other index types).
285: *
286: * @return count of unique values in the associated index
287: */
288: public int getCardinality() {
289: return this .cardinality;
290: }
291:
292: /**
293: * Compares this instance against the given object with respect to some "natural" ordering.
294: * Useful for sorting IndexColumn instances for UI display. Note: this class has a natural
295: * ordering that is inconsistent with equals.
296: *
297: * @param o Object against which this will be compared
298: * @return -1 if this is lesser than o; 0 if this is equal to o; 1 if this is greater than o
299: */
300: public int compareTo(final Object o) {
301: if (o == this ) {
302: return 0;
303: }
304:
305: final IndexColumn idx = (IndexColumn) o;
306: if (idx != null) {
307: if (this .name != null) {
308: return idx.name != null ? this .name.compareTo(idx.name)
309: : -1;
310: } else if (this .columnName != null) {
311: return idx.columnName != null ? this .columnName
312: .compareTo(idx.columnName) : -1;
313: } else {
314: return 0;
315: }
316: } else {
317: return -1;
318: }
319: }
320: }
|