IndexImpl.java :  » IDE-Netbeans » etl.project » org » netbeans » modules » sql » framework » model » impl » Java Open Source

Java Open Source » IDE Netbeans » etl.project 
etl.project » org » netbeans » modules » sql » framework » model » impl » IndexImpl.java
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */
package org.netbeans.modules.sql.framework.model.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.netbeans.modules.sql.framework.model.DBColumn;
import org.w3c.dom.Element;

import com.sun.sql.framework.exception.BaseException;
import com.sun.sql.framework.utils.StringUtil;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Locale;
import java.util.ResourceBundle;
import org.netbeans.modules.sql.framework.model.DBTable;
import org.netbeans.modules.sql.framework.model.Index;

/**
 * Implements Index interface.
 * 
 * @author Jonathan Giron
 * @version $Revision$
 */
public class IndexImpl implements Cloneable, Index {

    /**
     * Intermediate container class to hold metadata of columns involved in a particular
     * Index.
     */
    public static class Column implements Comparable {
        private String name;
        private int sequence;

        /**
         * Creates a new instance of Index.Column with the given DBColumn and sequence.
         * 
         * @param col new DBColumn
         * @param colSequence sequence of new column w.r.t. other columns
         */
        public Column(DBColumn col, int colSequence) {
            this(col.getName(), colSequence);
        }

        /**
         * Creates a new instance of Index.Column with the given name and sequence.
         * 
         * @param colName name of new column
         * @param colSequence sequence of new column w.r.t. other columns
         */
        public Column(String colName, int colSequence) {
            if (colName == null || colName.trim().length() == 0) {
                throw new IllegalArgumentException("Must supply non-empty String value for parameter colName.");
            }

            if (colSequence <= 0) {
                throw new IllegalArgumentException("Must supply positive integer value for parameter colSequence.");
            }

            name = colName;
            sequence = colSequence;
        }

        /**
         * Compares this object with the specified object for order. Returns a negative
         * integer, zero, or a positive integer as this object is less than, equal to, or
         * greater than the specified object.
         * <p>
         * Note: this class has a natural ordering that is inconsistent with equals.
         * 
         * @param o the Object to be compared.
         * @return a negative integer, zero, or a positive integer as this object is less
         *         than, equal to, or greater than the specified object.
         */
        public int compareTo(Object o) {
            return (this.sequence - ((Column) o).sequence);
        }

        /**
         * Gets name of this column.
         * 
         * @return column name
         */
        public String getName() {
            return name;
        }

        /**
         * Gets sequence of this column with respect to others in the associated index.
         * 
         * @return column index
         */
        public int getSequence() {
            return sequence;
        }
    }

    /** Name of attribute used for marshalling out cardinality value to XML */
    public static final String CARDINALITY_ATTR = "cardinality"; // NOI18N

    /** List of column names in key sequence order. */
    public static final String COLUMNS_ATTR = "columns"; // NOI18N

    /** Document element tag name for marshalling out this object to XML */
    public static final String ELEMENT_TAG = "index"; // NOI18N

    /** Name of attribute used for marshalling out index name to XML */
    public static final String NAME_ATTR = "name"; // NOI18N

    /** Name of attribute used for marshalling out sort order value to XML */
    public static final String SORTORDER_ATTR = "sortOrder"; // NOI18N

    /** Name of attribute used for marshalling out index type to XML */
    public static final String TYPE_ATTR = "type"; // NOI18N

    /** Name of attribute used for marshalling out uniqueness flag to XML */
    public static final String UNIQUE_ATTR = "unique"; // NOI18N

    /* Indicates number of unique values in index */
    private int cardinality;

    /* List of column names in key sequence order. */
    private List<String> columnNames;

    /* (optional) DOM element used to construct this instance of Index */
    private transient Element element;

    /* Name of this index */
    private String name;

    /* DBTable to which this Index belongs */
    private DBTable parent;

    /* Indicates sort order, if any, of index */
    private String sortSequence;

    /* Type of index, as enumerated in DatabaseMetaData */
    private int type;

    /* Indicates whether index is unique */
    private boolean unique = false;

    private static final String
        RS_INDEX_NAME = "INDEX_NAME"; // NOI18N
    
    private static final String
        RS_COLUMN_NAME = "COLUMN_NAME"; // NOI18N
        
    private static final String
        RS_NON_UNIQUE = "NON_UNIQUE"; // NOI18N
    
    private static final String
        RS_TYPE = "TYPE"; // NOI18N
    
    private static final String
        RS_ORDINAL = "ORDINAL_POSITION"; // NOI18N
    
    private static final String
        RS_ASC_OR_DESC = "ASC_OR_DESC"; // NOI18N
    
    private static final String
        RS_CARDINALITY = "CARDINALITY"; // NOI18N
    
        /**
     * Creates a List of IndexColumn instances from the given ResultSet.
     *
     * @param rs ResultSet containing index metadata as obtained from 
     * DatabaseMetaData
     * @return List of IndexColumn instances based from metadata in rs'
     *
     * @throws SQLException if SQL error occurs while reading in data from
     * given ResultSet
     */
    public static List<IndexImpl> createIndexList(ResultSet rs) throws SQLException {
        List<IndexImpl> indices = Collections.emptyList();
        
        if (rs != null && rs.next()) {
            indices = new ArrayList<IndexImpl>();
            do {
                IndexImpl newIndex = new IndexImpl(rs);
                
                // Ignore statistics indexes as they are relevant only to the
                // DB which sourced this metadata.
                if (newIndex.getType() != DatabaseMetaData.tableIndexStatistic) {
                    indices.add(newIndex);
                }
            } while (rs.next());
        }
        
        return indices;
    }

    IndexImpl(ResultSet rs) throws SQLException {
        if (rs == null) {
            Locale locale = Locale.getDefault();
            ResourceBundle cMessages = ResourceBundle.getBundle("org/netbeans/modules/sql/framework/model/impl/Bundle", locale); // NO i18n            
            throw new IllegalArgumentException(
                cMessages.getString("ERROR_VALID_RS")+"(ERROR_VALID_RS)"); // NOI18N
        }
        
        name = rs.getString(RS_INDEX_NAME);
        //columnName = rs.getString(RS_COLUMN_NAME);
        
        unique = !(rs.getBoolean(RS_NON_UNIQUE));
        type = rs.getShort(RS_TYPE);
        
        //ordinalPosition = rs.getShort(RS_ORDINAL);
        sortSequence = rs.getString(RS_ASC_OR_DESC);
        cardinality = rs.getInt(RS_CARDINALITY);
    }

    /**
     * Creates a new instance of IndexImpl, using the given keyElement as a source for
     * reconstituting its contents. Caller must invoke parseXML() after this constructor
     * returns in order to unmarshal and reconstitute the instance object.
     * 
     * @param keyElement DOM element containing XML marshalled version of a IndexImpl
     *        instance
     * @see #parseXML
     */
    public IndexImpl(Element keyElement) {
        this();
        element = keyElement;
    }

    /**
     * Creates a new instance of Index, cloning the contents of the given Index
     * implementation instance.
     * 
     * @param src Index instance to be cloned
     */
    public IndexImpl(Index src) {
        this();
        copyFrom(src);
    }

    /**
     * Creates a new instance of Index with the given key name and attributes.
     * 
     * @param indexName name of this Index, must be non-empty
     * @param indexType type of Index, as enumerated in java.sql.DatabaseMetaData; one of
     *        tableIndexClustered, tableIndexHashed, or tableIndexOther
     * @param isUnique true if index enforces uniqueness, false otherwise
     * @param sortOrder 'A' for ascending, 'D' for descending, null if undefined
     * @param indexCardinality cardinality of this index
     * @see java.sql.DatabaseMetaData#tableIndexClustered
     * @see java.sql.DatabaseMetaData#tableIndexHashed
     * @see java.sql.DatabaseMetaData#tableIndexOther
     */
    public IndexImpl(String indexName, int indexType, boolean isUnique, String sortOrder, int indexCardinality) {
        this();

        if (indexName == null) {
            throw new IllegalArgumentException("Must supply non-empty String ref for indexName param.");
        }

        name = indexName;
        type = indexType;
        unique = isUnique;
        sortSequence = sortOrder;
        cardinality = indexCardinality;
    }

    /**
     * Creates a new instance of Index with the given key name and attributes, and
     * referencing the column names in the given List.
     * 
     * @param indexName name of this Index, must be non-empty
     * @param indexType type of Index, as enumerated in java.sql.DatabaseMetaData; one of
     *        tableIndexClustered, tableIndexHashed, or tableIndexOther
     * @param isUnique true if index enforces uniqueness, false otherwise
     * @param sortOrder 'A' for ascending, 'D' for descending, null if undefined
     * @param indexCardinality cardinality of this index
     * @param indexColumnNames List of Column objects, or column names in sequential
     *        order, depending on state of isStringList
     * @param isStringList true if indexColumnName contains column names in sequential
     *        order, false if it contains Column objects which need to be sorted in
     *        sequential order.
     * @see java.sql.DatabaseMetaData#tableIndexClustered
     * @see java.sql.DatabaseMetaData#tableIndexHashed
     * @see java.sql.DatabaseMetaData#tableIndexOther
     */
    public IndexImpl(String indexName, int indexType, boolean isUnique, String sortOrder, int indexCardinality, List indexColumnNames,
            boolean isStringList) {
        this(indexName, indexType, isUnique, sortOrder, indexCardinality);
        setColumnNames(indexColumnNames, isStringList);
    }

    /*
     * IMPLEMENTATION OF Index
     */

    /* Private no-arg constructor */
    private IndexImpl() {
        name = null;
        columnNames = new ArrayList<String>();
    }

    /**
     * Create a clone of this PrimaryKeyImpl.
     * 
     * @return cloned copy of DBColumn.
     */
    @Override
    public Object clone() {
        try {
            IndexImpl impl = (IndexImpl) super.clone();
            impl.columnNames = new ArrayList<String>(this.columnNames);

            return impl;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.toString());
        }
    }

    /**
     * @see org.netbeans.modules.model.database.Index#contains(DBColumn)
     */
    public boolean contains(DBColumn col) {
        return (col != null) ? contains(col.getName()) : false;
    }

    /**
     * @see org.netbeans.modules.model.database.Index#contains(java.lang.String)
     */
    public boolean contains(String columnName) {
        return columnNames.contains(columnName);
    }

    /**
     * Overrides default implementation to return value based on memberwise comparison.
     * 
     * @param refObj Object against which we compare this instance
     * @return true if refObj is functionally identical to this instance; false otherwise
     */
    @Override
    public boolean equals(Object refObj) {
        if (this == refObj) {
            return true;
        }

        if (!(refObj instanceof IndexImpl)) {
            return false;
        }

        IndexImpl ref = (IndexImpl) refObj;

        boolean result = (name != null) ? name.equals(ref.name) : (ref.name == null);

        result &= (type == ref.type) && (cardinality == ref.cardinality) && (unique == ref.unique);

        result &= (sortSequence != null) ? sortSequence.equals(ref.sortSequence) : (ref.sortSequence == null);

        result &= (columnNames != null) ? columnNames.equals(ref.columnNames) : (ref.columnNames == null);

        return result;
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getCardinality
     */
    public int getCardinality() {
        return cardinality;
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getColumnCount
     */
    public int getColumnCount() {
        return columnNames.size();
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getColumnName
     */
    public String getColumnName(int iColumn) {
        return columnNames.get(iColumn);
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getColumnNames
     */
    public List<String> getColumnNames() {
        return Collections.unmodifiableList(columnNames);
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getName
     */
    public String getName() {
        return name;
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getParent
     */
    public DBTable getParent() {
        return parent;
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getSequence(DBColumn)
     */
    public int getSequence(DBColumn col) {
        if (col == null || col.getName() == null) {
            return -1;
        }

        return getSequence(col.getName().trim());
    }

    /*
     * Setter and non-API helper methods
     */

    /**
     * Gets the ordinal position of the column, if any, associated with the given
     * columnName.
     * 
     * @param columnName name of column whose position is desired
     * @return (zero-based) position of given column, or -1 if no column by the given
     *         columnName could be located
     */
    public int getSequence(String columnName) {
        return columnNames.indexOf(columnName);
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getSortSequence
     */
    public String getSortSequence() {
        return sortSequence;
    }

    /**
     * @see org.netbeans.modules.model.database.Index#getType
     */
    public int getType() {
        return type;
    }

    /**
     * Overrides default implementation to compute hashCode value for those members used
     * in equals() for comparison.
     * 
     * @return hash code for this object
     * @see java.lang.Object#hashCode
     */
    @Override
    public int hashCode() {
        int myHash = (name != null) ? name.hashCode() : 0;
        myHash += (columnNames != null) ? columnNames.hashCode() : 0;

        myHash += type + cardinality + (unique ? 1 : 0);
        myHash += (sortSequence != null) ? sortSequence.hashCode() : 0;

        return myHash;
    }

    /**
     * @see org.netbeans.modules.model.database.Index#contains(java.lang.String)
     */
    public boolean isUnique() {
        return unique;
    }

    /**
     * Parses the XML content, if any, represented by the DOM element member variable.
     * 
     * @exception BaseException thrown while parsing XML, or if member variable element is
     *            null
     */
    public void parseXML() throws BaseException {
        if (this.element == null) {
            throw new BaseException("No <" + ELEMENT_TAG + "> element found.");
        }

        this.name = element.getAttribute(NAME_ATTR);

        String val = element.getAttribute(TYPE_ATTR);
        try {
            this.type = Integer.parseInt(val);
        } catch (NumberFormatException e) {
            this.type = 0;
        } catch (NullPointerException e) {
            this.type = 0;
        }

        val = element.getAttribute(UNIQUE_ATTR);
        try {
            this.unique = Boolean.valueOf(val).booleanValue();
        } catch (NullPointerException e) {
            this.type = 0;
        }

        this.sortSequence = element.getAttribute(SORTORDER_ATTR);

        val = element.getAttribute(CARDINALITY_ATTR);
        try {
            this.cardinality = Integer.parseInt(val);
        } catch (NumberFormatException e) {
            this.cardinality = 0;
        } catch (NullPointerException e) {
            this.cardinality = 0;
        }

        String colNames = element.getAttribute(COLUMNS_ATTR);
        columnNames.addAll(StringUtil.createStringListFrom(colNames));
    }

    /**
     * Sets column names associated with this index from the given List, using the given
     * flag to interpret the type of objects contained in the list.
     * 
     * @param indexColumnNames List of column names (either as Index.Column objects or
     *        String values)
     * @param isStringList true if List contains column names as Strings, false if List
     *        contains Index.Column objects.
     */
    public void setColumnNames(List<String> indexColumnNames, boolean isStringList) {
        if (isStringList) {
            columnNames.addAll(indexColumnNames);
        } else {
            Collections.sort(indexColumnNames);
            Iterator iter = indexColumnNames.iterator();
            while (iter.hasNext()) {
                Column col = (Column) iter.next();
                columnNames.add(col.getName());
            }
        }
    }

    /**
     * Replaces the current List of column names with the contents of the given String
     * array.
     * 
     * @param newColNames array of names to supplant current list of column names
     */
    public void setColumnNames(String[] newColNames) {
        if (newColNames == null) {
            throw new IllegalArgumentException("Must supply non-null String[] for param newColNames.");
        }

        columnNames.clear();
        for (int i = 0; i < newColNames.length; i++) {
            columnNames.add(newColNames[i]);
        }
    }

    /**
     * Sets reference to SQLTable that owns this primary key.
     * 
     * @param newParent new parent of this primary key.
     */
    public void setParent(DBTable newParent) {
        parent = newParent;
    }

    /**
     * Gets the default XML representation of index metadata.
     * 
     * @return XML representation of the index metadata.
     */
    public synchronized String toXMLString() {
        return toXMLString(null);
    }

    /**
     * Gets the XML representation of index metadata, using the given String as a prefix
     * for successive elements.
     * 
     * @param prefix start-of-line prefix for the XML representation.
     * @return XML representation of the index metadata.
     */
    public synchronized String toXMLString(String prefix) {
        if (prefix == null) {
            prefix = "";
        }

        StringBuilder buf = new StringBuilder(100);

        buf.append(prefix).append("<").append(ELEMENT_TAG).append(" ");
        if (name != null && name.trim().length() != 0) {
            buf.append(NAME_ATTR).append("=\"").append(name.trim()).append("\" ");
        }

        buf.append(TYPE_ATTR).append("=\"").append(type).append("\" ");

        buf.append(UNIQUE_ATTR).append("=\"").append(unique).append("\" ");

        if (sortSequence != null && sortSequence.trim().length() != 0) {
            buf.append(SORTORDER_ATTR).append("=\"").append(sortSequence).append("\" ");
        }

        buf.append(CARDINALITY_ATTR).append("=\"").append(cardinality).append("\" ");

        if (columnNames.size() != 0) {
            buf.append(COLUMNS_ATTR).append("=\"");
            for (int i = 0; i < columnNames.size(); i++) {
                if (i != 0) {
                    buf.append(",");
                }
                buf.append((columnNames.get(i)).trim());
            }
            buf.append("\" ");
        }

        buf.append("/>\n");

        return buf.toString();
    }

    private void copyFrom(Index src) {
        name = src.getName();
        parent = src.getParent();

        columnNames.clear();
        columnNames.addAll(src.getColumnNames());

        type = src.getType();
        unique = src.isUnique();
        sortSequence = src.getSortSequence();
        cardinality = src.getCardinality();
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.