/* * Created on Jul 14, 2004 * * The source code contained in this file is in in the public domain. * It can be used in any project, or product without prior permission, * license or royalty payments. There is no claim of correctness and * NO WARRANTY OF ANY KIND provided with this code. */ package org.mobicents.slee.runtime.sbbentity; import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.slee.ChildRelation; import javax.slee.CreateException; import javax.slee.SLEEException; import javax.slee.SbbLocalObject; import javax.slee.TransactionRequiredLocalException; import javax.transaction.SystemException; import org.apache.log4j.Logger; import org.mobicents.slee.container.SleeContainer; import org.mobicents.slee.container.component.deployment.jaxb.descriptors.sbb.MGetChildRelationMethod; import org.mobicents.slee.runtime.sbb.SbbLocalObjectConcrete; import org.mobicents.slee.runtime.sbb.SbbLocalObjectImpl; import org.mobicents.slee.runtime.transaction.SleeTransactionManager; /** * * Implements the ChildRelation interface * * @author F.Moggia * @author M. Ranganathan * @author Ralf Siedow * @author eduardomartins * * */ public class ChildRelationImpl implements ChildRelation, Serializable { /** * */ private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(ChildRelationImpl.class); private static final SleeContainer sleeContainer = SleeContainer.lookupFromJndi(); private MGetChildRelationMethod getChildRelationMethod; private SbbEntity sbbEntity; private HashSet<SbbLocalObject> getLocalObjects() { HashSet<SbbLocalObject> localObjects = new HashSet<SbbLocalObject>(); for (Iterator it = sbbEntity.cacheData.getChildRelationSbbEntities(getChildRelationMethod).iterator(); it.hasNext();) { String sbbEntityId = (String) it.next(); localObjects.add(SbbEntityFactory.getSbbEntity(sbbEntityId).createSbbLocalObject()); } return localObjects; } /** * Creates a new instance of a child relation * @param getChildRelationMethod the child relation method * @param sbbEntity the sbb entity that owns this child relation */ public ChildRelationImpl(MGetChildRelationMethod getChildRelationMethod, SbbEntity sbbEntity) { if (getChildRelationMethod == null) throw new NullPointerException("null getChildRelationMethod"); this.sbbEntity = sbbEntity; this.getChildRelationMethod = getChildRelationMethod; } public Iterator iterator() { return new ChildRelationIterator(); } /** * The contains method. This method returns true if the SBB entity * represented by the SBB local object specified by the input argument is a * member of this child relation. If the method argument is not an SBB local * object, is an invalid SBB local object, or is an SBB local object whose * underlying SBB entity is not a member of this child relation, then this * method returns false. * */ public boolean contains(Object object) { if (!(object instanceof SbbLocalObject)) return false; SbbLocalObjectImpl sbblocal = (SbbLocalObjectImpl) object; String sbbEntityId = sbblocal.getSbbEntityId(); return sbbEntity.cacheData.childRelationHasSbbEntity(getChildRelationMethod, sbbEntityId); } /* * (non-Javadoc) * * @see javax.slee.ChildRelation#create() */ public SbbLocalObject create() throws CreateException, TransactionRequiredLocalException, SLEEException { SleeTransactionManager sleeTransactionManager = SleeContainer.lookupFromJndi().getTransactionManager(); sleeTransactionManager.mandateTransaction(); SbbEntity childSbbEntity = SbbEntityFactory.createSbbEntity( this.getChildRelationMethod.getSbbID(), this.sbbEntity.getServiceId(), this.sbbEntity.getSbbEntityId(), this.getChildRelationMethod.getChildRelationMethodName(), this.sbbEntity.getRootSbbId(), this.sbbEntity.getServiceConvergenceName()); if (logger.isDebugEnabled()) logger.debug("ChildRelation.create() : Created Sbb Entity: " + childSbbEntity.getSbbEntityId()); childSbbEntity.setPriority(getChildRelationMethod.getDefaultPriority()); /* * Exception handling here must follow Sec. 9.12.1 of spec * This is a non-slee originated method invocation * * If a non-SLEE originated method invocation returns by throwing a checked exception, then the following * occurs: * � The state of the transaction is unaffected * � The checked exception is propagated to the caller. * It is expected that the caller will have the appropriate logic to handle the exception. * If a non-SLEE originated method invocation returns by throwing a RuntimeException, then: * � The transaction is marked for rollback. * � The SBB object that was invoked is discarded, i.e. is moved to the Does Not Exist state. * � A javax.slee.TransactionRolledBackLocalException is propagated to the caller. * The transaction will eventually be rolled back when the highest level SLEE originated invocation re-turns * as described in Section 9.12.2. * The sbbRolledBack method is not invoked for an SBB originated method transaction because the * transa ction is only marked for rollback and will only be rolled back when the highest level SLEE * originated invocation returns. The sbbRolledBack method is only invoked on the SBB entity in-voked * by the highest level SLEE originated invocation. * If the RuntimeException propagates to the highest level (i.e. the SLEE originated method invocation * returns by throwing a RuntimeException) the SLEE originated method invocation exception handling * mechanism is init iated. */ try { //All checked exceptions (i.e. CreateException) are propagated to the caller childSbbEntity.assignSbbObject(); } catch ( CreateException e) { // All RuntimeExceptions are dealt with here if ( logger.isDebugEnabled()) logger.error("Caught CreateException in creating child entity", e); childSbbEntity.trashObject(); // Propagate exception to caller. throw e; } catch ( Exception e) { //All RuntimeExceptions are dealt with here logger.error("Caught RuntimeException in creating child entity", e); try { sleeTransactionManager.setRollbackOnly(); } catch (SystemException e1) { logger.error("Failed to set rollbackonly", e); } childSbbEntity.trashObject(); } sbbEntity.cacheData.addChildRelationSbbEntity(getChildRelationMethod,childSbbEntity.getSbbEntityId()); sbbEntity.addChildWithSbbObject(childSbbEntity); return childSbbEntity.createSbbLocalObject(); } /* * (non-Javadoc) * * @see java.util.Collection#size() */ public int size() { return sbbEntity.cacheData.childRelationSbbEntitiesSize(getChildRelationMethod); } /* * (non-Javadoc) * * @see java.util.Collection#clear() */ public void clear() { sleeContainer.getTransactionManager().mandateTransaction(); for (Iterator it = iterator();it.hasNext();) { it.next(); it.remove(); } } /* * (non-Javadoc) * * @see java.util.Collection#isEmpty() */ public boolean isEmpty() { return size() == 0; } /* * (non-Javadoc) * * @see java.util.Collection#toArray() */ public Object[] toArray() { sleeContainer.getTransactionManager().mandateTransaction(); return this.getLocalObjects().toArray(); } /** * This operation is not supported ( see page 62 ) of the spec. The add * methods add and addAll. Any attempts to add to the child relation using * these methods result in a java.lang. UnsupportedOperationException. For * example, the SLEE must throw the UnsupportedOperationException when these * methods are invoked with arguments that add to the collection. o An * invocation of an add method that has no effect on the collection, such as * invoking the addAll method with an empty collection may or may not throw * an UnsupportedOperationException . The create method of the ChildRelation * interface should be used to create a child SBB entity. This causes the * SLEE to automatically add an SBB local object that represents the newly * created SBB entity to the collection. */ public boolean add(Object object) { if (object == null) throw new NullPointerException("null arg! "); else throw new UnsupportedOperationException("Operation not supported !"); } /** * Spec page 62 The remove methods: clear, remove, removeAll, and retainAll. * o These methods may remove SBB entities from the child relation. The * input argument specifies which SBB entities will be removed from the * child relation or retained in the child relation by specifying the SBB * local object or collection of SBB local objects that represent the SBB * entities to be removed or retained. o Removing an SBB entity from a child * relation initiates a cascading removal of the SBB entity tree rooted by * the SBB entity, similar to invoking the remove method on an SBB local * object that represents the SBB entity. * */ public boolean remove(Object object) { sleeContainer.getTransactionManager().mandateTransaction(); if(logger.isDebugEnabled()) { logger.debug("removing sbb local object " + object); } if (object == null) throw new NullPointerException("Null arg for remove "); if (!(object instanceof SbbLocalObjectImpl)) return false; SbbLocalObjectImpl sbbLocalObjectImpl = (SbbLocalObjectImpl)object; if (sbbEntity.cacheData.childRelationHasSbbEntity(getChildRelationMethod, sbbLocalObjectImpl.getSbbEntityId())) { sbbLocalObjectImpl.remove(); return true; } else { return false; } } /** * This operation is not supported ( see page 62 ) of the spec. The add * methods add and addAll. Any attempts to add to the child relation using * these methods result in a java.lang. UnsupportedOperationException. For * example, the SLEE must throw the UnsupportedOperationException when these * methods are invoked with arguments that add to the collection. o An * invocation of an add method that has no effect on the collection, such as * invoking the addAll method with an empty collection may or may not throw * an UnsupportedOperationException . The create method of the ChildRelation * interface should be used to create a child SBB entity. This causes the * SLEE to automatically add an SBB local object that represents the newly * created SBB entity to the collection. */ public boolean addAll(Collection c) { if (c == null) throw new NullPointerException("Null arg!"); else throw new UnsupportedOperationException("Operation not supported !"); } /** * This method returns true if all SBB entities represented by the SBB local * objects in the collection specified by the input argument are members of * this child relation. If the collection contains an object that is not an * SBB local object, an SBB local object that is invalid, or an SBB local * object whose underlying SBB entity is not a member of this child * relation, then this method returns false. */ public boolean containsAll(Collection c) { if (c == null) throw new NullPointerException("null collection!"); for ( Iterator it = c.iterator(); it.hasNext(); ) { SbbLocalObjectConcrete sbbLocalInterface = ( SbbLocalObjectConcrete) it.next(); if (!sbbEntity.cacheData.childRelationHasSbbEntity(getChildRelationMethod, sbbLocalInterface.getSbbEntityId())) { if(logger.isDebugEnabled()) { logger.debug("containsAll : collection = " + c + " > "+sbbLocalInterface.getSbbEntityId()+" not in child relation"); } return false; } } if(logger.isDebugEnabled()) { logger.debug("containsAll : collection = " + c + " > all in child relation"); } return true; } /** * Removing an SBB entity from a child relation initiates a cascading * removal of the SBB entity tree rooted by the SBB entity, similar to * invoking the remove method on an SBB local object that represents the SBB * entity. * */ public boolean removeAll(Collection c) { boolean flag = true; if (c == null) throw new NullPointerException(" null collection ! "); for ( Iterator it = c.iterator(); it.hasNext(); ) { flag &= this.remove( it.next()); } return flag; } /* * (non-Javadoc) * * @see java.util.Collection#retainAll(java.util.Collection) */ public boolean retainAll(Collection c) { boolean flag = false; if (c == null) throw new NullPointerException(" null arg! "); for ( Iterator it = this.iterator(); it.hasNext();) { if ( ! c.contains(it.next())) { flag = true; it.remove(); } } return flag; } /* * (non-Javadoc) * * @see java.util.Collection#toArray(java.lang.Object[]) */ public Object[] toArray(Object[] a) { if (a == null) throw new NullPointerException("null arg!"); HashSet localObjects = this.getLocalObjects(); return localObjects.toArray(a); } public Set<String> getSbbEntitySet(){ return new HashSet<String>(sbbEntity.cacheData.getChildRelationSbbEntities(getChildRelationMethod)); } public void removeChild(String sbbEntityId) { sbbEntity.cacheData.removeChildRelationSbbEntity(getChildRelationMethod, sbbEntityId); } // --- ITERATOR /* * JAIN SLEE 1.0 Specification, Final Release Page 62 The iterator method * and the Iterator objects returned by this method. Chapter 6 The SBB * Abstract Class * * The SLEE must implement the methods of the Iterator objects returned by * the iterator method by following the contract defined by the * java.util.Iterator interface. o The next method of the Iterator object * returns an object that implements the SBB local interface of the child * SBB of the child relation. Java typecast can be used to narrow the * returned object reference to the SBB local interface of the child SBB. o * The remove method of the Iterator object removes the SBB entity that is * represented by the last SBB local object returned by the next method of * the Iterator object from the child relation. Removing an SBB entity from * a child relation by invoking this remove method initiates a cascading * removal of the SBB entity tree rooted by the SBB entity, similar to * invoking the remove method on an SBB local object that represents the SBB * entity. The behavior of the Iterator object is unspecified if the * underlying child relation is modified while the iteration is in progress * in any way other than by calling this remove method. */ class ChildRelationIterator implements Iterator { private Iterator<String> myIterator; private String nextEntity; private SbbLocalObject nextSbbLocalObject; public ChildRelationIterator() { this.myIterator = getSbbEntitySet().iterator(); } public void remove() { if (nextSbbLocalObject != null) { myIterator.remove(); nextSbbLocalObject.remove(); } else { throw new IllegalStateException(); } } public boolean hasNext() { return myIterator.hasNext(); } public Object next() { nextEntity = myIterator.next(); SbbEntity childSbbEntity = SbbEntityFactory.getSbbEntity(nextEntity); this.nextSbbLocalObject = childSbbEntity.createSbbLocalObject(); sbbEntity.addChildWithSbbObject(childSbbEntity); return nextSbbLocalObject; } } }