Package org.apache.ojb.odmg.collections

Source Code of org.apache.ojb.odmg.collections.DListImpl_2

package org.apache.ojb.odmg.collections;

/* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.ojb.broker.ManageableCollection;
import org.apache.ojb.broker.OJBRuntimeException;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerAware;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.core.ValueContainer;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.query.Criteria;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.apache.ojb.odmg.PBCapsule;
import org.apache.ojb.odmg.TransactionImpl;
import org.apache.ojb.odmg.TxManagerFactory;
import org.apache.ojb.odmg.TransactionExt;
import org.apache.ojb.odmg.oql.OQLQueryImpl;
import org.odmg.DArray;
import org.odmg.DCollection;
import org.odmg.DList;
import org.odmg.ODMGRuntimeException;
import org.odmg.OQLQuery;
import org.odmg.QueryInvalidException;
import org.odmg.Transaction;


/**
*
* @author Thomas Mahler
* @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id: DListImpl_2.java,v 1.6.2.1 2005/03/18 19:25:06 arminw Exp $
*/
public class DListImpl_2 extends AbstractList implements DList, DArray,
        ManageableCollection, PersistenceBrokerAware
{
    private static final long serialVersionUID = -9219943066614026526L;
    /*
     * declare transient, because ManageableCollection is {@link java.io.Serializable}.
     */
    private transient Logger log;
    private Integer id;
    private List elements;
    private int size;
    /**
     * PBKey this DList belongs to.
     */
    private PBKey pbKey;

    /**
     * Used by PB-Kernel to instantiate ManageableCollections
     * FOR INTERNAL USE ONLY
     */
    public DListImpl_2()
    {
        super();
        elements = new ArrayList();
        this.size = 0;
    }

    /**
     * Used on odmg-level
     */
    public DListImpl_2(PBKey pbKey)
    {
        this();
        this.pbKey = pbKey;
    }

    protected Logger getLog()
    {
        if (log == null)
        {
            log = LoggerFactory.getLogger(DListImpl_2.class);
        }
        return log;
    }

    private DListEntry_2 prepareEntry(Object obj)
    {
        return new DListEntry_2(this, obj);
    }

    private boolean checkForOpenTransaction(TransactionExt tx)
    {
        boolean result = false;
        if(tx != null && tx.isOpen())
        {
            result = true;
            if(pbKey == null) pbKey = tx.getBroker().getPBKey();
        }
        return result;
    }

    public PBKey getPBKey()
    {
        if(pbKey == null)
        {
            TransactionExt tx = TxManagerFactory.instance().getTransaction();
            if(tx != null) checkForOpenTransaction(tx);
        }
        return pbKey;
    }

    public void setPBKey(PBKey pbKey)
    {
        this.pbKey = pbKey;
    }

    /**
     * Inserts the specified element at the specified position in this list
     * (optional operation).  Shifts the element currently at that position
     * (if any) and any subsequent elements to the right (adds one to their
     * indices).
     *
     * @param index index at which the specified element is to be inserted.
     * @param element element to be inserted.
     *
     * @throws UnsupportedOperationException if the <tt>add</tt> method is not
     * supported by this list.
     * @throws    ClassCastException if the class of the specified element
     * prevents it from being added to this list.
     * @throws    IllegalArgumentException if some aspect of the specified
     * element prevents it from being added to this list.
     * @throws    IndexOutOfBoundsException if the index is out of range
     * (index &lt; 0 || index &gt; size()).
     */
    public void add(int index, Object element)
    {
        DListEntry_2 entry = prepareEntry(element);
        elements.add(index, entry);
        this.size++;
        // if we are in a transaction: acquire locks !
        TransactionImpl tx = TxManagerFactory.instance().getTransaction();
        if (checkForOpenTransaction(tx))
        {
            tx.lock(this, Transaction.WRITE);
            tx.lock(entry, Transaction.WRITE);
            tx.lock(element, Transaction.READ);
            entry.prepareForPersistency(tx.getBroker());
        }

        // changing the position markers of entries:
        int offset = 0;
        try
        {
            offset = ((DListEntry_2) elements.get(index - 1)).getPosition();
        }
        catch (Exception ignored)
        {
        }
        for (int i = offset; i < elements.size(); i++)
        {
            entry = (DListEntry_2) elements.get(i);
            entry.setPosition(i);
        }
    }

    /**
     * Removes the element at the specified position in this list (optional
     * operation).  Shifts any subsequent elements to the left (subtracts one
     * from their indices).  Returns the element that was removed from the
     * list.<p>
     *
     * This implementation always throws an
     * <tt>UnsupportedOperationException</tt>.
     *
     * @param index the index of the element to remove.
     * @return the element previously at the specified position.
     *
     * @throws UnsupportedOperationException if the <tt>remove</tt> method is
     *      not supported by this list.
     * @throws IndexOutOfBoundsException if the specified index is out of
     *       range (<tt>index &lt; 0 || index &gt;= size()</tt>).
     */
    public Object remove(int index)
    {
        DListEntry_2 entry = (DListEntry_2) elements.get(index);
        // if we are in a transaction: acquire locks !
        TransactionImpl tx = TxManagerFactory.instance().getTransaction();
        if (checkForOpenTransaction(tx))
        {
            tx.markDelete(entry);
        }
        this.size--;
        elements.remove(index);
        // changing the position markers of entries:
        int offset = 0;
        try
        {
            offset = ((DListEntry_2) elements.get(index)).getPosition();
        }
        catch (Exception ignored)
        {
        }
        for (int i = offset; i < elements.size(); i++)
        {
            entry = (DListEntry_2) elements.get(i);
            entry.setPosition(i);
        }

        return entry.getRealSubject();
    }

    /**
     * Creates a new <code>DList</code> object that contains the contents of this
     * <code>DList</code> object concatenated
     * with the contents of the <code>otherList</code> object.
     * @param  otherList  The list whose elements are placed at the end of the list
     * returned by this method.
     * @return  A new <code>DList</code> that is the concatenation of this list and
     * the list referenced by <code>otherList</code>.
     */
    public DList concat(DList otherList)
    {
        DListImpl_2 result = new DListImpl_2(pbKey);
        result.addAll(this);
        result.addAll(otherList);
        return result;
    }

    /**
     * Determines whether there is an element of the collection that evaluates to true
     * for the predicate.
     * @param  predicate  An OQL boolean query predicate.
     * @return  True if there is an element of the collection that evaluates to true
     * for the predicate, otherwise false.
     * @exception  org.odmg.QueryInvalidException  The query predicate is invalid.
     */
    public boolean existsElement(String predicate) throws org.odmg.QueryInvalidException
    {
        DList results = (DList) this.query(predicate);
        if (results == null || results.size() == 0)
            return false;
        else
            return true;
    }

    /**
     * Returns the element at the specified position in this list.
     *
     * @param index index of element to return.
     * @return the element at the specified position in this list.
     *
     * @throws IndexOutOfBoundsException if the index is out of range (index
     * &lt; 0 || index &gt;= size()).
     */
    public Object get(int index)
    {
        DListEntry_2 entry = (DListEntry_2) elements.get(index);
        return entry.getRealSubject();
    }

    /**
     * Insert the method's description here.
     * Creation date: (10.02.2001 20:53:01)
     * @return java.util.Vector
     */
    public List getElements()
    {
        return elements;
    }

    /**
     * Lazily return the Id, no point in precomputing it.
     * @return int
     */
    public Integer getId()
    {
        return id;
    }

    /**
     * Returns an iterator over the elements in this collection.  There are no
     * guarantees concerning the order in which the elements are returned
     * (unless this collection is an instance of some class that provides a
     * guarantee).
     *
     * @return an <tt>Iterator</tt> over the elements in this collection
     */
    public Iterator iterator()
    {
        return new DListIterator_2(this);
    }

    /**
     * Returns a list iterator of the elements in this list (in proper
     * sequence).
     *
     * @return a list iterator of the elements in this list (in proper
     * sequence).
     */
    public ListIterator listIterator()
    {
        return new DListIterator_2(this);
    }

    /**
     * Returns a list iterator of the elements in this list (in proper
     * sequence), starting at the specified position in this list.  The
     * specified index indicates the first element that would be returned by
     * an initial call to the <tt>next</tt> method.  An initial call to
     * the <tt>previous</tt> method would return the element with the
     * specified index minus one.
     *
     * @param index index of first element to be returned from the
     * list iterator (by a call to the <tt>next</tt> method).
     * @return a list iterator of the elements in this list (in proper
     * sequence), starting at the specified position in this list.
     * @throws IndexOutOfBoundsException if the index is out of range (index
     * &lt; 0 || index &gt; size()).
     */
    public ListIterator listIterator(int index)
    {
        return new DListIterator_2(this, index);
    }

    private Criteria getPkCriteriaForAllElements(PersistenceBroker brokerForClass)
    {
        try
        {
            Criteria crit = null;
            for (int i = 0; i < elements.size(); i++)
            {
                DListEntry_2 entry = (DListEntry_2) elements.get(i);
                Object obj = entry.getRealSubject();
                ClassDescriptor cld = brokerForClass.getClassDescriptor(obj.getClass());

                FieldDescriptor[] pkFields = cld.getPkFields();
                ValueContainer[] pkValues = brokerForClass.serviceBrokerHelper().getKeyValues(cld, obj);

                Criteria criteria = new Criteria();
                for (int j = 0; j < pkFields.length; j++)
                {
                    FieldDescriptor fld = pkFields[j];
                    criteria.addEqualTo(fld.getPersistentField().getName(), pkValues[j].getValue());
                }

                if (crit == null)
                    crit = criteria;
                else
                    crit.addOrCriteria(criteria);
            }
            return crit;
        }
        catch (PersistenceBrokerException e)
        {
            return null;
        }
    }

    private Class getElementsExtentClass(PersistenceBroker brokerForClass) throws PersistenceBrokerException
    {
        // we ll have to compute the most general extent class here !!!
        DListEntry_2 entry = (DListEntry_2) elements.get(0);
        Class elementsClass = entry.getRealSubject().getClass();
        Class extentClass = brokerForClass.getTopLevelClass(elementsClass);
        return extentClass;
    }

    /**
     * Evaluate the boolean query predicate for each element of the collection and
     * return a new collection that contains each element that evaluated to true.
     * @param  predicate  An OQL boolean query predicate.
     * @return  A new collection containing the elements that evaluated true for the predicate.
     * @exception  org.odmg.QueryInvalidException  The query predicate is invalid.
     */
    public DCollection query(String predicate) throws QueryInvalidException
    {
        // 1.build complete OQL statement
        String oql = "select all from java.lang.Object where " + predicate;
        /*TODO: Use a ObjectFactory to instantiate OQLQuery? */
        OQLQuery predicateQuery = new OQLQueryImpl(pbKey, this.getClass());
        predicateQuery.create(oql);
        Query pQ = ((OQLQueryImpl) predicateQuery).getQuery();
        Criteria pCrit = pQ.getCriteria();

        Transaction tx = TxManagerFactory.instance().getTransaction();
        if (tx == null) throw new QueryInvalidException("Need running transaction to do query");
        PBCapsule handle = new PBCapsule(pbKey, tx);
        DList result;
        try
        {
            PersistenceBroker broker = handle.getBroker();
            Criteria allElementsCriteria = this.getPkCriteriaForAllElements(broker);
            // join selection of elements with predicate criteria:
            allElementsCriteria.addAndCriteria(pCrit);

            Class clazz = null;
            try
            {
                clazz = this.getElementsExtentClass(broker);
            }
            catch (PersistenceBrokerException e)
            {
                throw new ODMGRuntimeException(e.getMessage());
            }
            Query q = new QueryByCriteria(clazz, allElementsCriteria);
            if (getLog().isDebugEnabled()) getLog().debug(q.toString());

            result = null;
            try
            {
                result = (DList) broker.getCollectionByQuery(DListImpl_2.class, q);
            }
            catch (PersistenceBrokerException e)
            {
                getLog().error("Query failed", e);
                throw new OJBRuntimeException(e);
            }
        }
        finally
        {
            // cleanup stuff
            if (handle != null) handle.destroy();
        }

        // 3. return resulting collection
        return result;

    }

    public int hashCode()
    {
        int hashCode = 1;
        Iterator it = elements.iterator();
        while (it.hasNext())
        {
            Object obj = it.next();
            hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
        }
        return hashCode;
    }

    public String toString()
    {
        ToStringBuilder buf = new ToStringBuilder(this);
        buf.append("id", id);
        buf.append("pbKey", pbKey);
        buf.append("size", size);
        buf.append("[containing elements: ");
        Iterator it = elements.iterator();
        while (it.hasNext())
        {
            Object obj = it.next();
            buf.append(obj != null ? obj.toString() : null);
        }
        buf.append("]");
        return buf.toString();
    }

    /**
     * Access all of the elements of the collection that evaluate to true for the
     * provided query predicate.
     * @param  predicate  An OQL boolean query predicate.
     * @return  An iterator used to iterate over the elements that evaluated true for the predicate.
     * @exception  org.odmg.QueryInvalidException  The query predicate is invalid.
     */
    public Iterator select(String predicate) throws org.odmg.QueryInvalidException
    {
        return this.query(predicate).iterator();
    }

    /**
     * Selects the single element of the collection for which the provided OQL query
     * predicate is true.
     * @param  predicate  An OQL boolean query predicate.
     * @return The element that evaluates to true for the predicate. If no element
     * evaluates to true, null is returned.
     * @exception  org.odmg.QueryInvalidException  The query predicate is invalid.
     */
    public Object selectElement(String predicate) throws org.odmg.QueryInvalidException
    {
        return ((DList) this.query(predicate)).get(0);
    }

    /**
     * Returns the number of elements in this collection.  If this collection
     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
     * <tt>Integer.MAX_VALUE</tt>.
     *
     * @return the number of elements in this collection
     */
    public int size()
    {
        return elements.size();
    }

    /**
     * add a single Object to the Collection. This method is used during reading Collection elements
     * from the database. Thus it is is save to cast anObject to the underlying element type of the
     * collection.
     */
    public void ojbAdd(Object anObject)
    {
        this.size++;
        DListEntry_2 entry = prepareEntry(anObject);
        entry.setPosition(elements.size());
        elements.add(entry);
    }

    /**
     * adds a Collection to this collection. Used in reading Extents from the Database.
     * Thus it is save to cast otherCollection to this.getClass().
     */
    public void ojbAddAll(ManageableCollection otherCollection)
    {
        // don't use this to avoid locking
        // this.addAll((DListImpl_2) otherCollection);
        Iterator it = otherCollection.ojbIterator();
        while (it.hasNext())
        {
            ojbAdd(it.next());
        }
    }

    public void afterStore(PersistenceBroker broker) throws PersistenceBrokerException
    {
    }

    /**
     * returns an Iterator over all elements in the collection. Used during store and delete Operations.
     * If the implementor does not return an iterator over ALL elements, OJB cannot store and delete all elements properly.
     */
    public Iterator ojbIterator()
    {
        return this.iterator();
    }

    /**
     * Resize the array to have <code>newSize</code> elements.
     * @param  newSize  The new size of the array.
     */
    public void resize(int newSize)
    {
    }

    /**
     * Sets the elements.
     * @param elements The elements to set
     */
    public void setElements(List elements)
    {
        this.elements = elements;
    }

    /**
     * Sets the id.
     * @param id The id to set
     */
    public void setId(Integer id)
    {
        this.id = id;
    }

    /**
     * Gets the size.
     * @return Returns a int
     */
    public int getSize()
    {
        return size;
    }

    /**
     * Sets the size.
     * @param size The size to set
     */
    public void setSize(int size)
    {
        this.size = size;
    }


    //***************************************************************
    // PersistenceBrokerAware interface
    //***************************************************************

    /**
     * prepare itself for persistence. Each DList entry generates an
     * {@link org.apache.ojb.broker.Identity} for the wrapped persistent
     * object.
     */
    public void beforeInsert(PersistenceBroker broker) throws PersistenceBrokerException
    {
        Iterator it = elements.iterator();
        DListEntry_2 entry;
        while (it.hasNext())
        {
            entry = (DListEntry_2) it.next();
            entry.prepareForPersistency(broker);
        }
    }

    /**
     * noop
     */
    public void beforeUpdate(PersistenceBroker broker) throws PersistenceBrokerException
    {
    }

    /**
     * noop
     */
    public void beforeDelete(PersistenceBroker broker) throws PersistenceBrokerException
    {
    }

    /**
     * noop
     */
    public void afterUpdate(PersistenceBroker broker) throws PersistenceBrokerException
    {
    }

    /**
     * noop
     */
    public void afterInsert(PersistenceBroker broker) throws PersistenceBrokerException
    {
    }

    /**
     * noop
     */
    public void afterDelete(PersistenceBroker broker) throws PersistenceBrokerException
    {
    }

    /**
     * noop
     */
    public void afterLookup(PersistenceBroker broker) throws PersistenceBrokerException
    {
    }
}
TOP

Related Classes of org.apache.ojb.odmg.collections.DListImpl_2

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.