Package org.apache.ojb.odmg.collections

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

package org.apache.ojb.odmg.collections;

/* Copyright 2002-2005 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.io.Serializable;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.Collection;

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.ManageableCollection;
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.RuntimeObject;
import org.apache.ojb.odmg.oql.OQLQueryImpl;
import org.odmg.DCollection;
import org.odmg.DList;
import org.odmg.DSet;
import org.odmg.ODMGRuntimeException;
import org.odmg.OQLQuery;
import org.odmg.Transaction;


/**
*
*/
public class DSetImpl extends AbstractSet implements DSet, Serializable, PersistenceBrokerAware, ManageableCollection
{
  private static final long serialVersionUID = -4459673364598652639L;

    private transient Logger log;

    private Integer id;
    private List elements;

    private PBKey pbKey;

    /**
     * Used by PB-Kernel to instantiate ManageableCollections
     * FOR INTERNAL USE ONLY
     */
    public DSetImpl()
    {
        super();
        elements = new ArrayList();
//        if(getTransaction() == null)
//        {
//            throw new TransactionNotInProgressException("Materialization of DCollection instances must be done" +
//                    " within a odmg-tx");
//        }
        getPBKey();
    }

    /**
     * DSetImpl constructor comment.
     */
    public DSetImpl(PBKey pbKey)
    {
        this();
        this.pbKey = pbKey;
    }

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

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

    protected TransactionImpl getTransaction()
    {
        return TxManagerFactory.instance().getTransaction();
    }

    protected boolean checkForOpenTransaction(TransactionImpl tx)
    {
        boolean result = false;
        if(tx != null && tx.isOpen())
        {
            result = true;
        }
        return result;
    }

    public PBKey getPBKey()
    {
        if(pbKey == null)
        {
            TransactionImpl tx = getTransaction();
            if(tx != null && tx.isOpen())
            {
                pbKey = tx.getBroker().getPBKey();
            }
        }
        return pbKey;
    }

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

    public boolean remove(Object o)
    {
        return super.remove(o);
    }

    public boolean removeAll(Collection c)
    {
        return super.removeAll(c);
    }

    public boolean add(Object o)
    {
        if (!this.contains(o))
        {
            DSetEntry entry = prepareEntry(o);
            elements.add(entry);
            // if we are in a transaction: get locks !
            TransactionImpl tx = getTransaction();
            if ((tx != null) && (tx.isOpen()))
            {
                List regList = tx.getRegistrationList();
                RuntimeObject rt = new RuntimeObject(this, tx);
                tx.lockAndRegister(rt, Transaction.WRITE, false, regList);

                rt = new RuntimeObject(o, tx);
                tx.lockAndRegister(rt, Transaction.READ, regList);

                rt = new RuntimeObject(entry, tx, true);
                tx.lockAndRegister(rt, Transaction.WRITE, false, regList);
            }
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * Create a new <code>DSet</code> object that contains the elements of this
     * collection minus the elements in <code>otherSet</code>.
     * @param  otherSet  A set containing elements that should not be in the result set.
     * @return  A newly created <code>DSet</code> instance that contains the elements
     * of this set minus those elements in <code>otherSet</code>.
     */
    public DSet difference(DSet otherSet)
    {
        DSetImpl result = new DSetImpl(getPBKey());
        Iterator iter = this.iterator();
        while (iter.hasNext())
        {
            Object candidate = iter.next();
            if (!otherSet.contains(candidate))
            {
                result.add(candidate);
            }
        }
        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;
    }

    public List getElements()
    {
        return elements;
    }

    public void setElements(List elements)
    {
        this.elements = elements;
    }

    public Integer getId()
    {
        return id;
    }

    /**
     * Create a new <code>DSet</code> object that is the set intersection of this
     * <code>DSet</code> object and the set referenced by <code>otherSet</code>.
     * @param  otherSet  The other set to be used in the intersection operation.
     * @return  A newly created <code>DSet</code> instance that contains the
     * intersection of the two sets.
     */
    public DSet intersection(DSet otherSet)
    {
        DSet union = this.union(otherSet);
        DSetImpl result = new DSetImpl(getPBKey());
        Iterator iter = union.iterator();
        while (iter.hasNext())
        {
            Object candidate = iter.next();
            if (this.contains(candidate) && otherSet.contains(candidate))
            {
                result.add(candidate);
            }
        }
        return result;
    }

    /**
     * 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 DSetIterator(this);
    }

    /**
     * Determine whether this set is a proper subset of the set referenced by
     * <code>otherSet</code>.
     * @param  otherSet  Another set.
     * @return True if this set is a proper subset of the set referenced by
     * <code>otherSet</code>, otherwise false.
     */
    public boolean properSubsetOf(org.odmg.DSet otherSet)
    {
        return (this.size() > 0 && this.size() < otherSet.size() && this.subsetOf(otherSet));
    }

    /**
     * Determine whether this set is a proper superset of the set referenced by
     * <code>otherSet</code>.
     * @param  otherSet  Another set.
     * @return True if this set is a proper superset of the set referenced by
     * <code>otherSet</code>, otherwise false.
     */
    public boolean properSupersetOf(org.odmg.DSet otherSet)
    {
        return (otherSet.size() > 0 && otherSet.size() < this.size() && this.supersetOf(otherSet));
    }

    /**
     * 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 org.odmg.QueryInvalidException
    {
        // 1.build complete OQL statement
        String oql = "select all from java.lang.Object where " + predicate;
        TransactionImpl tx = getTransaction();

        OQLQuery predicateQuery = tx.getImplementation().newOQLQuery();

        PBCapsule capsule = new PBCapsule(tx.getImplementation().getCurrentPBKey(), tx);
        PersistenceBroker broker = capsule.getBroker();

        try
        {
            predicateQuery.create(oql);
            Query pQ = ((OQLQueryImpl) predicateQuery).getQuery();
            Criteria pCrit = pQ.getCriteria();

            Criteria allElementsCriteria = this.getPkCriteriaForAllElements(broker);
            // join selection of elements with predicate criteria:
            pCrit.addAndCriteria(allElementsCriteria);
            Class clazz = this.getElementsExtentClass(broker);
            Query q = new QueryByCriteria(clazz, pCrit);
            if (log.isDebugEnabled()) log.debug(q.toString());
            // 2. perfom query
            return (DSetImpl) broker.getCollectionByQuery(DSetImpl.class, q);
        }
        catch (PersistenceBrokerException e)
        {
            throw new ODMGRuntimeException(e.getMessage());
        }
        finally
        {
            capsule.destroy();
        }
    }

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

                FieldDescriptor[] pkFields = cld.getPkFields();
                ValueContainer[] pkValues = broker.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)
        {
            log.error(e);
            return null;
        }
    }

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


    /**
     * 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);
    }

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

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

    /**
     * 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();
    }

    /**
     * Determine whether this set is a subset of the set referenced by <code>otherSet</code>.
     * @param  otherSet  Another set.
     * @return True if this set is a subset of the set referenced by <code>otherSet</code>,
     * otherwise false.
     */
    public boolean subsetOf(DSet otherSet)
    {
        return otherSet.containsAll(this);
    }

    /**
     * Determine whether this set is a superset of the set referenced by <code>otherSet</code>.
     * @param  otherSet  Another set.
     * @return True if this set is a superset of the set referenced by <code>otherSet</code>,
     * otherwise false.
     */
    public boolean supersetOf(DSet otherSet)
    {
        return this.containsAll(otherSet);
    }

    /**
     * Create a new <code>DSet</code> object that is the set union of this
     * <code>DSet</code> object and the set referenced by <code>otherSet</code>.
     * @param  otherSet  The other set to be used in the union operation.
     * @return  A newly created <code>DSet</code> instance that contains the union of the two sets.
     */
    public DSet union(DSet otherSet)
    {
        DSetImpl result = new DSetImpl(getPBKey());
        result.addAll(this);
        result.addAll(otherSet);
        return result;
    }


    //***************************************************************
    // ManageableCollection interface
    //***************************************************************

    /**
     * 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)
    {
        DSetEntry 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) 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();
    }

    //***************************************************************
    // 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();
//        DSetEntry entry;
//        while (it.hasNext())
//        {
//            entry = (DSetEntry) 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.DSetImpl

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.