Package nexj.core.runtime

Source Code of nexj.core.runtime.InstanceAssociationCollection$AccessorIterator

package nexj.core.runtime;

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;

import nexj.core.meta.Primitive;
import nexj.core.meta.TypeMismatchException;
import nexj.core.scripting.Function;
import nexj.core.scripting.Machine;
import nexj.core.scripting.Pair;
import nexj.core.scripting.ScriptingException;
import nexj.core.scripting.Symbol;
import nexj.core.util.Ditto;

/**
* Collection rolling up nested collections from associations.
*/
public class InstanceAssociationCollection extends AbstractCollection implements Cloneable, Ditto, Function
{
   // attributes

   /**
    * The property name.
    */
   protected String m_sName;

   // associations

   /**
    * The wrapped collection.
    */
   protected Collection m_col;

   // constructors

   /**
    * Constructs the accessor collection.
    * @param col The wrapped collection.
    * @param sName The property name.
    */
   public InstanceAssociationCollection(Collection col, String sName)
   {
      assert col != null;
      assert sName != null;

      m_col = col;
      m_sName = sName;
   }

   // operations

   /**
    * @see java.util.AbstractCollection#iterator()
    */
   public Iterator iterator()
   {
      return new AccessorIterator(m_col.iterator());
   }

   /**
    * @see java.util.AbstractCollection#size()
    */
   public int size()
   {
      if (m_col instanceof InstanceAssociationCollection)
      {
         int nCount = 0;

         for (Iterator itr = m_col.iterator(); itr.hasNext(); itr.next())
         {
            ++nCount;
         }

         return nCount;
      }

      return m_col.size();
   }

   /**
    * @see java.util.AbstractCollection#isEmpty()
    */
   public boolean isEmpty()
   {
      if (m_col instanceof InstanceAssociationCollection)
      {
         return !m_col.iterator().hasNext();
      }

      return m_col.isEmpty();
   }

   /**
    * @see nexj.core.scripting.Function#invoke(int, nexj.core.scripting.Machine)
    */
   public boolean invoke(int nArgCount, Machine machine)
   {
      if (nArgCount == 1)
      {
         Object arg = machine.getArg(0, nArgCount);

         if (!(arg instanceof Symbol))
         {
            throw new TypeMismatchException("#<association-collection>");
         }

         String sName = arg.toString();

         if (sName.length() != 0 && sName.charAt(0) == ':')
         {
            if (arg == Symbol._SIZE || arg == Symbol._COUNT)
            {
               machine.returnValue(Primitive.createInteger(size()), nArgCount);

               return false;
            }

            if (arg == Symbol._LIST)
            {
               machine.returnValue(list(), nArgCount);

               return false;
            }

            if (arg == Symbol._ITERATOR)
            {
               machine.returnValue(iterator(), nArgCount);

               return false;
            }
         }

         machine.returnValue(new InstanceAssociationCollection(this, arg.toString()), nArgCount);

         return false;
      }

      throw new ScriptingException(
         (nArgCount < 1) ? "err.scripting.maxArgCount" : "err.scripting.maxArgCount",
         new Object[]{"#<association-collection>", Primitive.createInteger(1),
         Primitive.createInteger(nArgCount)});
   }

   /**
    * @return The items in the collection as a linked list.
    */
   public Pair list()
   {
      Pair pair = null;

      for (Iterator itr = iterator(); itr.hasNext();)
      {
         pair = new Pair(itr.next(), pair);
      }

      return Pair.nreverse(pair);
   }

   /**
    * @see nexj.core.util.Ditto#ditto()
    */
   public Object ditto()
   {
      return new ArrayList(size());
   }

   /**
    * @see java.lang.Object#clone()
    */
   public Object clone()
   {
      try
      {
         return super.clone();
      }
      catch (CloneNotSupportedException e)
      {
         return null;
      }
   }

   // inner classes

   /**
    * Iterator wrapper implementing the property access logic.
    */
   protected class AccessorIterator implements Iterator
   {
      // associations

      /**
       * The next available object. Points to this if empty.
       */
      protected Object m_next;

      /**
       * The wrapped iterator.
       */
      protected Iterator m_itr;

      /**
       * Iterator for a possible inner collection.
       */
      protected Iterator m_innerItr;

      // constructors

      /**
       * Constructs the iterator.
       * @param itr The wrapped iterator.
       */
      protected AccessorIterator(Iterator itr)
      {
         m_next = this;
         m_itr = itr;
      }

      // operations

      /**
       * @return The next iterator value, or this if none.
       */
      protected Object findNext()
      {
         for (;;)
         {
            if (m_innerItr != null)
            {
               if (m_innerItr.hasNext())
               {
                  return m_innerItr.next();
               }

               m_innerItr = null;
            }

            if (m_itr.hasNext())
            {
               Object obj = m_itr.next();;

               if (obj == null)
               {
                  return null;
               }

               if (!(obj instanceof Instance))
               {
                  throw new TypeMismatchException("#<instance-collection select/1>");
               }

               Instance instance = (Instance)obj;

               Object value = instance.getValue(m_sName);

               if (instance.getMetaclass().getAttribute(m_sName).isCollection())
               {
                  if (value != null)
                  {
                     m_innerItr = ((Collection)value).iterator();
                  }

                  continue;
               }

               return value;
            }

            return this;
         }
      }

      /**
       * @see java.util.Iterator#hasNext()
       */
      public boolean hasNext()
      {
         if (m_next == this)
         {
            m_next = findNext();

            return m_next != this;
         }

         return true;
      }

      /**
       * @see java.util.Iterator#next()
       */
      public Object next()
      {
         Object obj = m_next;

         if (obj == this)
         {
            obj = findNext();

            if (obj == this)
            {
               throw new NoSuchElementException();
            }
         }

         m_next = this;

         return obj;
      }

      /**
       * @see java.util.Iterator#remove()
       */
      public void remove()
      {
         throw new UnsupportedOperationException();
      }
   }
}
TOP

Related Classes of nexj.core.runtime.InstanceAssociationCollection$AccessorIterator

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.