// $Id: Composer.java,v 1.5 1998/01/27 10:02:07 oliva Exp $

package BR.unicamp.Guarana;

import java.util.Enumeration;

/** Composers are MetaObjects that delegate operations to other
    MetaObjects.  The only difference between a MetaObject and a
    Composer is semantic: a Composer is expected to delegate operation
    handling to other MetaObjects, while non-Composers are expected to
    handle operations by themselves.  A Composer must implement at
    least one method that will return the set of MetaObjects it
    delegates to.
   
    @author Alexandre Oliva
    @version $Revision: 1.5 $  */
public abstract class Composer extends MetaObject {
  /** Provides the set of MetaObjects the Composer delegates to.  The
      Enumeration may contain non-MetaObject objects that mark up
      semantics of delegation.  Thus, concurrent MetaObjects may be
      preceded and followed by such objects; MetaObjects that are only
      invoked conditionally may be marked so, etc.  There are no
      predefined marks.

      Even if the Composer does not delegate to any MetaObject, it
      must return a non-null Enumeration.  The Enumeration must
      reflect the set of MetaObjects at the moment of the invocation
      of this method; if the set of MetaObjects changes thereafter,
      the Enumeration must NOT change accordingly.  It must iterate on
      a copy of the current set, or prevent any modification thereof.

      @return an unmodifiable set of MetaObjects the Composer
      delegates to as an Enumeration.  */
  public abstract Enumeration getMetaObjects();

  /** Provides an array of MetaObjects this Composer delegates to,
      that is ensured not to change.  It must be a copy of the current
      set of MetaObjects, or the array must be ensured not to change.

      The default behavior is to count the number of MetaObjects
      in the Enumeration returned by getMetaObjects(), then create an
      array that large, and copy references to the MetaObjects into
      that array.  Mark up non-MetaObjects are ignored.

      @return an unmodifiable array of MetaObjects.  */
  public synchronized MetaObject[] getMetaObjectsArray() {
    int count = 0;
    for(final Enumeration e = getMetaObjects();
	e.hasMoreElements();)
      if (e.nextElement() instanceof MetaObject)
	++count;
    MetaObject[] res = new MetaObject[count];
    int i = 0;
    for(final Enumeration e = getMetaObjects();
	e.hasMoreElements();) {
      Object o = e.nextElement();
      if (o instanceof MetaObject)
	res[i++] = (MetaObject)o;
    }
    return res;
  }
}
