Behavior.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.Behaviors;

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.Magnitudes.*;
import Hoot.Magnitudes.Integer;
import Hoot.Magnitudes.Character;
import Hoot.Magnitudes.Float;
import Hoot.Magnitudes.Double;
import Hoot.Collections.*;
import Hoot.Collections.String;
import java.util.*;
import Hoot.Runtime.Names.Primitive;
import Hoot.Runtime.Names.TypeName;
import Hoot.Runtime.Behaviors.Mirror;
import Hoot.Runtime.Behaviors.Typified;
import Hoot.Runtime.Behaviors.HootRegistry;
import Hoot.Collections.Set;
import Hoot.Magnitudes.Number;
import Hoot.Magnitudes.Integer;
import Smalltalk.Core.Subject;
import Smalltalk.Core.Classified;
import Smalltalk.Magnitudes.Scalar;
import Smalltalk.Magnitudes.Ordinal;
import Smalltalk.Collections.Collected;
import Smalltalk.Collections.CollectedDistinctly;

public abstract class Behavior extends Object implements Classified
{

  public static Metaclass type() { return (Metaclass)Metaclass.$class; }
  @Override public Metaclass $class() { return (Metaclass)Metaclass.$class; }
  public static class Metaclass extends Object.Metaclass implements Classified.Metatype
  {
    static final Behavior.Metaclass $class = new Behavior.Metaclass();
    public Metaclass() {
      this(Behavior.Metaclass.class);
    }

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

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

  }


  protected final HashSet<Behavior> subclasses = new HashSet();
  protected static final Object [] EmptyArray = {
  };

  /**
   * @return 
   */
  protected   Behavior addSubclass(final Behavior subClass)
  {
    java.lang.String exitID = "Behavior>>addSubclass";
    Frame f0 = new Frame(exitID);
    if (!((subClass == null))) {
      if ((subClass.superclass() == this)) {
        subclasses.add(subClass);
      };
    };
    return (Behavior)subClass;
  }

  /**
   * @return 
   */
  protected final   Behavior registerType()
  {
    java.lang.String exitID = "Behavior>>registerType";
    Frame f0 = new Frame(exitID);
    HootRegistry.registerType(this);
    this.registerSubclass();
    this.initialize();
    return (Behavior)this;
  }

  /**
   * @return 
   */
  protected   Behavior registerSubclass()
  {
    java.lang.String exitID = "Behavior>>registerSubclass";
    Frame f0 = new Frame(exitID);
    if (!(this.hasHeritage().asPrimitive())) {
      return this;
    };
    this.superior().addSubclass(this);
    return (Behavior)this;
  }

  /**
   * @return 
   */
  protected   void initialize()
  {
    java.lang.String exitID = "Behavior>>initialize";
    Frame f0 = new Frame(exitID);
  }

  /**
   * 
   */
  protected    Behavior()
  {
    super();
    java.lang.String exitID = "Behavior>>Behavior";
    Frame f0 = new Frame(exitID);
    this.registerType();
  }

  /**
   * 
   */
  protected    Behavior(final Typified aType)
  {
    this();
    java.lang.String exitID = "Behavior>>Behavior";
    Frame f0 = new Frame(exitID);
  }

  /**
   * 
   */
  protected    Behavior(final java.lang.Class aClass)
  {
    this();
    java.lang.String exitID = "Behavior>>Behavior";
    Frame f0 = new Frame(exitID);
  }

  /**
   * @return 
   */
  @Override public   Boolean equals(final Subject candidate)
  {
    java.lang.String exitID = "Behavior>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.equals(((Behavior)candidate)));
  }

  /**
   * @return 
   */
  @Override public   Boolean notMore(final Scalar upperBound)
  {
    java.lang.String exitID = "Behavior>>notMore";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.notMore(((Behavior)upperBound)));
  }

  /**
   * @return 
   */
  @Override public   Boolean lessThan(final Scalar upperBound)
  {
    java.lang.String exitID = "Behavior>>lessThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.lessThan(((Behavior)upperBound)));
  }

  /**
   * @return 
   */
  @Override public   Boolean moreThan(final Scalar lowerBound)
  {
    java.lang.String exitID = "Behavior>>moreThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.moreThan(((Behavior)lowerBound)));
  }

  /**
   * @return 
   */
  @Override public   Boolean notLess(final Scalar lowerBound)
  {
    java.lang.String exitID = "Behavior>>notLess";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.notLess(((Behavior)lowerBound)));
  }

  /**
   * @return 
   */
  public   Boolean equals(final Behavior candidate)
  {
    java.lang.String exitID = "Behavior>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.name().equals(candidate.name()));
  }

  /**
   * @return 
   */
  public   Boolean notMore(final Behavior upperBound)
  {
    java.lang.String exitID = "Behavior>>notMore";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.equals(upperBound)).or(Predicate.with(f2 -> {
      return (this.lessThan(upperBound));
    }, ""));
  }

  /**
   * @return 
   */
  public   Boolean notLess(final Behavior lowerBound)
  {
    java.lang.String exitID = "Behavior>>notLess";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.equals(lowerBound)).or(Predicate.with(f2 -> {
      return (this.moreThan(lowerBound));
    }, ""));
  }

  /**
   * @return 
   */
  public   Boolean moreThan(final Behavior lowerBound)
  {
    java.lang.String exitID = "Behavior>>moreThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)(lowerBound.lessThan(this));
  }

  /**
   * @return 
   */
  public   Boolean lessThan(final Behavior upperBound)
  {
    java.lang.String exitID = "Behavior>>lessThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)(this.nameSort().lessThan(upperBound.nameSort()));
  }

  /**
   * @return 
   */
  public   CollectedDistinctly<Classified> allSubclasses()
  {
    java.lang.String exitID = "Behavior>>allSubclasses";
    Frame f0 = new Frame(exitID);
    HashSet<Behavior> result = new HashSet();
    this.allSubclassesDo(Closure.with(f2 -> {
      Behavior each = f2.getValue(0).value();
      result.add(each);
    }, "each"));
    return (CollectedDistinctly<Classified>)((CollectedDistinctly)Set.from(result));
  }

  /**
   * @return 
   */
  public   CollectedDistinctly<Classified> allSuperclasses()
  {
    java.lang.String exitID = "Behavior>>allSuperclasses";
    Frame f0 = new Frame(exitID);
    HashSet<Behavior> result = new HashSet();
    this.allSuperclassesDo(Closure.with(f2 -> {
      Behavior each = f2.getValue(0).value();
      result.add(each);
    }, "each"));
    return (CollectedDistinctly<Classified>)((CollectedDistinctly)Set.from(result));
  }

  /**
   * @return 
   */
  public   CollectedDistinctly<Classified> subclasses()
  {
    java.lang.String exitID = "Behavior>>subclasses";
    Frame f0 = new Frame(exitID);
    HashSet<Behavior> result = new HashSet();
    synchronized (subclasses) {
      for (Behavior each : subclasses) {
        result.add(each);
      }
    };
    return (CollectedDistinctly<Classified>)((CollectedDistinctly)Set.from(result));
  }

  /**
   * @return 
   */
  public   CollectedDistinctly<Classified> withAllSubclasses()
  {
    java.lang.String exitID = "Behavior>>withAllSubclasses";
    Frame f0 = new Frame(exitID);
    Set<Behavior> results = ((Set)this.allSubclasses());
    results.add(this);
    return (CollectedDistinctly<Classified>)((CollectedDistinctly)results);
  }

  /**
   * @return 
   */
  public   CollectedDistinctly<Classified> withAllSuperclasses()
  {
    java.lang.String exitID = "Behavior>>withAllSuperclasses";
    Frame f0 = new Frame(exitID);
    Set<Behavior> results = ((Set)this.allSuperclasses());
    results.add(this);
    return (CollectedDistinctly<Classified>)((CollectedDistinctly)results);
  }

  /**
   * @return 
   */
  public   Behavior allSubclassesDo(final Closure aBlock)
  {
    java.lang.String exitID = "Behavior>>allSubclassesDo";
    Frame f0 = new Frame(exitID);
    this.subclassesDo(aBlock);
    this.subclassesDo(Closure.with(f2 -> {
      Behavior each = f2.getValue(0).value();
      return each.allSubclassesDo(aBlock);
    }, "each"));
    return (Behavior)this;
  }

  /**
   * @return 
   */
  public   Behavior allSuperclassesDo(final Closure aBlock)
  {
    java.lang.String exitID = "Behavior>>allSuperclassesDo";
    Frame f0 = new Frame(exitID);
    if (this.superclass().hasNoClass()) {
      return this;
    };
    ((Behavior)this.superclass()).onlySuperclassesDo(aBlock);
    return (Behavior)this;
  }

  /**
   * @return 
   */
  private   Behavior onlySuperclassesDo(final Closure aBlock)
  {
    java.lang.String exitID = "Behavior>>onlySuperclassesDo";
    Frame f0 = new Frame(exitID);
    aBlock.value(this.yourself());
    if (this.superclass().hasNoClass()) {
      return this;
    };
    ((Behavior)this.superclass()).onlySuperclassesDo(aBlock);
    return (Behavior)this;
  }

  /**
   * @return 
   */
  public   Behavior subclassesDo(final Closure aBlock)
  {
    java.lang.String exitID = "Behavior>>subclassesDo";
    Frame f0 = new Frame(exitID);
    this.subclasses().$do(aBlock);
    return (Behavior)this;
  }

  /**
   * @return 
   */
  public   Behavior withAllSubclassesDo(final Closure aBlock)
  {
    java.lang.String exitID = "Behavior>>withAllSubclassesDo";
    Frame f0 = new Frame(exitID);
    aBlock.value(this);
    this.allSubclassesDo(aBlock);
    return (Behavior)this;
  }

  /**
   * @return 
   */
  public   Behavior withAllSuperclassesDo(final Closure aBlock)
  {
    java.lang.String exitID = "Behavior>>withAllSuperclassesDo";
    Frame f0 = new Frame(exitID);
    aBlock.value(this);
    this.allSuperclassesDo(aBlock);
    return (Behavior)this;
  }

  /**
   * @return 
   */
  public  <ElementType extends Subject> Collected<ElementType> $new(final Ordinal capacity)
  {
    java.lang.String exitID = "Behavior>>$new";
    Frame f0 = new Frame(exitID);
    return (Collected<ElementType>)Array.type().$new(capacity);
  }

  /**
   * @return 
   */
  public  <ResultType extends Subject> ResultType $new()
  {
    java.lang.String exitID = "Behavior>>$new";
    Frame f0 = new Frame(exitID);
    return (ResultType)Primitive.newInstance(this.primitiveClass());
  }

  /**
   * @return 
   */
  public final   java.lang.Class primitiveSuperclass()
  {
    java.lang.String exitID = "Behavior>>primitiveSuperclass";
    Frame f0 = new Frame(exitID);
    return (java.lang.Class)this.primitiveClass().getSuperclass();
  }

  /**
   * @return 
   */
  public   Boolean hasHeritage()
  {
    java.lang.String exitID = "Behavior>>hasHeritage";
    Frame f0 = new Frame(exitID);
    if ((this.primitiveSuperclass() == null)) {
      return False.literal();
    };

    Typified result = HootRegistry.getType(this.primitiveSuperclass());
    if (result.hasNoClass()) {
      return False.literal();
    };
    return (Boolean)True.literal();
  }

  /**
   * @return 
   */
  public final   Behavior superior()
  {
    java.lang.String exitID = "Behavior>>superior";
    Frame f0 = new Frame(exitID);
    return (Behavior)((Behavior)this.superclass());
  }

  /**
   * @return 
   */
  public   Typified superclass()
  {
    java.lang.String exitID = "Behavior>>superclass";
    Frame f0 = new Frame(exitID);
    if (!(this.hasHeritage().asPrimitive())) {
      return null;
    };

    Typified result = HootRegistry.getType(this.primitiveSuperclass());
    if (result.hasNoClass()) {
      return null;
    };
    return (Typified)result;
  }

  /**
   * @return 
   */
  @Override public   Boolean isClass()
  {
    java.lang.String exitID = "Behavior>>isClass";
    Frame f0 = new Frame(exitID);
    return (Boolean)True.literal();
  }

  /**
   * @return 
   */
  @Override public   Boolean isBehavior()
  {
    java.lang.String exitID = "Behavior>>isBehavior";
    Frame f0 = new Frame(exitID);
    return (Boolean)True.literal();
  }

  /**
   * @return 
   */
  public   Boolean inheritsFrom(final Behavior candidateClass)
  {
    java.lang.String exitID = "Behavior>>inheritsFrom";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    Object.isNull(candidateClass).ifTrue(Closure.with(f2 -> {
      return (Boolean)f0.exit(exitID, False.literal());
    }, ""));
    return (Boolean)f0.exit(exitID, Boolean.from(candidateClass.primitiveClass().isAssignableFrom(this.primitiveClass())));
    });
  }

  /**
   * @return 
   */
  public   String namePrefix()
  {
    java.lang.String exitID = "Behavior>>namePrefix";
    Frame f0 = new Frame(exitID);
    Character first = ((Character)this.name().first());
    if (first.isVowel().asPrimitive()) {
      return String.from("an ");
    };
    return (String)String.from("a ");
  }

  /**
   * @return 
   */
  public   String name()
  {
    java.lang.String exitID = "Behavior>>name";
    Frame f0 = new Frame(exitID);
    return (String)String.from(this.typeName().hootName());
  }

  /**
   * @return 
   */
  public   String nameSpace()
  {
    java.lang.String exitID = "Behavior>>nameSpace";
    Frame f0 = new Frame(exitID);
    return (String)String.from(this.typeName().hootPackage());
  }

  /**
   * @return 
   */
  public   String simpleName()
  {
    java.lang.String exitID = "Behavior>>simpleName";
    Frame f0 = new Frame(exitID);
    return (String)String.from(this.typeName().shortName());
  }

  /**
   * @return 
   */
  public   String nameSort()
  {
    java.lang.String exitID = "Behavior>>nameSort";
    Frame f0 = new Frame(exitID);
    return (String)this.nameSpace().append(this.depth().printString()).append(this.simpleName());
  }

  /**
   * @return 
   */
  public   TypeName typeName()
  {
    java.lang.String exitID = "Behavior>>typeName";
    Frame f0 = new Frame(exitID);
    return (TypeName)TypeName.fromName(this.primitiveClass().getName());
  }

  /**
   * @return 
   */
  public  <NumericType extends Number> NumericType zero()
  {
    java.lang.String exitID = "Behavior>>zero";
    Frame f0 = new Frame(exitID);
    return (NumericType)((NumericType)SmallInteger.from(0));
  }

  /**
   * @return 
   */
  public   Integer depth()
  {
    java.lang.String exitID = "Behavior>>depth";
    Frame f0 = new Frame(exitID);
    return (Integer)SmallInteger.from(Primitive.hierarchyDepth(this.primitiveClass()));
  }
}