Class TUIModule.Builder<B extends TUIModule.Builder<B>>

java.lang.Object
com.calebleavell.jatui.modules.TUIModule.Builder<B>
All Implemented Interfaces:
DirectedGraphNode<TUIModule.Property,TUIModule.Builder<?>,B>
Direct Known Subclasses:
ApplicationModule.Builder, ContainerModule.Builder, FunctionModule.Builder, ModuleTemplate, TextInputModule.Builder, TextModule.Builder
Enclosing class:
TUIModule

public abstract static class TUIModule.Builder<B extends TUIModule.Builder<B>> extends Object implements DirectedGraphNode<TUIModule.Property,TUIModule.Builder<?>,B>
Builder for TUIModule. The builder uses a Curiously Recurring Template Pattern, which means Builders which extend this can use the fluent method chains provided by this builder while retaining their type.

Note: Module builders are lazily realized by the scheduler at runtime. Calling build() is generally not required (with the rare exception of cases like building an ApplicationModule first).

Required fields: type, name
Optional fields: children, propertyUpdateFlags, application, ansi, scanner, printStream, enableAnsi
Utility fields (not set by user): logger, usedNames
  • Field Details

    • name

      protected String name
      The identifier for this module.
      It is highly recommended to try and keep this unique in order to allow identification methods (e.g., via ApplicationModule.getInput(java.lang.String)) to function properly.
      Warnings and potentially errors will be logged if modules with duplicate names are created.
    • children

      protected List<TUIModule.Builder<?>> children
      Every child module that should be run.
    • propertyUpdateFlags

      Specifies how property propagation functions for application, ansi, scanner, printStream, and enableAnsi.
      Property updating behavior is provided by DirectedGraphNode.PropertyUpdateFlag. All properties are set to DirectedGraphNode.PropertyUpdateFlag.UPDATE by default.
    • application

      protected ApplicationModule application
      The application this module is tied to.
    • ansi

      protected org.fusesource.jansi.Ansi ansi
      The ansi that may be displayed (Jansi object). Note that not every module will display ansi.
    • scanner

      protected Scanner scanner
      The Scanner that reads input from the defined source. It is set to System.in by default (provided by TUIModule.DEFAULT_SCANNER).
      Implementation Note:
      See TUIModule.scanner for an explanation on why every module needs an individual reference to a scanner.
    • printStream

      protected PrintStream printStream
      PrintStream that outputs data to the defined location. It is set to System.in by default.
      Implementation Note:
      See TUIModule.scanner for an explanation on why every module needs an individual reference to a PrintStream.
    • enableAnsi

      protected boolean enableAnsi
      Whether ansi will be displayed or not.
    • type

      protected final Class<B extends TUIModule.Builder<B>> type
      The class extending this class (CRTP).
    • logger

      protected static final org.slf4j.Logger logger
      The Logger for the module, provided by the slf4j facade
    • usedNames

      protected static final Map<String,Integer> usedNames
      The frequency of names of all children of this module. This is used to support name duplicate detection.
      An error is logged if there are name collisions.
  • Constructor Details

    • Builder

      public Builder(Class<B> type, String name)
      Constructs a new TUIModule.Builder.
      Parameters:
      type - The type of the module. This is usually defined by the inheriting class (e.g., type for TextModule.Builder would be TextModule.Builder.class).
      name - The unique name of this module.
    • Builder

      protected Builder(Class<B> type)
      Constructs an empty TUIModule.Builder. Used for copying.
      Parameters:
      type - The type of the module. This is usually defined by the inheriting class (e.g., type for TextModule.Builder would be TextModule.Builder.class).
  • Method Details

    • createInstance

      protected abstract B createInstance()
      Gets a fresh instance of this type of Builder. Note, this is intended only for copying utility and may have unknown consequences if used in other ways.
      Returns:
      A fresh, empty instance.
    • deepCopy

      protected B deepCopy(B original, Map<TUIModule.Builder<?>,TUIModule.Builder<?>> visited)
      Copies all data of original into this module, including a deep copy of all children.
      Parameters:
      original - The module to copy from.
      visited - All children that have already been deep-copied.
      Returns:
      The instance that was copied into (self if original hasn't been visited yet).
    • deepCopy

      protected B deepCopy(B original)
      Wraps deepCopy(Builder, Map) to create copyMap for us.
      Parameters:
      original - The module to copy into this module.
      Returns:
      self
    • getDeepCopy

      public B getDeepCopy()
      Creates a deep copy of this node and it's children
      Returns:
      A deep copy of self
    • shallowCopy

      protected void shallowCopy(B original)
      Creates a copy of original by mutating this instance. Children are not copied. This is a utility method for getCopy()
      Parameters:
      original - The builder to copy from
    • getCopy

      public B getCopy()
      Creates a deep copy of this node and it's children; delegates to getDeepCopy(), created for simplicity.
      Returns:
      A deep copy of self
    • getType

      public Class<B> getType()
      Gets the type of this module; enables the CRTP.
      Specified by:
      getType in interface DirectedGraphNode<TUIModule.Property,TUIModule.Builder<?>,B extends TUIModule.Builder<B>>
      Returns:
      the class type of this module.
    • getChildren

      public List<TUIModule.Builder<?>> getChildren()
      Get the TUIModule Builders that are the children of this builder, in the order they will be run.
      Specified by:
      getChildren in interface DirectedGraphNode<TUIModule.Property,TUIModule.Builder<?>,B extends TUIModule.Builder<B>>
      Returns:
      The list of children of this module.
    • getPropertyUpdateFlags

      The PropertyUpdateFlags determine the behavior of property propagation. See TUIModule.Property and DirectedGraphNode.PropertyUpdateFlag.
      Specified by:
      getPropertyUpdateFlags in interface DirectedGraphNode<TUIModule.Property,TUIModule.Builder<?>,B extends TUIModule.Builder<B>>
      Returns:
      The flags for each property which determine propagation behavior.
    • updateFlag

      public B updateFlag(TUIModule.Property property, DirectedGraphNode.PropertyUpdateFlag flag)
      Set the propagation behavior of a specific property. See TUIModule.Property for the properties and DirectedGraphNode.PropertyUpdateFlag for behavior types.
      Parameters:
      property - The property given by TUIModule.Property
      flag - The propagation behavior given by DirectedGraphNode.PropertyUpdateFlag
      Returns:
      self
    • lockProperty

      public B lockProperty(TUIModule.Property property)
      Set the propagation behavior of property to not allow updates when a parent module is updated.
      Parameters:
      property - The property given by TUIModule.Property
      Returns:
      self
      Implementation Note:
      Internally, this sets the property flag to DirectedGraphNode.PropertyUpdateFlag.HALT
    • unlockProperty

      public B unlockProperty(TUIModule.Property property)
      Set the propagation behavior of property to allow updates when a parent module is updated. Properties are unlocked by default.
      Parameters:
      property - The property given by TUIModule.Property
      Returns:
      self
      Implementation Note:
      Internally, this sets the property flag to DirectedGraphNode.PropertyUpdateFlag.UPDATE
    • updateProperties

      public B updateProperties(TUIModule.Builder<?> module)
      Recursively updates all properties in this module based on the given module. All the properties that are updated are given by TUIModule.Property. This method does not override the property update flags given by DirectedGraphNode.PropertyUpdateFlag for either this module or for children.
      Parameters:
      module - The module to copy properties from.
      Returns:
      self
    • addChildren

      public B addChildren(List<TUIModule.Builder<?>> children)
      Linearly append the given children to this module's children.
      Parameters:
      children - The children to add.
      Returns:
      self
    • addChildren

      public B addChildren(TUIModule.Builder<?>... children)
      Linearly append the given children to this module's children.
      Parameters:
      children - The children to add.
      Returns:
      self
    • addChild

      public B addChild(TUIModule.Builder<?> child)
      Add a child to the end of this module's children.
      Parameters:
      child - The child to add.
      Returns:
      self
    • addChild

      public B addChild(int index, TUIModule.Builder<?> child)
      Attempts to add a child at the given index.
      Parameters:
      index - The index to add the child at.
      child - The child to add.
      Returns:
      self
    • clearChildren

      public TUIModule.Builder<B> clearChildren()
      Removes all children from this module.
      Returns:
      self.
    • getChild

      public TUIModule.Builder<?> getChild(String name)
      Finds a child matching the name. It is recommended to name all modules uniquely so this returns a unique module every time.
      Parameters:
      name - The name of the child
      Returns:
      The first found child (DFS), or null if none is found
    • getChild

      public <T extends TUIModule.Builder<?>> T getChild(String name, Class<T> type)
      Finds a child matching the name and class type. It is recommended to name all modules uniquely so this returns a unique module every time.
      Parameters:
      name - The name of the child
      type - the type of builder to search for (e.g., TextModule.class)
      Returns:
      The first found child (DFS), or null if none is found of the correct type.
    • getName

      public String getName()
      Returns:
      The name of this module.
    • name

      public B name(String name)
      Sets the name of this module. Ideally, each module should get a unique name. A warning is logged if a module is given a name that has been given to another module.
      Parameters:
      name - The unique name of this module.
      Returns:
      self
    • prependToName

      public void prependToName(String name)
      Prepends name to the current name of this module. Useful for doing things like adding the name of the parent module to this module.
      Parameters:
      name - The name to prepend to the current name.
    • getApplication

      public ApplicationModule getApplication()
      The ApplicationModule this module is tied to. An application module is primarily used for TUI input storage, as well as for providing a clean way to enter/exit the TUI.
      Returns:
      The ApplicationModule that this module is tied to.
    • getAnsi

      public org.fusesource.jansi.Ansi getAnsi()
      If this module displays text, this is the ansi that determines the text styling of that module (e.g., coloring, bolding, etc.). Ansi is provided by Jansi.
      Returns:
      The ansi stored in the module.
    • getScanner

      public Scanner getScanner()
      The Scanner that reads input from the defined source. It is set to System.in by default (provided by TUIModule.DEFAULT_SCANNER).
      Returns:
      The reference to the Scanner used by this module (Note that not every module will use the Scanner).
    • getPrintStream

      public PrintStream getPrintStream()
      PrintStream that outputs data to the defined location. It is set to System.in by default.
      Returns:
      The reference to the PrintStream used by this module (Note that not every module will use the PrintStream).
    • getAnsiEnabled

      public boolean getAnsiEnabled()
      Whether ansi is enabled applies to modules who may display text (e.g., TextModule). If ansi is disabled, only the raw text is displayed.
      Returns:
      Whether ansi is enabled for this module.
    • application

      public B application(ApplicationModule app)
      Sets the ApplicationModule for this module and recursively for its children.

      An application module is primarily used for TUI input storage, as well as for providing a clean way to enter/exit the TUI.
      For most cases, you only need one application module per TUI.

      Note: To prevent a module's application from being updated when you set the property of a parent, use lockProperty(Property). You can also use updateFlag(Property, PropertyUpdateFlag) for more fine-grained control.
      Parameters:
      app - The ApplicationModule that this module will be tied to.
      Returns:
      self
    • style

      public B style(org.fusesource.jansi.Ansi ansi)
      Sets the Ansi for this module and recursively for its children.

      For modules that display text,the ansi determines the text styling of that module (e.g., coloring, bolding, etc.). Ansi is provided by Jansi.

      Note: Setting the ansi automatically locks it from further updating, either directly or via updating a parent. If this is not desired, use unlockProperty(Property). You can also use updateFlag(Property, PropertyUpdateFlag). Setting the ansi uses TUIModule.Property.SET_ANSI. Note that defining behavior for SET_ANSI does not affect behavior for merging ansi (e.g., via prependStyle(Ansi)).
      Parameters:
      ansi - The Ansi that this module may use.
      Returns:
      self
    • prependStyle

      public B prependStyle(org.fusesource.jansi.Ansi ansi)
      Prepends Ansi to the beginning of the existing ansi for this module and recursively for its children.

      For modules that display text,the ansi determines the text styling of that module (e.g., coloring, bolding, etc.). Ansi is provided by Jansi.

      Note: To prevent a module's ansi from being merged into when you set the property of a parent, use lockProperty(Property). Prepending the ansi uses TUIModule.Property.MERGE_ANSI. You can also use updateFlag(Property, PropertyUpdateFlag) for more fine-grained control. Note that defining behavior for MERGE_ANSI does not affect behavior for setting ansi directly.
      Parameters:
      ansi - The Ansi that this module may use.
      Returns:
      self
    • appendStyle

      public B appendStyle(org.fusesource.jansi.Ansi ansi)
      Appends Ansi to the end of the existing ansi for this module and recursively for its children.

      For modules that display text,the ansi determines the text styling of that module (e.g., coloring, bolding, etc.). Ansi is provided by Jansi.

      Note: To prevent a module's ansi from being merged into when you set the property of a parent, use lockProperty(Property). Appending the ansi uses TUIModule.Property.MERGE_ANSI. You can also use updateFlag(Property, PropertyUpdateFlag) for more fine-grained control. Note that defining behavior for MERGE_ANSI does not affect behavior for setting ansi directly.
      Parameters:
      ansi - The Ansi that this module may use.
      Returns:
      self
    • scanner

      public B scanner(Scanner scanner)
      Sets the Scanner for this module and recursively for its children.

      The Scanner reads input from the defined source (note that not every module reads input). It is set to System.in by default (provided by TUIModule.DEFAULT_SCANNER).

      Note: Setting the scanner automatically locks it from further updating, either directly or via updating a parent. If this is not desired, use unlockProperty(Property). You can also use updateFlag(Property, PropertyUpdateFlag) for more fine-grained control.
      Parameters:
      scanner - The Scanner that this module may use.
      Returns:
      self
    • printStream

      public B printStream(PrintStream printStream)
      Sets the Scanner for this module and recursively for its children.

      The PrintStream outputs data to the defined location (note that not every module writes data). It is set to System.in by default.

      Note: Setting the PrintStream automatically locks it from further updating, either directly or via updating a parent. If this is not desired, use unlockProperty(Property). You can also use updateFlag(Property, PropertyUpdateFlag) for more fine-grained control.
      Parameters:
      printStream - The PrintStream that this module may use.
      Returns:
      self
    • enableAnsi

      public B enableAnsi(boolean enable)
      Enables or disables ansi for this module and recursively for its children.

      Locking TUIModule.Property.SET_ANSI does not prevent ansi from being disabled via this method. You must lock TUIModule.Property.ENABLE_ANSI.
      Ansi is enabled by default.

      For modules that display text,the ansi determines the text styling of that module (e.g., coloring, bolding, etc.). Ansi is provided by Jansi.

      Note: Changing whether ansi is enabled automatically locks it from further updating, either directly or via updating a parent. If this is not desired, use unlockProperty(Property). You can also use updateFlag(Property, PropertyUpdateFlag). Changing whether ansi is enabled uses TUIModule.Property.ENABLE_ANSI. Note that defining behavior for ENABLE_ANSI does not affect behavior for setting or merging ansi (e.g., via prependStyle(Ansi)).
      Parameters:
      enable - Whether ansi is enabled.
      Returns:
      self
    • self

      public B self()
      Casts this builder into the type given by the CRTP.
      Specified by:
      self in interface DirectedGraphNode<TUIModule.Property,TUIModule.Builder<?>,B extends TUIModule.Builder<B>>
      Returns:
      self, casted to the appropriate type
      Implementation Note:
      This is a safe operation because type is enforced to be type B at runtime.
    • shallowStructuralEquals

      public boolean shallowStructuralEquals(B first, B second)

      Checks equality for properties given by the builder.

      For TUIModule, this includes:

      • name
      • application
      • ansi
      • scanner
      • printStream
      • enableAnsi

      Note: Runtime properties (e.g., currentRunningChild, terminated), are not considered. Children are also not considered here, but are considered in equals().

      Specified by:
      shallowStructuralEquals in interface DirectedGraphNode<TUIModule.Property,TUIModule.Builder<?>,B extends TUIModule.Builder<B>>
      Parameters:
      first - The first TUIModule to compare
      second - The second TUIModule to compare
      Returns:
      true if first and second are equal according to builder-provided properties
      Implementation Note:
      This is the Function<TUIModule<?>, TUIModule.Builder<?>, Boolean> that is passed into DirectedGraphNode.structuralEquals(DirectedGraphNode)
    • structuralEquals

      public static boolean structuralEquals(TUIModule.Builder<?> first, TUIModule.Builder<?> second)
      This is the same as shallowStructuralEquals, but it's static and does include a recursive children check.
      Parameters:
      first - The first TUIModule to compare
      second - The second TUIModule to compare
      Returns:
      true if first and second are equal according to builder-provided properties
      Implementation Note:
      Polymorphism is automatic here and thus this method does not generally need to be overloaded.
    • toString

      public String toString()
      Returns the name of this module. For a formatted string of the module hierarchy stemming from this module, see TUIModule.toTreeString(). This will require building the module.
      Overrides:
      toString in class Object
      Returns:
      The name of this module.
    • build

      public abstract TUIModule build()
      Builds and returns the configured TUIModule.
      Returns:
      the constructed module.