/* BeanContextSupport.java --
   Copyright (C) 2003, 2005, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.beans.beancontext;

import java.beans.Beans;
import java.beans.DesignMode;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.Visibility;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

/**
 * This is a helper class for implementing a bean context.  It is
 * intended to be used either by subclassing or by calling methods
 * of this implementation from another.
 *
 * @author Michael Koch
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @since 1.2
 */
public class BeanContextSupport extends BeanContextChildSupport
  implements BeanContext, Serializable, PropertyChangeListener,
  VetoableChangeListener
{
  private static final long serialVersionUID = -4879613978649577204L;

  /**
   * Deserializes a stored bean context.  Hook methods are provided to allow
   * subclasses to perform their own deserialization after the default
   * deserialization but prior to the deserialization of the children.  Note that
   * {@link #readChildren(ObjectInputStream)} is only called if there
   * is no distinct peer.  If there is, the peer is expected to call
   * the method instead.
   *
   * @param s the stream to deserialize.
   * @throws ClassNotFoundException if the class of an object being deserialized
   *                                could not be found.
   * @throws IOException if an I/O error occurs.
   */
  private void readObject (ObjectInputStream s)
    throws ClassNotFoundException, IOException
  {
    s.defaultReadObject();
    bcsPreDeserializationHook(s);
    BeanContext peer = getBeanContextPeer();
    if (peer == null || peer == this)
      readChildren(s);
  }

  /**
   * Serializes a bean context.  Hook methods are provided to allow
   * subclasses to perform their own serialization after the default
   * serialization but prior to serialization of the children.  Note that
   * {@link #writeChildren(ObjectOutputStream)} is only called if there
   * is no distinct peer.  If there is, the peer is expected to call
   * the method instead.
   *
   * @param s the stream to serialize.
   * @throws ClassNotFoundException if the class of an object being deserialized
   *                                could not be found.
   * @throws IOException if an I/O error occurs.
   */
  private void writeObject (ObjectOutputStream s)
    throws ClassNotFoundException, IOException
  {
    serializing = true;
    s.defaultWriteObject();
    bcsPreSerializationHook(s);
    BeanContext peer = getBeanContextPeer();
    if (peer == null || peer == this)
      writeChildren(s);
    serializing = false;
  }

  protected class BCSChild implements Serializable
  {
    private static final long serialVersionUID = -5815286101609939109L;

    private Object targetChild;
    private Object peer;

    BCSChild(Object targetChild, Object peer)
    {
      this.targetChild = targetChild;
      this.peer = peer;
    }

    private Object getTargetChild()
    {
      return targetChild;
    }

  }

  protected static final class BCSIterator implements Iterator
  {
    private Iterator child;

    BCSIterator(Iterator child)
    {
      this.child = child;
    }

    public boolean hasNext ()
    {
      return child.hasNext();
    }

    public Object next ()
    {
      return child.next();
    }

    public void remove ()
    {
      // This must be a noop remove operation.
    }
  }

  protected transient ArrayList bcmListeners;

  protected transient HashMap children;

  protected transient boolean designTime;

  protected transient Locale locale;

  protected transient boolean okToUseGui;

  private transient boolean serializing;

  /**
   * Construct a BeanContextSupport instance.
   */
  public BeanContextSupport ()
  {
    this (null, null, false, true);
  }

  /**
   * Construct a BeanContextSupport instance.
   *
   * @param peer  the bean context peer (<code>null</code> permitted).
   */
  public BeanContextSupport(BeanContext peer)
  {
    this (peer, null, false, true);
  }

  /**
   * Construct a BeanContextSupport instance.
   *
   * @param peer  the bean context peer (<code>null</code> permitted).
   * @param locale  the locale (<code>null</code> permitted, equivalent to
   *     the default locale).
   */
  public BeanContextSupport (BeanContext peer, Locale locale)
  {
    this (peer, locale, false, true);
  }

  /**
   * Construct a BeanContextSupport instance.
   *
   * @param peer  the bean context peer (<code>null</code> permitted).
   * @param locale  the locale (<code>null</code> permitted, equivalent to
   *     the default locale).
   * @param dtime  a flag indicating whether or not the bean context is in
   *     design time mode.
   */
  public BeanContextSupport (BeanContext peer, Locale locale, boolean dtime)
  {
    this (peer, locale, dtime, true);
  }

  /**
   * Construct a BeanContextSupport instance.
   *
   * @param peer  the bean context peer (<code>null</code> permitted).
   * @param locale  the locale (<code>null</code> permitted, equivalent to
   *     the default locale).
   * @param dtime  a flag indicating whether or not the bean context is in
   *     design time mode.
   * @param visible  initial value of the <code>okToUseGui</code> flag.
   */
  public BeanContextSupport (BeanContext peer, Locale locale, boolean dtime,
                             boolean visible)
  {
    super(peer);

    this.locale = locale == null ? Locale.getDefault() : locale;
    designTime = dtime;
    okToUseGui = visible;

    initialize ();
  }

  /**
   * <p>
   * Add a child to the bean context.  A child can be a simple
   * <code>Object</code>, a <code>BeanContextChild</code>
   * or another <code>BeanContext</code>.
   * </p>
   * <p>
   * The children of a <code>BeanContext</code> form a set.  As
   * a result, this method returns <code>false</code> if the given
   * object is already a child of this context.
   * </p>
   * <p>
   * If the child is a <code>BeanContextChild</code>, or a proxy
   * for such a child, the <code>setBeanContext()</code> method
   * is invoked on the child.  If this operation is vetoed by the
   * child, via throwing a <code>PropertyVetoException</code>,
   * then the current completion state of the <code>add()</code>
   * operation is rolled back and a <code>IllegalStateException</code>
   * is thrown.  If the <code>BeanContextChild</code> is successfully
   * added, then the context registers with its
   * <code>PropertyChangeListener</code> and
   * <code>VetoableChangeListener</code> for "beanContext" events.
   * </p>
   * <p>
   * If the child implements <code>java.beans.Visibility</code>,
   * then its ability to use a GUI is set based on that of
   * this context.
   * </p>
   * <p>
   * A <code>BeanContextMembershipEvent</code> is fired when the
   * child is successfully added to the bean context.
   * </p>
   * <p>
   * This method is synchronized over the global hierarchy lock.
   * </p>
   *
   * @param targetChild the child to add.
   * @return false if the child has already been added.
   * @throws IllegalArgumentException if the child is null.
   * @throws IllegalStateException if the child vetos the setting
   *                               of its context.
   */
  public boolean add(Object targetChild)
  {
    synchronized (globalHierarchyLock)
      {
        if (targetChild == null)
          throw new IllegalArgumentException();

        BCSChild child;
        synchronized (children)
          {
            if (children.containsKey(targetChild)
                || ! validatePendingAdd(targetChild))
              return false;
            child = createBCSChild(targetChild, beanContextChildPeer);
            children.put(targetChild, child);
          }
        synchronized (targetChild)
          {
            BeanContextChild bcChild = null;
            if (targetChild instanceof BeanContextChild)
              bcChild = (BeanContextChild) targetChild;
            if (targetChild instanceof BeanContextProxy)
              bcChild = ((BeanContextProxy) targetChild).getBeanContextProxy();
            if (bcChild != null)
              try
                {
                  bcChild.setBeanContext(this);
                  bcChild.addVetoableChangeListener("beanContext", this);
                  bcChild.addPropertyChangeListener("beanContext", this);
                }
              catch (PropertyVetoException e)
                {
                  synchronized (children)
                    {
                      children.remove(targetChild);
                    }
                  throw new IllegalStateException("The child refused to " +
                                                  "associate itself with " +
                                                  "this context.", e);
                }
            if (targetChild instanceof Visibility)
              {
                Visibility visibleChild = (Visibility) targetChild;
                if (okToUseGui)
                  visibleChild.okToUseGui();
                else
                  visibleChild.dontUseGui();
              }
            childJustAddedHook(targetChild, child);
          }
        fireChildrenAdded(new BeanContextMembershipEvent(this,
                                                         new Object[]{ targetChild }));
        return true;
      }
  }

  public boolean addAll (Collection c)
  {
    // Intentionally throws an exception.
    throw new UnsupportedOperationException();
  }

  public void addBeanContextMembershipListener
    (BeanContextMembershipListener listener)
  {
    synchronized (bcmListeners)
      {
        if (! bcmListeners.contains(listener))
          bcmListeners.add(listener);
      }
  }

  /**
   * Returns true if this bean needs a GUI
   * but is being prevented from using one.
   *
   * @return true if <code>needsGui()</code>
   *              is true but the bean has been
   *              told not to use it.
   */
  public boolean avoidingGui()
  {
    return needsGui() && (!okToUseGui);
  }

  protected Iterator bcsChildren ()
  {
    synchronized (children)
      {
        return new BCSIterator(children.values().iterator());
      }
  }

  /**
   * Subclasses may use this method to perform their own deserialization
   * after the default deserialization process has taken place, but
   * prior to the deserialization of the children.  It should not
   * be used to replace the implementation of <code>readObject</code>
   * in the subclass.
   *
   * @param ois the input stream.
   * @throws ClassNotFoundException if the class of an object being deserialized
   *                                could not be found.
   * @throws IOException if an I/O error occurs.
   */
  protected void bcsPreDeserializationHook (ObjectInputStream ois)
    throws ClassNotFoundException, IOException
  {
    /* Purposefully left empty */
  }

  /**
   * Subclasses may use this method to perform their own serialization
   * after the default serialization process has taken place, but
   * prior to the serialization of the children.  It should not
   * be used to replace the implementation of <code>writeObject</code>
   * in the subclass.
   *
   * @param oos the output stream.
   * @throws IOException if an I/O error occurs.
   */
  protected void bcsPreSerializationHook (ObjectOutputStream oos)
    throws IOException
  {
    /* Purposefully left empty */
  }

  /**
   * Called when a child is deserialized.
   *
   * @param child the deserialized child.
   * @param bcsc the deserialized context wrapper for the child.
   */
  protected void childDeserializedHook (Object child, BeanContextSupport.BCSChild bcsc)
  {
    // Do nothing in the base class.
  }

  protected void childJustAddedHook (Object child, BeanContextSupport.BCSChild bcsc)
  {
    // Do nothing in the base class.
  }

  protected void childJustRemovedHook (Object child, BeanContextSupport.BCSChild bcsc)
  {
    // Do nothing in the base class.
  }

  protected static final boolean classEquals (Class first, Class second)
  {
    // Lame function!
    return (first == second || first.getName().equals(second.getName()));
  }

  public void clear ()
  {
    // This is the right thing to do.
    // The JDK docs are really bad here.
    throw new UnsupportedOperationException();
  }

  public boolean contains (Object o)
  {
    synchronized (children)
      {
        return children.containsKey(o);
      }
  }

  public boolean containsAll (Collection c)
  {
    synchronized (children)
      {
        Iterator it = c.iterator();
        while (it.hasNext())
          if (! children.containsKey(it.next()))
            return false;
      }
    return true;
  }

  public boolean containsKey (Object o)
  {
    synchronized (children)
      {
        return children.containsKey(o);
      }
  }

  protected final Object[] copyChildren ()
  {
    synchronized (children)
      {
        return children.keySet().toArray();
      }
  }

  protected BeanContextSupport.BCSChild createBCSChild (Object targetChild, Object peer)
  {
    return new BCSChild(targetChild, peer);
  }

  /**
   * Deserializes objects (written by {@link #serialize(ObjectOutputStream,
   * Collection)}) and adds them to the specified collection.
   *
   * @param ois  the input stream (<code>null</code> not permitted).
   * @param coll  the collection to add the objects to (<code>null</code> not
   *     permitted).
   *
   * @throws ClassNotFoundException
   * @throws IOException
   *
   * @see #serialize(ObjectOutputStream, Collection)
   */
  protected final void deserialize (ObjectInputStream ois, Collection coll)
    throws ClassNotFoundException, IOException
  {
    int itemCount = ois.readInt();
    for (int i = 0; i < itemCount; i++)
      coll.add(ois.readObject());
  }

  /**
   * Informs this bean that is should not make
   * use of the GUI.
   */
  public void dontUseGui()
  {
    okToUseGui = false;
  }

  protected final void fireChildrenAdded (BeanContextMembershipEvent bcme)
  {
    synchronized (bcmListeners)
      {
        Iterator it = bcmListeners.iterator();
        while (it.hasNext())
          {
            BeanContextMembershipListener l
              = (BeanContextMembershipListener) it.next();
            l.childrenAdded(bcme);
          }
      }
  }

  protected final void fireChildrenRemoved (BeanContextMembershipEvent bcme)
  {
    synchronized (bcmListeners)
      {
        Iterator it = bcmListeners.iterator();
        while (it.hasNext())
          {
            BeanContextMembershipListener l
            = (BeanContextMembershipListener) it.next();
            l.childrenRemoved(bcme);
          }
      }
  }

  /**
   * Returns the bean context peer.
   *
   * @return The bean context peer.
   *
   * @see BeanContextChildSupport#beanContextChildPeer
   */
  public BeanContext getBeanContextPeer()
  {
    return (BeanContext) beanContextChildPeer;
  }

  /**
   * Returns the {@link BeanContextChild} implementation for the given child.
   *
   * @param child  the child (<code>null</code> permitted).
   *
   * @return The bean context child.
   *
   * @throws IllegalArgumentException if <code>child</code> implements both
   *     the {@link BeanContextChild} and {@link BeanContextProxy} interfaces.
   */
  protected static final BeanContextChild getChildBeanContextChild(Object child)
  {
    if (child == null)
      return null;
    if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
      throw new IllegalArgumentException("Child cannot implement "
          + "BeanContextChild and BeanContextProxy simultaneously.");
    if (child instanceof BeanContextChild)
      return (BeanContextChild) child;
    if (child instanceof BeanContextProxy)
      return ((BeanContextProxy) child).getBeanContextProxy();
    return null;
  }

  /**
   * Returns <code>child</code> as an instance of
   * {@link BeanContextMembershipListener}, or <code>null</code> if
   * <code>child</code> does not implement that interface.
   *
   * @param child  the child (<code>null</code> permitted).
   *
   * @return The child cast to {@link BeanContextMembershipListener}.
   */
  protected static final BeanContextMembershipListener
      getChildBeanContextMembershipListener(Object child)
  {
    if (child instanceof BeanContextMembershipListener)
      return (BeanContextMembershipListener) child;
    else
      return null;
  }

  /**
   * Returns <code>child</code> as an instance of
   * {@link PropertyChangeListener}, or <code>null</code> if <code>child</code>
   * does not implement that interface.
   *
   * @param child  the child (<code>null</code> permitted).
   *
   * @return The child cast to {@link PropertyChangeListener}.
   */
  protected static final PropertyChangeListener getChildPropertyChangeListener(
      Object child)
  {
    if (child instanceof PropertyChangeListener)
      return (PropertyChangeListener) child;
    else
      return null;
  }

  /**
   * Returns <code>child</code> as an instance of {@link Serializable}, or
   * <code>null</code> if <code>child</code> does not implement that
   * interface.
   *
   * @param child  the child (<code>null</code> permitted).
   *
   * @return The child cast to {@link Serializable}.
   */
  protected static final Serializable getChildSerializable(Object child)
  {
    if (child instanceof Serializable)
      return (Serializable) child;
    else
      return null;
  }

  /**
   * Returns <code>child</code> as an instance of
   * {@link VetoableChangeListener}, or <code>null</code> if <code>child</code>
   * does not implement that interface.
   *
   * @param child  the child (<code>null</code> permitted).
   *
   * @return The child cast to {@link VetoableChangeListener}.
   */
  protected static final VetoableChangeListener getChildVetoableChangeListener(
      Object child)
  {
    if (child instanceof VetoableChangeListener)
      return (VetoableChangeListener) child;
    else
      return null;
  }

  /**
   * Returns <code>child</code> as an instance of {@link Visibility}, or
   * <code>null</code> if <code>child</code> does not implement that interface.
   *
   * @param child  the child (<code>null</code> permitted).
   *
   * @return The child cast to {@link Visibility}.
   */
  protected static final Visibility getChildVisibility(Object child)
  {
    if (child instanceof Visibility)
      return (Visibility) child;
    else
      return null;
  }

  public Locale getLocale ()
  {
    return locale;
  }

  public URL getResource (String name, BeanContextChild bcc)
  {
    if (! contains(bcc))
      throw new IllegalArgumentException("argument not a child");
    ClassLoader loader = bcc.getClass().getClassLoader();
    return (loader == null ? ClassLoader.getSystemResource(name)
            : loader.getResource(name));
  }

  public InputStream getResourceAsStream (String name, BeanContextChild bcc)
  {
    if (! contains(bcc))
      throw new IllegalArgumentException("argument not a child");
    ClassLoader loader = bcc.getClass().getClassLoader();
    return (loader == null ? ClassLoader.getSystemResourceAsStream(name)
            : loader.getResourceAsStream(name));
  }

  protected void initialize ()
  {
    bcmListeners = new ArrayList();
    children = new HashMap();
  }

  /**
   * This is a convenience method for instantiating a bean inside this
   * context.  It delegates to the appropriate method in
   * <code>java.beans.Beans</code> using the context's classloader.
   *
   * @param beanName the name of the class of bean to instantiate.
   * @throws IOException if an I/O error occurs in loading the class.
   * @throws ClassNotFoundException if the class, <code>beanName</code>,
   *                                can not be found.
   */
  public Object instantiateChild (String beanName)
    throws IOException, ClassNotFoundException
  {
    return Beans.instantiate(getClass().getClassLoader(), beanName, this);
  }

  /**
   * Returns <code>true</code> if the <code>BeanContext</code> is in
   * design time mode, and <code>false</code> if it is in runtime mode.
   *
   * @return A boolean.
   *
   * @see #setDesignTime(boolean)
   */
  public boolean isDesignTime()
  {
    return designTime;
  }

  /**
   * Returns true if this bean context has no children.
   *
   * @return true if there are no children.
   */
  public boolean isEmpty ()
  {
    synchronized (children)
      {
        return children.isEmpty();
      }
  }

  /**
   * Returns true if the bean context is in the process
   * of being serialized.
   *
   * @return true if the context is being serialized.
   */
  public boolean isSerializing()
  {
    return serializing;
  }

  public Iterator iterator ()
  {
    synchronized (children)
      {
        return children.keySet().iterator();
      }
  }

  /**
   * Returns false as this bean does not a
   * GUI for its operation.
   *
   * @return false
   */
  public boolean needsGui()
  {
    return false;
  }

  /**
   * Informs this bean that it is okay to make use of
   * the GUI.
   */
  public void okToUseGui ()
  {
    okToUseGui = true;
  }

  /**
   * Subclasses may use this method to catch property changes
   * arising from the children of this context.  At present,
   * we just listen for the beans being assigned to a different
   * context and remove them from here if such an event occurs.
   *
   * @param pce the property change event.
   */
  public void propertyChange (PropertyChangeEvent pce)
  {
    if (pce.getNewValue() != this)
      remove(pce.getSource(), false);
  }

  /**
   * Deserializes the children using the
   * {@link #deserialize(ObjectInputStream, Collection} method
   * and then calls {@link childDeserializedHook(Object, BCSChild)}
   * for each child deserialized.
   *
   * @param ois the input stream.
   * @throws IOException if an I/O error occurs.
   */
  public final void readChildren (ObjectInputStream ois)
    throws IOException, ClassNotFoundException
  {
    List temp = new ArrayList();
    deserialize(ois, temp);
    Iterator i = temp.iterator();
    synchronized (globalHierarchyLock)
      {
        synchronized (children)
          {
            while (i.hasNext())
              {
                BCSChild bcs = (BCSChild) i.next();
                childDeserializedHook(bcs.getTargetChild(), bcs);
                children.put(bcs.getTargetChild(), bcs);
              }
          }
      }
  }

  /**
   * Remove the specified child from the context.  This is
   * the same as calling <code>remove(Object,boolean)</code>
   * with a request for the <code>setBeanContext()</code> method
   * of the child to be called (i.e. the second argument is true).
   *
   * @param targetChild the child to remove.
   */
  public boolean remove (Object targetChild)
  {
    return remove(targetChild, true);
  }

  /**
   * <p>
   * Removes a child from the bean context.  A child can be a simple
   * <code>Object</code>, a <code>BeanContextChild</code>
   * or another <code>BeanContext</code>.  If the given child is not
   * a child of this context, this method returns <code>false</code>.
   * </p>
   * <p>
   * If the child is a <code>BeanContextChild</code>, or a proxy
   * for such a child, the <code>setBeanContext()</code> method
   * is invoked on the child (if specified).  If this operation is vetoed
   * by the child, via throwing a <code>PropertyVetoException</code>,
   * then the current completion state of the <code>remove()</code>
   * operation is rolled back and a <code>IllegalStateException</code>
   * is thrown.  If the <code>BeanContextChild</code> is successfully
   * removed, then the context deregisters with its
   * <code>PropertyChangeListener</code> and
   * <code>VetoableChangeListener</code> for "beanContext" events.
   * </p>
   * <p>
   * A <code>BeanContextMembershipEvent</code> is fired when the
   * child is successfully removed from the bean context.
   * </p>
   * <p>
   * This method is synchronized over the global hierarchy lock.
   * </p>
   *
   * @param targetChild the child to remove.
   * @param callChildSetBC true if the <code>setBeanContext()</code>
   *                       method of the child should be called.
   * @return false if the child doesn't exist.
   * @throws IllegalArgumentException if the child is null.
   * @throws IllegalStateException if the child vetos the setting
   *                               of its context.
   */
  protected boolean remove (Object targetChild, boolean callChildSetBC)
  {
    synchronized (globalHierarchyLock)
      {
        if (targetChild == null)
          throw new IllegalArgumentException();

        BCSChild child;
        synchronized (children)
          {
            if (!children.containsKey(targetChild)
                || !validatePendingRemove(targetChild))
              return false;
            child = (BCSChild) children.remove(targetChild);
          }
        synchronized (targetChild)
          {
            BeanContextChild bcChild = null;
            if (targetChild instanceof BeanContextChild)
              bcChild = (BeanContextChild) targetChild;
            if (targetChild instanceof BeanContextProxy)
              bcChild = ((BeanContextProxy) targetChild).getBeanContextProxy();
            if (bcChild != null)
              try
                {
                  if (callChildSetBC)
                    bcChild.setBeanContext(null);
                  bcChild.removeVetoableChangeListener("beanContext", this);
                  bcChild.removePropertyChangeListener("beanContext", this);
                }
              catch (PropertyVetoException e)
                {
                  synchronized (children)
                    {
                      children.put(targetChild, child);
                    }
                  throw new IllegalStateException("The child refused to " +
                                                  "disassociate itself with " +
                                                  "this context.", e);
                }
            childJustRemovedHook(targetChild, child);
          }
        fireChildrenRemoved(new BeanContextMembershipEvent(this,
                                                         new Object[]{ targetChild }));
        return true;
      }
  }

  public boolean removeAll (Collection c)
  {
    // Intentionally throws an exception.
    throw new UnsupportedOperationException();
  }

  public void removeBeanContextMembershipListener (BeanContextMembershipListener bcml)
  {
    synchronized (bcmListeners)
      {
        bcmListeners.remove(bcml);
      }
  }

  public boolean retainAll (Collection c)
  {
    // Intentionally throws an exception.
    throw new UnsupportedOperationException();
  }

  /**
   * Writes the items in the collection to the specified output stream.  Items
   * in the collection that are not instances of {@link Serializable}
   * (this includes <code>null</code>) are simply ignored.
   *
   * @param oos  the output stream (<code>null</code> not permitted).
   * @param coll  the collection (<code>null</code> not permitted).
   *
   * @throws IOException
   *
   * @see #deserialize(ObjectInputStream, Collection)
   */
  protected final void serialize(ObjectOutputStream oos, Collection coll)
    throws IOException
  {
    Object[] items = coll.toArray();
    int itemCount = 0;
    for (int i = 0; i < items.length; i++)
      {
        if (items[i] instanceof Serializable)
          itemCount++;
      }
    oos.writeInt(itemCount);
    for (int i = 0; i < items.length; i++)
      {
        if (items[i] instanceof Serializable)
          oos.writeObject(items[i]);
      }
  }

  /**
   * Sets the flag that indicates whether or not the
   * <code>BeanContext</code> is in design mode.  If the flag changes
   * value, a {@link PropertyChangeEvent} (with the property name 'designMode')
   * is sent to registered listeners.  Note that the property name used here
   * does NOT match the specification in the {@link DesignMode} interface, we
   * match the reference implementation instead - see bug parade entry 4295174.
   *
   * @param dtime  the new value for the flag.
   *
   * @see #isDesignTime()
   */
  public void setDesignTime(boolean dtime)
  {
    boolean save = designTime;
    designTime = dtime;
    // note that we use the same property name as Sun's implementation,
    // even though this is a known bug: see bug parade entry 4295174
    firePropertyChange("designMode", Boolean.valueOf(save),
                       Boolean.valueOf(dtime));
  }

  public void setLocale (Locale newLocale)
    throws PropertyVetoException
  {
    if (newLocale == null || locale == newLocale)
      return;
    fireVetoableChange("locale", locale, newLocale);
    Locale oldLocale = locale;
    locale = newLocale;
    firePropertyChange("locale", oldLocale, newLocale);
  }

  public int size ()
  {
    synchronized (children)
      {
        return children.size();
      }
  }

  /**
   * Returns an array containing the children of this <code>BeanContext</code>.
   *
   * @return An array containing the children.
   */
  public Object[] toArray()
  {
    synchronized (children)
      {
        return children.keySet().toArray();
      }
  }

  /**
   * Populates, then returns, the supplied array with the children of this
   * <code>BeanContext</code>.  If the array is too short to hold the
   * children, a new array is allocated and returned.  If the array is too
   * long, it is padded with <code>null</code> items at the end.
   *
   * @param array  an array to populate (<code>null</code> not permitted).
   */
  public Object[] toArray(Object[] array)
  {
    synchronized (children)
      {
        return children.keySet().toArray(array);
      }
  }

  protected boolean validatePendingAdd (Object targetChild)
  {
    return true;
  }

  protected boolean validatePendingRemove (Object targetChild)
  {
    return true;
  }

  /**
   * Subclasses may use this method to veto changes arising
   * from the children of this context.
   *
   * @param pce the vetoable property change event fired.
   */
  public void vetoableChange (PropertyChangeEvent pce)
    throws PropertyVetoException
  {
    /* Purposefully left empty */
  }

  /**
   * Serializes the children using the
   * {@link #serialize(ObjectOutputStream, Collection} method.
   *
   * @param oos the output stream.
   * @throws IOException if an I/O error occurs.
   */
  public final void writeChildren (ObjectOutputStream oos)
    throws IOException
  {
    synchronized (children)
      {
        serialize(oos, children.values());
      }
  }

}
