alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.mdr.persistence.jdbcimpl;

import org.netbeans.mdr.persistence.*;
import org.netbeans.mdr.util.*;

import java.sql.*;
import java.util.*;
import java.io.*;

/**
 * JdbcMultivaluedOrderedIndex implements the MDR MultivaluedOrderedIndex
 * using JDBC.
 *
 * @author John V. Sichi
 * @version $Id: JdbcMultivaluedOrderedIndex.java,v 1.4 2004/03/05 00:33:57 jsichi Exp $
 */
class JdbcMultivaluedOrderedIndex
    extends JdbcMultivaluedIndex implements MultivaluedOrderedIndex
{
    protected LazyPreparedStatement sqlInsertWithOrdinal;
    protected LazyPreparedStatement sqlUpdateWithOrdinal;
    protected LazyPreparedStatement sqlDeleteWithOrdinal;
    protected LazyPreparedStatement sqlShiftOrdinals;
    protected LazyPreparedStatement sqlFindOrdered;
    protected LazyPreparedStatement sqlFindValueOrdinal;
    
    protected void defineSql()
    {
        super.defineSql();

        // TODO:  assert needSurrogate

        sqlInsertWithOrdinal = new LazyPreparedStatement(
            "insert into " + tableName
            + " values(?,?,?,?)");
        
        sqlUpdateWithOrdinal = new LazyPreparedStatement(
            "update " + tableName + " set " + valColName
            + " = ? where " + keyColName + " = ? and "
            + storage.ORDINAL_COL_NAME + " = ?");
        
        sqlDeleteWithOrdinal = new LazyPreparedStatement(
            "delete from " + tableName
            + " where " + keyColName + " = ?"
            + " and " + storage.ORDINAL_COL_NAME + " = ?");
        
        sqlShiftOrdinals = new LazyPreparedStatement(
            "update " + tableName + " set "
            + storage.ORDINAL_COL_NAME + " = " + storage.ORDINAL_COL_NAME
            + " + ? where " + keyColName + " = ? and "
            + storage.ORDINAL_COL_NAME + " >= ?");

        // NOTE:  keyColName is redundant in ORDER BY, but maybe it improves
        // the chances that even a stupid optimizer will realize it can use the
        // primary key index for ordering.  And if DBMS doesn't support
        // ORDER BY non-selected column (which is non-standard), we
        // extend the select list but ignore the extra columns during fetch.
        String selectOrdered = "select " + valColName;
        boolean orderByUnrelated = false;
        try {
            orderByUnrelated =
                storage.getDatabaseMetaData().supportsOrderByUnrelated();
        } catch (SQLException ex) {
            // assume exception means it doesn't
        }
        if (!orderByUnrelated) {
            selectOrdered = selectOrdered
                + ", " + keyColName + ", " + storage.ORDINAL_COL_NAME;
        }
        sqlFindOrdered = new LazyPreparedStatement(
            selectOrdered + " from " + tableName
            + " where " + keyColName + " = ? order by "
            + keyColName + ", " + storage.ORDINAL_COL_NAME);

        sqlFindValueOrdinal = new LazyPreparedStatement(
            "select " + storage.ORDINAL_COL_NAME + " from " + tableName
            + " where " + keyColName + " = ?"
            + " and " + valColName + " = ?");
    }
    
    // implement MultivaluedOrderedIndex
    public List getItemsOrdered(Object key) throws StorageException
    {
        return new ItemList(key,null);
    }
    
    // implement MultivaluedOrderedIndex
    public Collection getObjectsOrdered(
        Object key, SinglevaluedIndex repos) throws StorageException
    {
        if (keyType == Storage.EntryType.MOFID) {
            return new ItemList(key,repos);
        } else {
            return getItemsOrdered(key);
        }
    }
    
    // implement MultivaluedOrderedIndex
    public void add(Object key, int index, Object value)
        throws StorageException
    {
        addImpl(key,index,value,true);
    }
    
    // override JdbcIndex
    protected void addImpl(Object key, Object value) throws StorageException
    {
        // Have to query to get the current size as the new index.  But as an
        // optimization, there's no need to shift the ordinals of the existing
        // entries.
        int index = getItemsOrdered(key).size();
        addImpl(key,index,value,false);
    }

    private void addImpl(
        Object key, int index, Object value,boolean shiftOrdinals)
        throws StorageException
    {
        if (shiftOrdinals) {
            storage.executeUpdate(
                sqlShiftOrdinals,
                new Object[]{new Integer(1),key,new Integer(index)});
        }
        
        Object [] args = new Object[]{
            key,value,new Integer(index),
            new Long(storage.getSerialNumber())};
        storage.executeUpdate(sqlInsertWithOrdinal,args);
    }

    // implement MultivaluedOrderedIndex
    public boolean remove(Object key, int index)
        throws StorageException
    {
        return removeImpl(key,index,true);
    }
    
    // override JdbcMultivaluedIndex
    public boolean remove(Object key, Object value) throws StorageException
    {
        int index = storage.getSingletonInt(
            sqlFindValueOrdinal,
            new Object[]{key,value});
        if (index == -1) {
            return false;
        }
        remove(key,index);
        return true;
    }
    
    private boolean removeImpl(Object key, int index,boolean shiftOrdinals)
        throws StorageException
    {
        storage.executeUpdate(
            sqlDeleteWithOrdinal,
            new Object[]{key,new Integer(index)});

        if (shiftOrdinals) {
            storage.executeUpdate(
                sqlShiftOrdinals,
                new Object[]{new Integer(-1),key,new Integer(index)});
        }
        
        return true;
    }
    
    // implement MultivaluedOrderedIndex
    public void replace(Object key, int index, Object element)
        throws StorageException
    {
        storage.executeUpdate(
            sqlUpdateWithOrdinal,
            new Object[]{element,key,new Integer(index)});
    }

    private class ItemList extends AbstractSequentialList
    {
        private Object key;
        private SinglevaluedIndex repos;

        ItemList(Object key,SinglevaluedIndex repos)
        {
            this.key = key;
            this.repos = repos;
        }

        // implement AbstractSequentialList
        public ListIterator listIterator(int index)
        {
            try {
                ListIterator iter = new ItemListIter(
                    storage.getResultSetIterator(
                        sqlFindOrdered,
                        new Object[]{key},
                        getValueType()),
                    repos,
                    key);
                while (iter.nextIndex() != index) {
                    iter.next();
                }
                return iter;
            } catch (StorageException ex) {
                throw new RuntimeStorageException(ex);
            }
        }

        // implement AbstractSequentialList
        public int size()
        {
            try {
                return storage.getSingletonInt(sqlFindCount,new Object[]{key});
            } catch (StorageException ex) {
                throw new RuntimeStorageException(ex);
            }
        }
    }

    private class ItemListIter implements ListIterator
    {
        private ListIterator iter;
        private SinglevaluedIndex repos;
        private Object key;
        private int lastPos;

        ItemListIter(
            ListIterator iter,SinglevaluedIndex repos,Object key)
        {
            this.iter = iter;
            this.repos = repos;
            this.key = key;

            lastPos = -1;
        }

        // implement ListIterator
        public void add(Object obj)
        {
            try {
                int index = nextIndex();
                // if at end, no need to shift ordinals
                addImpl(key,index,obj,iter.hasNext());
            } catch (StorageException ex) {
                throw new RuntimeStorageException(ex);
            }
            iter.add(obj);
            lastPos = -1;
        }

        // implement ListIterator
        public boolean hasNext()
        {
            return iter.hasNext();
        }

        // implement ListIterator
        public boolean hasPrevious()
        {
            return iter.hasPrevious();
        }

        private Object getValue(Object obj)
        {
            if (repos != null) {
                try {
                    return repos.get(obj);
                } catch (StorageException ex) {
                    throw new RuntimeStorageException(ex);
                }
            } else {
                return obj;
            }
        }

        // implement ListIterator
        public Object next()
        {
            lastPos = iter.nextIndex();
            return getValue(iter.next());
        }

        // implement ListIterator
        public int nextIndex() 
        {
            return iter.nextIndex();
        }

        // implement ListIterator
        public Object previous()
        {
            lastPos = iter.previousIndex();
            return getValue(iter.previous());
        }

        // implement ListIterator
        public int previousIndex()
        {
            return iter.previousIndex();
        }

        // implement ListIterator
        public void remove()
        {
            if (lastPos == -1) {
                throw new IllegalStateException();
            }
            // remove from iter first, in case we just did a previous() from end
            iter.remove();
            try {
                // if at end, no need to shift ordinals
                removeImpl(
                    key,lastPos,iter.hasNext());
            } catch (StorageException ex) {
                throw new RuntimeStorageException(ex);
            }
            lastPos = -1;
        }

        // implement ListIterator
        public void set(Object obj)
        {
            iter.set(obj);
            try {
                JdbcMultivaluedOrderedIndex.this.replace(
                    key,lastPos,obj);
            } catch (StorageException ex) {
                throw new RuntimeStorageException(ex);
            }
            lastPos = -1;
        }
    }
}

// End JdbcMultivaluedOrderedIndex.java
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.