Dictionary.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 Hoot.Magnitudes.Integer;
import Hoot.Streams.WriteStream;
import Hoot.Runtime.Names.Primitive;
import Smalltalk.Core.Posit;
import Smalltalk.Core.Subject;
import Smalltalk.Collections.*;
import Smalltalk.Magnitudes.Ordinal;
import Smalltalk.Magnitudes.Scalar;
import Smalltalk.Magnitudes.Associated;

public class Dictionary<KeyType extends Object, ElementType extends Object> extends Collection<ElementType> implements CollectedDictionary<KeyType, ElementType>
{

  public static Metaclass type() { return (Metaclass)Metaclass.$class; }
  @Override public Metaclass $class() { return (Metaclass)Metaclass.$class; }
  public static class Metaclass extends Collection.Metaclass implements CollectedDictionary.Metatype
  {
    static final Dictionary.Metaclass $class = new Dictionary.Metaclass();
    public Metaclass() {
      this(Dictionary.Metaclass.class);
    }

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

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


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

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

    /**
     * @return 
     */
    public  <ElementType extends Subject, KeyType extends Scalar> Dictionary withAll(final CollectedDictionary<KeyType, ElementType> pairedElements)
    {
      java.lang.String exitID = "DictionaryMetatype>>withAll";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      Dictionary results = this.$new(pairedElements.size());
      pairedElements.keysAndValuesDo(Closure.with(f3 -> {
        KeyType key = f3.getValue(0).value();
        ElementType value = f3.getValue(1).value();
        results.at_put(((Object)key), ((Object)value));
      }, "key", "value"));
      return (Dictionary)f0.exit(exitID, results);
      });
    }

    /**
     * @return 
     */
    public   Dictionary from(final java.util.Map primitiveMap)
    {
      java.lang.String exitID = "DictionaryMetatype>>from";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Dictionary)f0.exit(exitID, new Dictionary(primitiveMap));
      });
    }

    /**
     * @return 
     */
    public   Dictionary synchronizedFrom(final java.util.Map primitiveMap)
    {
      java.lang.String exitID = "DictionaryMetatype>>synchronizedFrom";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Dictionary)f0.exit(exitID, this.from(primitiveMap));
      });
    }
  }


  protected java.util.Map<KeyType, ElementType> contents;

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

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

  /**
   * 
   */
  protected    Dictionary(final java.util.Map primitiveMap)
  {
    java.lang.String exitID = "Dictionary>>Dictionary";
    Frame f0 = new Frame(exitID);
     contents = java.util.Collections.synchronizedMap(primitiveMap);
  }

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

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

  /**
   * @return 
   */
  public   Set<KeyType> keys()
  {
    java.lang.String exitID = "Dictionary>>keys";
    Frame f0 = new Frame(exitID);
    return (Set<KeyType>)Set.from(contents.keySet());
  }

  /**
   * @return 
   */
  public   KeyType indexOf(final ElementType element)
  {
    java.lang.String exitID = "Dictionary>>indexOf";
    Frame f0 = new Frame(exitID);
    return (KeyType)this.indexOf_ifAbsent(element, Closure.with(f2 -> {
      this.elementNotFound();
    return Nil.literal();
    }, ""));
  }

  /**
   * @return 
   */
  public   KeyType indexOf_ifAbsent(final ElementType element, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>indexOf_ifAbsent";
    Frame f0 = new Frame(exitID);
    KeyType key = Primitive.findKey(element, contents);
    return (KeyType)(Boolean.primitiveValue((key == null)) ? aBlock.value() : key);
  }

  /**
   * @return 
   */
  public   KeyType keyAtValue(final ElementType element)
  {
    java.lang.String exitID = "Dictionary>>keyAtValue";
    Frame f0 = new Frame(exitID);
    return (KeyType)this.indexOf(element);
  }

  /**
   * @return 
   */
  public   KeyType keyAtValue_ifAbsent(final ElementType element, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>keyAtValue_ifAbsent";
    Frame f0 = new Frame(exitID);
    return (KeyType)this.indexOf_ifAbsent(element, aBlock);
  }

  /**
   * @return 
   */
  public   ElementType at(final KeyType index)
  {
    java.lang.String exitID = "Dictionary>>at";
    Frame f0 = new Frame(exitID);
    if (contents.containsKey(index)) {
      return contents.get(index);
    };
    this.elementNotFound();
    return (ElementType)null;
  }

  /**
   * @return 
   */
  public   ElementType at_ifAbsent(final KeyType index, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>at_ifAbsent";
    Frame f0 = new Frame(exitID);
    if (contents.containsKey(index)) {
      return contents.get(index);
    };
    return (ElementType)aBlock.value();
  }

  /**
   * @return 
   */
  public   ElementType at_ifAbsentPut(final KeyType index, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>at_ifAbsentPut";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.at_ifAbsent(index, Closure.with(f2 -> {
      return this.at_put(index, aBlock.value());
    }, ""));
  }

  /**
   * @return 
   */
  public   ElementType at_put(final KeyType index, final ElementType element)
  {
    java.lang.String exitID = "Dictionary>>at_put";
    Frame f0 = new Frame(exitID);
    contents.put(index, element);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   ElementType atAll_put(final CollectedDistinctly<KeyType> indices, final ElementType element)
  {
    java.lang.String exitID = "Dictionary>>atAll_put";
    Frame f0 = new Frame(exitID);
    indices.$do(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      return this.at_put(key, element);
    }, "key"));
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   ElementType atAllPut(final ElementType element)
  {
    java.lang.String exitID = "Dictionary>>atAllPut";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.atAll_put(this.keys(), element);
  }

  /**
   * @return 
   */
  public   OrderedCollection<ElementType> values()
  {
    java.lang.String exitID = "Dictionary>>values";
    Frame f0 = new Frame(exitID);
    OrderedCollection<ElementType> results = OrderedCollection.type().$new(this.size());
    this.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return results.add(element);
    }, "key", "element"));
    return (OrderedCollection<ElementType>)results;
  }

  /**
   * @return 
   */
  public   ElementType add(final ElementType element)
  {
    java.lang.String exitID = "Dictionary>>add";
    Frame f0 = new Frame(exitID);
    return (ElementType)element;
  }

  /**
   * @return 
   */
  public   Collected<ElementType> addAll(final Collected<ElementType> elements)
  {
    java.lang.String exitID = "Dictionary>>addAll";
    Frame f0 = new Frame(exitID);
    return (Collected<ElementType>)elements;
  }

  /**
   * @return 
   */
  public   Association add(final Associated pairedElement)
  {
    java.lang.String exitID = "Dictionary>>add";
    Frame f0 = new Frame(exitID);
    this.at_put(pairedElement.key(), ((ElementType)pairedElement.value()));
    return (Association)((Association)pairedElement);
  }

  /**
   * @return 
   */
  public   CollectedDictionary addAll(final CollectedDictionary<KeyType, ElementType> pairedElements)
  {
    java.lang.String exitID = "Dictionary>>addAll";
    Frame f0 = new Frame(exitID);
    pairedElements.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return this.at_put(key, element);
    }, "key", "element"));
    return (CollectedDictionary)pairedElements;
  }

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

  /**
   * @return 
   */
  @Override public   Boolean equals(final Collected aCollection)
  {
    java.lang.String exitID = "Dictionary>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)Dictionary.type().accepts(aCollection).and(Predicate.with(f2 -> {
      return (this.equals(((Dictionary)aCollection)));
    }, ""));
  }

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

  /**
   * @return 
   */
  public   Dictionary associationsDo(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>associationsDo";
    Frame f0 = new Frame(exitID);
    this.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return aBlock.value(Association.withKey_withValue(key, element));
    }, "key", "element"));
    return (Dictionary)this;
  }

  /**
   * @return 
   */
  @Override public   Dictionary collect(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>collect";
    Frame f0 = new Frame(exitID);
    Dictionary results = Dictionary.type().$new(this.size());
    this.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return results.at_put(key, aBlock.value(element));
    }, "key", "element"));
    return (Dictionary)results;
  }

  /**
   * @return 
   */
  @Override public   Dictionary $do(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>$do";
    Frame f0 = new Frame(exitID);
    this.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return aBlock.value(element);
    }, "key", "element"));
    return (Dictionary)this;
  }

  /**
   * @return 
   */
  public   Dictionary keysAndValuesDo(final DyadicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>keysAndValuesDo";
    Frame f0 = new Frame(exitID);
    this.keys().$do(Closure.with(f2 -> {
      Scalar key = f2.getValue(0).value();
      return aBlock.value_value(key, contents.get(key));
    }, "key"));
    return (Dictionary)this;
  }

  /**
   * @return 
   */
  public   Dictionary sortedKeysAndValuesDo(final DyadicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>sortedKeysAndValuesDo";
    Frame f0 = new Frame(exitID);
    this.keys().sorted().$do(Closure.with(f2 -> {
      Scalar key = f2.getValue(0).value();
      return aBlock.value_value(key, contents.get(key));
    }, "key"));
    return (Dictionary)this;
  }

  /**
   * @return 
   */
  public   Dictionary keysDo(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>keysDo";
    Frame f0 = new Frame(exitID);
    this.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return aBlock.value(key);
    }, "key", "element"));
    return (Dictionary)this;
  }

  /**
   * @return 
   */
  public   Dictionary valuesDo(final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>valuesDo";
    Frame f0 = new Frame(exitID);
    this.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return aBlock.value(element);
    }, "key", "element"));
    return (Dictionary)this;
  }

  /**
   * @return 
   */
  @Override public   Dictionary reject(final MonadicPredicate aBlock)
  {
    java.lang.String exitID = "Dictionary>>reject";
    Frame f0 = new Frame(exitID);
    Dictionary results = Dictionary.type().$new(this.size());
    this.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return aBlock.value(element).ifFalse(Closure.with(f3 -> {
      return results.at_put(key, element);
    }, ""));
    }, "key", "element"));
    return (Dictionary)results;
  }

  /**
   * @return 
   */
  @Override public   Dictionary select(final MonadicPredicate aBlock)
  {
    java.lang.String exitID = "Dictionary>>select";
    Frame f0 = new Frame(exitID);
    Dictionary results = Dictionary.type().$new(this.size());
    this.keysAndValuesDo(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      ElementType element = f2.getValue(1).value();
      return aBlock.value(element).ifTrue(Closure.with(f3 -> {
      return results.at_put(key, element);
    }, ""));
    }, "key", "element"));
    return (Dictionary)results;
  }

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

  /**
   * @return 
   */
  public   ElementType removeKey(final KeyType key)
  {
    java.lang.String exitID = "Dictionary>>removeKey";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.removeKey_ifAbsent(key, Closure.with(f2 -> {
      this.elementNotFound();
    return Nil.literal();
    }, ""));
  }

  /**
   * @return 
   */
  public   ElementType removeKey_ifAbsent(final KeyType key, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>removeKey_ifAbsent";
    Frame f0 = new Frame(exitID);
    ElementType result = this.at_ifAbsent(key, aBlock);
    contents.remove(key);
    return (ElementType)result;
  }

  /**
   * @return 
   */
  public   Dictionary removeAllKeys(final CollectedDistinctly<KeyType> keys)
  {
    java.lang.String exitID = "Dictionary>>removeAllKeys";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    this.removeAllKeys_ifAbsent(keys, Closure.with(f2 -> {
      this.elementNotFound();
    return (Dictionary)f0.exit(exitID, Nil.literal().asPrimitive());
    }, ""));
    return (Dictionary)this;
    });
  }

  /**
   * @return 
   */
  public   Dictionary removeAllKeys_ifAbsent(final CollectedDistinctly<KeyType> keys, final MonadicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>removeAllKeys_ifAbsent";
    Frame f0 = new Frame(exitID);
    Dictionary results = Dictionary.type().$new(this.size());
    keys.$do(Closure.with(f2 -> {
      KeyType key = f2.getValue(0).value();
      results.at_put(key, this.removeKey_ifAbsent(key, Closure.with(f3 -> {
      return aBlock.value(key);
    }, "")));
    }, "key"));
    return (Dictionary)results;
  }

  /**
   * @return 
   */
  public   ElementType remove(final ElementType element)
  {
    java.lang.String exitID = "Dictionary>>remove";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.remove_ifAbsent(element, Closure.with(f2 -> {
      this.elementNotFound();
    return Nil.literal();
    }, ""));
  }

  /**
   * @return 
   */
  public   ElementType remove_ifAbsent(final ElementType element, final NiladicValuable aBlock)
  {
    java.lang.String exitID = "Dictionary>>remove_ifAbsent";
    Frame f0 = new Frame(exitID);
    return (ElementType)this.removeKey(this.keyAtValue_ifAbsent(element, aBlock));
  }

  /**
   * @return 
   */
  public   Collected<ElementType> removeAll(final Collected<ElementType> elements)
  {
    java.lang.String exitID = "Dictionary>>removeAll";
    Frame f0 = new Frame(exitID);
    elements.$do(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      
    KeyType key = this.keyAtValue(element);
    return key.notNil().ifTrue(Closure.with(f3 -> {
      return this.removeKey(key);
    }, ""));
    }, "element"));
    return (Collected<ElementType>)elements;
  }

  /**
   * @return 
   */
  public   OrderedCollection<ElementType> removeAllSuchThat(final MonadicPredicate criteria)
  {
    java.lang.String exitID = "Dictionary>>removeAllSuchThat";
    Frame f0 = new Frame(exitID);
    OrderedCollection<ElementType> results = OrderedCollection.type().$new();
    this.valuesDo(Closure.with(f2 -> {
      ElementType element = f2.getValue(0).value();
      return criteria.value(element).ifTrue(Closure.with(f3 -> {
      results.add(element);
    this.removeKey(this.keyAtValue(element));
    }, ""));
    }, "element"));
    return (OrderedCollection<ElementType>)results;
  }

  /**
   * @return 
   */
  @Override public   Boolean includes(final Subject element)
  {
    java.lang.String exitID = "Dictionary>>includes";
    Frame f0 = new Frame(exitID);
    return (Boolean)Boolean.from(contents.containsValue(((ElementType)element)));
  }

  /**
   * @return 
   */
  public   Boolean includesIndex(final KeyType index)
  {
    java.lang.String exitID = "Dictionary>>includesIndex";
    Frame f0 = new Frame(exitID);
    return (Boolean)Boolean.from(contents.containsKey(index));
  }

  /**
   * @return 
   */
  public   Posit includesKey(final KeyType key)
  {
    java.lang.String exitID = "Dictionary>>includesKey";
    Frame f0 = new Frame(exitID);
    return (Posit)this.includesIndex(key);
  }
}