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.dbmodel.impl;
038:
039: import org.netbeans.modules.jdbcwizard.builder.dbmodel.DBTable;
040: import org.netbeans.modules.jdbcwizard.builder.dbmodel.DBColumn;
041: import org.netbeans.modules.jdbcwizard.builder.dbmodel.Index;
042:
043: import java.util.ArrayList;
044: import java.util.Collections;
045: import java.util.Iterator;
046: import java.util.List;
047: import java.util.ResourceBundle;
048: import org.openide.util.NbBundle;
049:
050: /**
051: * Implements Index interface.
052: *
053: * @author
054: */
055: public class IndexImpl implements Index, Cloneable {
056:
057: /* Name of this index */
058: private String name;
059:
060: /* Type of index, as enumerated in DatabaseMetaData */
061: private int type;
062:
063: /* DBTable to which this Index belongs */
064: private DBTable parent;
065:
066: /* List of column names in key sequence order. */
067: private List columnNames;
068:
069: /* Indicates whether index is unique */
070: private boolean unique = false;
071:
072: /* Indicates sort order, if any, of index */
073: private String sortSequence;
074:
075: /* Indicates number of unique values in index */
076: private int cardinality;
077:
078: private IndexImpl() {
079: this .name = null;
080: this .columnNames = new ArrayList();
081: }
082:
083: /**
084: * Creates a new instance of Index with the given key name and attributes.
085: *
086: * @param indexName name of this Index, must be non-empty
087: * @param indexType type of Index, as enumerated in java.sql.DatabaseMetaData; one of
088: * tableIndexClustered, tableIndexHashed, or tableIndexOther
089: * @param isUnique true if index enforces uniqueness, false otherwise
090: * @param sortOrder 'A' for ascending, 'D' for descending, null if undefined
091: * @param indexCardinality cardinality of this index
092: * @see java.sql.DatabaseMetaData#tableIndexClustered
093: * @see java.sql.DatabaseMetaData#tableIndexHashed
094: * @see java.sql.DatabaseMetaData#tableIndexOther
095: */
096: public IndexImpl(final String indexName, final int indexType,
097: final boolean isUnique, final String sortOrder,
098: final int indexCardinality) {
099: this ();
100:
101: if (indexName == null) {
102: final ResourceBundle cMessages = NbBundle
103: .getBundle(IndexImpl.class);
104:
105: throw new IllegalArgumentException(cMessages
106: .getString("ERROR_INDEX_NAME")
107: + "(ERROR_INDEX_NAME)");// NO
108: // i18n
109: }
110:
111: this .name = indexName;
112: this .type = indexType;
113: this .unique = isUnique;
114: this .sortSequence = sortOrder;
115: this .cardinality = indexCardinality;
116: }
117:
118: /**
119: * Creates a new instance of Index with the given key name and attributes, and referencing the
120: * column names in the given List.
121: *
122: * @param indexName name of this Index, must be non-empty
123: * @param indexType type of Index, as enumerated in java.sql.DatabaseMetaData; one of
124: * tableIndexClustered, tableIndexHashed, or tableIndexOther
125: * @param isUnique true if index enforces uniqueness, false otherwise
126: * @param sortOrder 'A' for ascending, 'D' for descending, null if undefined
127: * @param indexCardinality cardinality of this index
128: * @param indexColumnNames List of Column objects, or column names in sequential order,
129: * depending on state of isStringList
130: * @param isStringList true if indexColumnName contains column names in sequential order, false
131: * if it contains Column objects which need to be sorted in sequential order.
132: * @see java.sql.DatabaseMetaData#tableIndexClustered
133: * @see java.sql.DatabaseMetaData#tableIndexHashed
134: * @see java.sql.DatabaseMetaData#tableIndexOther
135: */
136: public IndexImpl(final String indexName, final int indexType,
137: final boolean isUnique, final String sortOrder,
138: final int indexCardinality, final List indexColumnNames,
139: final boolean isStringList) {
140: this (indexName, indexType, isUnique, sortOrder,
141: indexCardinality);
142: this .setColumnNames(indexColumnNames, isStringList);
143: }
144:
145: /**
146: * Creates a new instance of Index, cloning the contents of the given Index implementation
147: * instance.
148: *
149: * @param src Index instance to be cloned
150: */
151: public IndexImpl(final Index src) {
152: this ();
153: this .copyFrom(src);
154: }
155:
156: /*
157: * IMPLEMENTATION OF com.stc.model.database.Index
158: */
159:
160: /**
161: * @see com.stc.model.database.Index#getName
162: */
163: public String getName() {
164: return this .name;
165: }
166:
167: /**
168: * @see com.stc.model.database.Index#getParent
169: */
170: public DBTable getParent() {
171: return this .parent;
172: }
173:
174: /**
175: * @see com.stc.model.database.Index#getType
176: */
177: public int getType() {
178: return this .type;
179: }
180:
181: /**
182: * @see com.stc.model.database.Index#contains(String)
183: */
184: public boolean isUnique() {
185: return this .unique;
186: }
187:
188: /**
189: * @see com.stc.model.database.Index#getSortSequence
190: */
191: public String getSortSequence() {
192: return this .sortSequence;
193: }
194:
195: /**
196: * @see com.stc.model.database.Index#getCardinality
197: */
198: public int getCardinality() {
199: return this .cardinality;
200: }
201:
202: /**
203: * @see com.stc.model.database.Index#getColumnNames
204: */
205: public List getColumnNames() {
206: return Collections.unmodifiableList(this .columnNames);
207: }
208:
209: /**
210: * @see com.stc.model.database.Index#getColumnCount
211: */
212: public int getColumnCount() {
213: return this .columnNames.size();
214: }
215:
216: /**
217: * @see com.stc.model.database.Index#getSequence(DBColumn)
218: */
219: public int getSequence(final DBColumn col) {
220: if (col == null || col.getName() == null) {
221: return -1;
222: }
223:
224: return this .getSequence(col.getName().trim());
225: }
226:
227: /**
228: * @see com.stc.model.database.Index#getColumnName
229: */
230: public String getColumnName(final int iColumn) {
231: return (String) this .columnNames.get(iColumn);
232: }
233:
234: /**
235: * @see com.stc.model.database.Index#contains(String)
236: */
237: public boolean contains(final String columnName) {
238: return this .columnNames.contains(columnName);
239: }
240:
241: /**
242: * @see com.stc.model.database.Index#contains(DBColumn)
243: */
244: public boolean contains(final DBColumn col) {
245: return col != null ? this .contains(col.getName()) : false;
246: }
247:
248: /*
249: * Setter and non-API helper methods
250: */
251:
252: /**
253: * Sets reference to JDBCTable that owns this primary key.
254: *
255: * @param newParent new parent of this primary key.
256: */
257: public void setParent(final DBTable newParent) {
258: this .parent = newParent;
259: }
260:
261: public void setColumnNames(final List indexColumnNames,
262: final boolean isStringList) {
263: if (isStringList) {
264: this .columnNames.addAll(indexColumnNames);
265: } else {
266: Collections.sort(indexColumnNames);
267: final Iterator iter = indexColumnNames.iterator();
268: while (iter.hasNext()) {
269: final IndexImpl.Column col = (IndexImpl.Column) iter
270: .next();
271: this .columnNames.add(col.getName());
272: }
273: }
274: }
275:
276: /**
277: * Gets the ordinal position of the column, if any, associated with the given columnName.
278: *
279: * @param columnName name of column whose position is desired
280: * @return (zero-based) position of given column, or -1 if no column by the given columnName
281: * could be located
282: */
283: public int getSequence(final String columnName) {
284: return this .columnNames.indexOf(columnName);
285: }
286:
287: /**
288: * Create a clone of this PrimaryKeyImpl.
289: *
290: * @return cloned copy of DBColumn.
291: */
292: public Object clone() {
293: try {
294: final IndexImpl impl = (IndexImpl) super .clone();
295: impl.columnNames = new ArrayList(this .columnNames);
296:
297: return impl;
298: } catch (final CloneNotSupportedException e) {
299: throw new InternalError(e.toString());
300: }
301: }
302:
303: /**
304: * Overrides default implementation to return value based on memberwise comparison.
305: *
306: * @param refObj Object against which we compare this instance
307: * @return true if refObj is functionally identical to this instance; false otherwise
308: */
309: public boolean equals(final Object refObj) {
310: if (this == refObj) {
311: return true;
312: }
313:
314: if (!(refObj instanceof IndexImpl)) {
315: return false;
316: }
317:
318: final IndexImpl ref = (IndexImpl) refObj;
319:
320: boolean result = this .name != null ? this .name.equals(ref.name)
321: : ref.name == null;
322:
323: result &= this .type == ref.type
324: && this .cardinality == ref.cardinality
325: && this .unique == ref.unique;
326:
327: result &= this .sortSequence != null ? this .sortSequence
328: .equals(ref.sortSequence) : ref.sortSequence == null;
329:
330: result &= this .columnNames != null ? this .columnNames
331: .equals(ref.columnNames) : ref.columnNames == null;
332:
333: return result;
334: }
335:
336: /**
337: * Overrides default implementation to compute hashCode value for those members used in equals()
338: * for comparison.
339: *
340: * @return hash code for this object
341: * @see java.lang.Object#hashCode
342: */
343: public int hashCode() {
344: int myHash = this .name != null ? this .name.hashCode() : 0;
345: myHash += this .columnNames != null ? this .columnNames
346: .hashCode() : 0;
347:
348: myHash += this .type + this .cardinality + (this .unique ? 1 : 0);
349: myHash += this .sortSequence != null ? this .sortSequence
350: .hashCode() : 0;
351:
352: return myHash;
353: }
354:
355: /**
356: * Replaces the current List of column names with the contents of the given String array.
357: *
358: * @param newColNames array of names to supplant current list of column names
359: */
360: public void setColumnNames(final String[] newColNames) {
361: if (newColNames == null) {
362: final ResourceBundle cMessages = NbBundle
363: .getBundle(IndexImpl.class);
364: throw new IllegalArgumentException(cMessages
365: .getString("ERROR_COL_NAMES")
366: + "(ERROR_COL_NAMES)");// NO
367: // i18n
368: }
369:
370: this .columnNames.clear();
371: for (int i = 0; i < newColNames.length; i++) {
372: this .columnNames.add(newColNames[i]);
373: }
374: }
375:
376: private void copyFrom(final Index src) {
377: this .name = src.getName();
378: this .parent = src.getParent();
379:
380: this .columnNames.clear();
381: this .columnNames.addAll(src.getColumnNames());
382:
383: this .type = src.getType();
384: this .unique = src.isUnique();
385: this .sortSequence = src.getSortSequence();
386: this .cardinality = src.getCardinality();
387: }
388:
389: /**
390: * Intermediate container class to hold metadata of columns involved in a particular Index.
391: */
392: public static class Column implements Comparable {
393: private String name;
394:
395: private int sequence;
396:
397: /**
398: * Creates a new instance of Index.Column with the given name and sequence.
399: *
400: * @param colName name of new column
401: * @param colSequence sequence of new column w.r.t. other columns
402: */
403: public Column(final String colName, final int colSequence) {
404: final ResourceBundle cMessages = NbBundle
405: .getBundle(IndexImpl.class);
406: if (colName == null || colName.trim().length() == 0) {
407: throw new IllegalArgumentException(cMessages
408: .getString("ERROR_COL_NAME")
409: + "(ERROR_COL_NAME)");// NO
410: // i18n
411: }
412:
413: if (colSequence <= 0) {
414: throw new IllegalArgumentException(cMessages
415: .getString("ERROR_COL_SEQ")
416: + "(ERROR_COL_SEQ)");// NO
417: // i18n
418: }
419:
420: this .name = colName;
421: this .sequence = colSequence;
422: }
423:
424: /**
425: * Creates a new instance of Index.Column with the given DBColumn and sequence.
426: *
427: * @param col new DBColumn
428: * @param colSequence sequence of new column w.r.t. other columns
429: */
430: public Column(final DBColumn col, final int colSequence) {
431: this (col.getName(), colSequence);
432: }
433:
434: /**
435: * Gets name of this column.
436: *
437: * @return column name
438: */
439: public String getName() {
440: return this .name;
441: }
442:
443: /**
444: * Gets sequence of this column with respect to others in the associated index.
445: *
446: * @return column index
447: */
448: public int getSequence() {
449: return this .sequence;
450: }
451:
452: /**
453: * Compares this object with the specified object for order. Returns a negative integer,
454: * zero, or a positive integer as this object is less than, equal to, or greater than the
455: * specified object.
456: * <p>
457: * Note: this class has a natural ordering that is inconsistent with equals.
458: *
459: * @param o the Object to be compared.
460: * @return a negative integer, zero, or a positive integer as this object is less than,
461: * equal to, or greater than the specified object.
462: */
463: public int compareTo(final Object o) {
464: return this .sequence - ((Column) o).sequence;
465: }
466: }
467: }
|