SortedCollection.java

/**
* Copyright 2010,2021 Nikolas S Boyd.
Permission is granted to copy this work provided this copyright statement is retained in all copies.

*/
package Hoot.Collections;

import Hoot.Runtime.Functions.*;
import Hoot.Runtime.Faces.*;
import Hoot.Runtime.Values.*;
import Hoot.Runtime.Blocks.*;
import Smalltalk.Core.*;
import Smalltalk.Blocks.*;
import Smalltalk.Magnitudes.*;
import Hoot.Behaviors.*;
import Hoot.Behaviors.Nil;
import Hoot.Behaviors.Object;
import Hoot.Behaviors.True;
import Hoot.Behaviors.False;
import Hoot.Behaviors.Boolean;
import Hoot.Magnitudes.*;
import Hoot.Magnitudes.Integer;
import Hoot.Magnitudes.Character;
import Hoot.Magnitudes.Float;
import Hoot.Magnitudes.Double;
import java.util.ArrayList;
import java.util.Collections;
import Hoot.Magnitudes.Integer;
import Hoot.Streams.WriteStream;
import Smalltalk.Core.Subject;
import Smalltalk.Collections.*;
import Smalltalk.Magnitudes.Scalar;
import Smalltalk.Magnitudes.Ordinal;

public class SortedCollection<ElementType extends Object> extends SequencedCollection<ElementType> implements CollectedSortably<ElementType>
{

  public static Metaclass type() { return (Metaclass)Metaclass.$class; }
  @Override public Metaclass $class() { return (Metaclass)Metaclass.$class; }
  public static class Metaclass extends SequencedCollection.Metaclass implements CollectedSortably.Metatype
  {
    static final SortedCollection.Metaclass $class = new SortedCollection.Metaclass();
    public Metaclass() {
      this(SortedCollection.Metaclass.class);
    }

    public Metaclass(java.lang.Class aClass) {
      super(aClass);
    }

    @Override public java.lang.Class outerClass() { return SortedCollection.class; }


    /**
     * @return 
     */
    @Override public   SortedCollection $new()
    {
      java.lang.String exitID = "SortedCollectionMetatype>>$new";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SortedCollection)f0.exit(exitID, this.$new(SmallInteger.from(10)));
      });
    }

    /**
     * @return 
     */
    @Override public   SortedCollection $new(final Ordinal capacity)
    {
      java.lang.String exitID = "SortedCollectionMetatype>>$new";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SortedCollection)f0.exit(exitID, new SortedCollection(capacity));
      });
    }

    /**
     * @return 
     */
    public   SortedCollection from(final java.util.List primitiveList)
    {
      java.lang.String exitID = "SortedCollectionMetatype>>from";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SortedCollection)f0.exit(exitID, new SortedCollection(primitiveList));
      });
    }

    /**
     * @return 
     */
    public   SortedCollection synchronizedFrom(final java.util.List primitiveList)
    {
      java.lang.String exitID = "SortedCollectionMetatype>>synchronizedFrom";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SortedCollection)f0.exit(exitID, new SortedCollection(java.util.Collections.synchronizedList(primitiveList)));
      });
    }

    /**
     * @return 
     */
    public   DyadicPredicate sortBlock()
    {
      java.lang.String exitID = "SortedCollectionMetatype>>sortBlock";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return Closure.with(f3 -> {
        Ordered a = f3.getValue(0).value();
        Ordered b = f3.getValue(1).value();
        return (a.lessThan(b));
      }, "a", "b").toPredicate();
      });
    }
  }


  protected final java.util.List<ElementType> contents;
  protected Boolean needsSort = False.literal();
  protected DyadicPredicate sortBlock = SortedCollection.type().sortBlock();

  /**
   * 
   */
  protected    SortedCollection()
  {
    this(new java.util.ArrayList());
    java.lang.String exitID = "SortedCollection>>SortedCollection";
    Frame f0 = new Frame(exitID);
  }

  /**
   * 
   */
  protected    SortedCollection(final Ordinal capacity)
  {
    this(new java.util.ArrayList(capacity.intValue()));
    java.lang.String exitID = "SortedCollection>>SortedCollection";
    Frame f0 = new Frame(exitID);
  }

  /**
   * 
   */
  protected    SortedCollection(final java.util.List primitiveList)
  {
    java.lang.String exitID = "SortedCollection>>SortedCollection";
    Frame f0 = new Frame(exitID);
     contents = java.util.Collections.synchronizedList(primitiveList);
  }

  /**
   * @return 
   */
  @Override protected   ElementType get(final int index)
  {
    java.lang.String exitID = "SortedCollection>>get";
    Frame f0 = new Frame(exitID);
    return (ElementType)contents.get(index);
  }

  /**
   * @return 
   */
  public   java.util.List primitiveContents()
  {
    java.lang.String exitID = "SortedCollection>>primitiveContents";
    Frame f0 = new Frame(exitID);
    this.reSort();
    return (java.util.List)contents;
  }

  /**
   * @return 
   */
  @Override public   Integer size()
  {
    java.lang.String exitID = "SortedCollection>>size";
    Frame f0 = new Frame(exitID);
    return (Integer)SmallInteger.from(contents.size());
  }

  /**
   * @return 
   */
  public   DyadicPredicate sortBlock()
  {
    java.lang.String exitID = "SortedCollection>>sortBlock";
    Frame f0 = new Frame(exitID);
    return (DyadicPredicate)sortBlock;
  }

  /**
   * @return 
   */
  public   SortedCollection sortBlock(final DyadicPredicate aBlock)
  {
    java.lang.String exitID = "SortedCollection>>sortBlock";
    Frame f0 = new Frame(exitID);
     sortBlock = aBlock;

     needsSort = True.literal();
    return (SortedCollection)this;
  }

  /**
   * @return 
   */
  protected   SortedCollection reSort()
  {
    java.lang.String exitID = "SortedCollection>>reSort";
    Frame f0 = new Frame(exitID);
    if (needsSort.asPrimitive()) {
      synchronized (contents) {
        Collections.sort(contents);

         needsSort = False.literal();
      };
    };
    return (SortedCollection)this;
  }

  /**
   * @return 
   */
  public   ElementType add(final Object element)
  {
    java.lang.String exitID = "SortedCollection>>add";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Object.isNull(((Object)element)).ifTrue(Closure.with(f2 -> {
      return (ElementType)f0.exit(exitID, element);
    }, ""));
    this.registerType(((Object)element));
    contents.add(((ElementType)element));

     needsSort = True.literal();
    return (ElementType)f0.exit(exitID, ((ElementType)element));
    });
  }

  /**
   * @return 
   */
  public   ElementType add_at(final Object element, final int index)
  {
    java.lang.String exitID = "SortedCollection>>add_at";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.add(((ElementType)element));
  }

  /**
   * @return 
   */
  @Override public   ElementType add_afterIndex(final ElementType element, final Ordinal index)
  {
    java.lang.String exitID = "SortedCollection>>add_afterIndex";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.add(element);
  }

  /**
   * @return 
   */
  @Override public   ElementType add_beforeIndex(final ElementType element, final Ordinal index)
  {
    java.lang.String exitID = "SortedCollection>>add_beforeIndex";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.add(element);
  }

  /**
   * @return 
   */
  @Override public   int hashCode()
  {
    java.lang.String exitID = "SortedCollection>>hashCode";
    Frame f0 = new Frame(exitID);
    return (int)contents.hashCode();
  }

  /**
   * @return 
   */
  @Override public   Boolean equals(final Collected aCollection)
  {
    java.lang.String exitID = "SortedCollection>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.equals(aCollection.asSortedCollection()));
  }

  /**
   * @return 
   */
  public   Boolean equals(final SortedCollection aCollection)
  {
    java.lang.String exitID = "SortedCollection>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)Boolean.from(contents.equals(aCollection.primitiveContents()));
  }

  /**
   * @return 
   */
  @Override public   SortedCollection asSortedCollection()
  {
    java.lang.String exitID = "SortedCollection>>asSortedCollection";
    Frame f0 = new Frame(exitID);
    return (SortedCollection)this;
  }

  /**
   * @return 
   */
  public   SortedCollection removeAll()
  {
    java.lang.String exitID = "SortedCollection>>removeAll";
    Frame f0 = new Frame(exitID);
    contents.clear();
    return (SortedCollection)this;
  }

  /**
   * @return 
   */
  public   ElementType removeAtIndex_ifAbsent(final Ordinal index, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "SortedCollection>>removeAtIndex_ifAbsent";
    Frame f0 = new Frame(exitID);
    this.reSort();

    int i = this.checkIndex_ifAbsent(index, aBlock);
    return (ElementType)contents.remove(i);
  }

  /**
   * @return 
   */
  public   ElementType removeAtIndex(final Ordinal index)
  {
    java.lang.String exitID = "SortedCollection>>removeAtIndex";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.removeAtIndex_ifAbsent(index, Closure.with(f2 -> {
      return this.indexRangeError();
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   OrderedCollection<ElementType> removeAllSuchThat(final MonadicPredicate criteria)
  {
    java.lang.String exitID = "SortedCollection>>removeAllSuchThat";
    Frame f0 = new Frame(exitID);
    ArrayList results = new ArrayList(10);
    SmallInteger.from(1).to_do(this.size(), Closure.with(f2 -> {
      Ordinal index = f2.getValue(0).value();
      
    ElementType element = contents.get((index.intValue() - 1));
    if (criteria.value(element).primitiveBoolean()) {
      results.add(element);
      this.removeAtIndex(index);
    };
    }, "index"));
    return (OrderedCollection<ElementType>)OrderedCollection.type().from(results);
  }

  /**
   * @return 
   */
  public   ElementType removeFirst()
  {
    java.lang.String exitID = "SortedCollection>>removeFirst";
    Frame f0 = new Frame(exitID);
    this.emptyCheck();
    this.reSort();
    return (ElementType)contents.remove(0);
  }

  /**
   * @return 
   */
  public   ElementType removeLast()
  {
    java.lang.String exitID = "SortedCollection>>removeLast";
    Frame f0 = new Frame(exitID);
    this.emptyCheck();
    this.reSort();
    return (ElementType)contents.remove((contents.size() - 1));
  }

  /**
   * @return 
   */
  public   Collected<ElementType> removeFirst(final Ordinal count)
  {
    java.lang.String exitID = "SortedCollection>>removeFirst";
    Frame f0 = new Frame(exitID);
    ArrayList results = new ArrayList(count.intValue());
    ((Integer)count).timesRepeat(Closure.with(f2 -> {
      results.add(this.removeFirst());
    }, ""));
    return (Collected<ElementType>)OrderedCollection.type().from(results);
  }

  /**
   * @return 
   */
  public   Collected<ElementType> removeLast(final Ordinal count)
  {
    java.lang.String exitID = "SortedCollection>>removeLast";
    Frame f0 = new Frame(exitID);
    ArrayList results = new ArrayList(count.intValue());
    ((Integer)count).timesRepeat(Closure.with(f2 -> {
      results.add(this.removeLast());
    }, ""));
    return (Collected<ElementType>)OrderedCollection.type().from(results);
  }

  /**
   * @return 
   */
  public   WriteStream writeStream()
  {
    java.lang.String exitID = "SortedCollection>>writeStream";
    Frame f0 = new Frame(exitID);
    return (WriteStream)WriteStream.type().with(this);
  }
}