/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. 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
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. 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 packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* 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 don't 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.
*/
/*
* EJBHashSet.java
*
* Created on December 10, 2001
*/
package com.sun.jdo.spi.persistence.support.ejb.cmp;
import java.util.*;
import javax.ejb.EJBLocalObject;
import com.sun.jdo.api.persistence.support.PersistenceManager;
import com.sun.jdo.api.persistence.support.Transaction;
import com.sun.jdo.spi.persistence.support.sqlstore.ejb.JDOEJB20Helper;
import com.sun.jdo.spi.persistence.utility.logging.Logger;
import com.sun.jdo.spi.persistence.support.sqlstore.LogHelperSQLStore;
/*
* This is the implementation of the java.util.Set interface for the CMP
* fields of the Collection type. Represents many side of the relationships.
*
* @author Marina Vatkina
*/
public class EJBHashSet extends HashSet {
// Reference to the PersistenceManager and Transaction that were active
// at the time of this Set creation.
private PersistenceManager pm = null;
private Transaction tx = null;
// HashSet of the persistence-capable instances associated with this Set.
private HashSet pcSet = null;
// Helper instance for conversion of the persistence-capable instances
// to the EJBLocalObject type and back.
private JDOEJB20Helper helper = null;
// Flag that indicates invalid state of this Set.
private boolean valid = false;
//The logger
private static Logger logger = LogHelperSQLStore.getLogger();
/**
* Creates new instance of <code>EJBHashSet</code> for this parameters.
* @param pm the PersistenceManager associated with the calling bean.
* @param helper the JDOEJB20Helper instance.
* @param pcs a Collection of persistence-capable instances.
*/
public EJBHashSet(PersistenceManager pm, JDOEJB20Helper helper, Collection pcs) {
this.pm = pm;
tx = pm.currentTransaction();
this.helper = helper;
// Convert Collection.
setSCOHashSet(pcs);
valid = true;
}
// -------------------------Public Methods------------------
/**
* Adds the specified element to this set if it is not already
* present.
*
* @param o element to be added to this set.
* @return <tt>true</tt> if the set did not already contain the specified
* element.
* @see java.util.HashSet
*/
public boolean add(Object o) {
logger.finest("---EJBHashSet.add---"); // NOI18N
assertIsValid();
assertInTransaction();
helper.assertInstanceOfLocalInterfaceImpl(o);
Object pc = helper.convertEJBLocalObjectToPC((EJBLocalObject) o, pm, true);
return pcSet.add(pc);
}
/**
* Adds all of the elements in the specified collection to this collection
*
* @param c collection whose elements are to be added to this collection.
* @return <tt>true</tt> if this collection changed as a result of the
* call.
* @throws UnsupportedOperationException if the <tt>addAll</tt> method is
* not supported by this collection.
*
* @see java.util.AbstractCollection
* @see java.util.HashSet
*/
public boolean addAll(Collection c) {
logger.finest("---EJBHashSet.addAll---"); // NOI18N
assertIsValid();
assertInTransaction();
assertInstancesOfLocalInterfaceImpl(c);
return pcSet.addAll(helper.convertCollectionEJBLocalObjectToPC(c, pm, true));
}
/**
* Removes the given element from this set if it is present.
*
* @param o object to be removed from this set, if present.
* @return <tt>true</tt> if the set contained the specified element.
* @see java.util.HashSet
*/
public boolean remove(Object o) {
logger.finest("---EJBHashSet.remove---"); // NOI18N
assertIsValid();
assertInTransaction();
helper.assertInstanceOfLocalInterfaceImpl(o);
EJBLocalObject lo = (EJBLocalObject) o;
return pcSet.remove(helper.convertEJBLocalObjectToPC(lo, pm, true));
}
/**
* Removes from this collection all of its elements that are contained in
* the specified collection (optional operation). <p>
* Processes each element remove internally not to have call backs
* into #remove(Object).
*
* @param c elements to be removed from this collection.
* @return <tt>true</tt> if this collection changed as a result of the
* call.
*
* @throws UnsupportedOperationException removeAll is not supported
* by this collection.
*
* @see java.util.HashSet
* @see java.util.AbstractCollection
*/
public boolean removeAll(Collection c) {
logger.finest("---EJBHashSet.removeAll---"); // NOI18N
assertIsValid();
assertInTransaction();
assertInstancesOfLocalInterfaceImpl(c);
return pcSet.removeAll(helper.convertCollectionEJBLocalObjectToPC(c, pm, true));
}
/**
* Retains only the elements in this collection that are contained in the
* specified collection (optional operation).
*
* @return <tt>true</tt> if this collection changed as a result of the
* call.
*
* @throws UnsupportedOperationException if the <tt>retainAll</tt> method
* is not supported by this collection.
*
* @see java.util.HashSet
* @see java.util.AbstractCollection
*/
public boolean retainAll(Collection c) {
logger.finest("---EJBHashSet.retainAll---"); // NOI18N
assertIsValid();
assertInTransaction();
assertInstancesOfLocalInterfaceImpl(c);
return pcSet.retainAll(helper.convertCollectionEJBLocalObjectToPC(c, pm, true));
}
/**
* Removes all of the elements from this set.
* @see java.util.HashSet
*/
public void clear() {
logger.finest("---EJBHashSet.clear---"); // NOI18N
assertIsValid();
assertInTransaction();
pcSet.clear();
}
/**
* Returns the number of elements in this set (its cardinality).
*
* @return the number of elements in this set (its cardinality).
*/
public int size() {
logger.finest("---EJBHashSet.size---"); // NOI18N
assertIsValid();
assertInTransaction();
return pcSet.size();
}
/**
* Returns <tt>true</tt> if this set contains no elements.
*
* @return <tt>true</tt> if this set contains no elements.
*/
public boolean isEmpty() {
logger.finest("---EJBHashSet.isEmpty---"); // NOI18N
assertIsValid();
assertInTransaction();
return pcSet.isEmpty();
}
/**
* Returns <tt>true</tt> if this set contains the specified element.
*
* @param o element whose presence in this set is to be tested.
* @return <tt>true</tt> if this set contains the specified element.
*/
public boolean contains(Object o) {
logger.finest("---EJBHashSet.contains---"); // NOI18N
assertIsValid();
assertInTransaction();
helper.assertInstanceOfLocalInterfaceImpl(o);
EJBLocalObject lo = (EJBLocalObject) o;
return pcSet.contains(helper.convertEJBLocalObjectToPC(lo, pm, true));
}
/**
* Returns <tt>true</tt> if this collection contains all of the elements
* in the specified collection. <p>
*
* This implementation iterates over the specified collection, checking
* each element returned by the iterator in turn to see if it's
* contained in this collection. If all elements are so contained
* <tt>true</tt> is returned, otherwise <tt>false</tt>.
*
* @param c collection to be checked for containment in this collection.
* @return <tt>true</tt> if this collection contains all of the elements
* in the specified collection.
*
* @see #contains(Object)
*/
public boolean containsAll(Collection c) {
logger.finest("---EJBHashSet.containsAll---"); // NOI18N
assertIsValid();
assertInTransaction();
assertInstancesOfLocalInterfaceImpl(c);
return pcSet.containsAll(helper.convertCollectionEJBLocalObjectToPC(c, pm, true));
}
/**
* Returns a shallow copy of this <tt>HashSet</tt> instance: the elements
* themselves are not cloned.
*
* @return a shallow copy of this set.
*/
public Object clone() {
logger.finest("---EJBHashSet.clone---"); // NOI18N
EJBHashSet newSet = (EJBHashSet)super.clone();
newSet.pcSet = (HashSet)pcSet.clone();
return newSet;
}
/**
* Returns set of the persistence-capable instances associated
* with this Set.
* @return Set of the persistence-capable instances.
*/
public HashSet getSCOHashSet() {
assertIsValid();
assertInTransaction();
return (pcSet != null) ? (HashSet)pcSet.clone() : null;
}
/**
* Replace the set of the persistence-capable instances associated
* with this EJBHashSet.
* There is no need to check transaction as it has already been checked
* in this case.
*/
public void setSCOHashSet(Collection coll) {
if (coll instanceof java.util.HashSet)
pcSet = (java.util.HashSet)coll;
else
pcSet = new java.util.HashSet(coll);
}
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set.
* @see ConcurrentModificationException
*/
public Iterator iterator() {
assertIsValid();
assertInTransaction();
return new EJBHashIterator();
}
private class EJBHashIterator implements Iterator {
Iterator _iterator = null;
Object lastReturned = null;
EJBHashIterator() {
_iterator = pcSet.iterator();
}
public boolean hasNext() {
assertIsValid();
assertInTransaction();
return _iterator.hasNext();
}
public Object next() {
assertIsValid();
assertInTransaction();
try {
lastReturned = _iterator.next();
} catch(ConcurrentModificationException e) {
IllegalStateException ise = new IllegalStateException(
e.toString());
ise.initCause(e);
throw ise;
}
return helper.convertPCToEJBLocalObject(lastReturned, pm);
}
public void remove() {
assertIsValid();
assertInTransaction();
try {
_iterator.remove();
} catch(ConcurrentModificationException e) {
IllegalStateException ise = new IllegalStateException(
e.toString());
ise.initCause(e);
throw ise;
}
}
}
/**
* Verifies that this Set is not marked as invalid.
* @throw IllegalStateException of validation fails.
*/
private void assertIsValid() {
if (!valid)
throw new IllegalStateException(); // RESOLVE Exception text.
}
/**
* Verifies that persistence manager is not closed and
* the current transaction is active.
* @throw IllegalStateException of validation fails.
*/
private void assertInTransaction() {
if (pm.isClosed() || !tx.isActive()) {
invalidate();
throw new IllegalStateException(); // RESOLVE Exception text.
}
}
/**
* Verifies that elements of this Collection are of the expected type.
* @param c the Collection to verify.
* @throw EJBException of validation fails.
*/
private void assertInstancesOfLocalInterfaceImpl(Collection c) {
for (Iterator it = c.iterator(); it.hasNext();)
helper.assertInstanceOfLocalInterfaceImpl(it.next());
}
/**
* Marks this Set as invalid and releases all references.
*/
public void invalidate() {
valid = false;
pm = null;
tx = null;
helper = null;
pcSet = null;
}
}