Class InsertionService

java.lang.Object
com.tccc.kos.commons.util.ready.ReadyBean
com.tccc.kos.commons.core.service.AbstractService
com.tccc.kos.ext.dispense.service.insertion.InsertionService
All Implemented Interfaces:
com.tccc.kos.commons.core.context.CtxEventListener, com.tccc.kos.commons.core.service.handle.ContextHandleAware, com.tccc.kos.commons.core.service.handle.HandleAware, com.tccc.kos.commons.core.service.trouble.TroubleAware, com.tccc.kos.commons.util.ready.Ready, com.tccc.kos.commons.util.ready.ReadyListener, com.tccc.kos.core.service.assembly.AssemblyListener, PumpListener, ReplaceLineListener

public final class InsertionService extends com.tccc.kos.commons.core.service.AbstractService implements com.tccc.kos.core.service.assembly.AssemblyListener, com.tccc.kos.commons.core.service.trouble.TroubleAware, ReplaceLineListener
Service that manages the process of inserting an ingredient container into holders. This service allows filters to be added and every insertion must pass every filter in order to successfully complete the insertion process. For example, a filter may check if an ingredient is expired or sold out before allowing it to be inserted.

This service tracks installed containers so the data is available to filters which can enforce rules around switching ingredients. However, this service does not assume that containers that existed before the last reboot are installed after a reboot. That is, on every restart it is the responsibility of some other service to insert all the ingredients again. For more complex devices like Freestyle dispensers which have rfid to detect cartridges, this handles the case where someone swapped cartridges while the device was turned off. For a more typical BiB device the IngredientAssignmentService can be used to persistently assign an ingredient to a holder and that service will perform all the insertions at startup.

When a filter prevents a container from being inserted, it remains in the insertion queue unless explicitly removed. This allows pending insertions to be retried if internal state changes such that the insertion may be successful. For example, consider a filter that blocks insertions of containers that use unknown ingredients. Until ingredients are installed all containers will have unknown ingredients and thus the filter will block all insertions. Once ingredients become available the pending inserts can be retried and completed as ingredients will now be known.

When a cartridge is removed using this service, all troubles tagged with the container will also be removed. Any troubles added using a filter will automatically be tagged with the container. Any troubles generated after insertion that are relative to the cartridge (sold out, expired, etc...) should tag the container to be removed automatically. The troubles related to this service such as ContainerTrouble and ContainerHolderTrouble will automatically tag the container.

Since:
1.0
Version:
2023-03-06
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
     
    static final String
     
    static final String
     
    static final String
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    Add a filter to the filter list.
    void
    addFilter(InsertionFilter<?> filter, double group)
    Add a filter to the filter list at the next available position for the specified group.
    void
    addFilter(InsertionFilter<?> filter, double group, double position)
    Add a filter to the internal list in the specified group at the specified position.
    void
    Trigger async retry all pending inserts
    Return all previously inserted ingredientId's for the pump.
    void
    insert(boolean inventoryScan, Container container, Holder holder)
    Insert the specified container into the specified holder.
    void
    insert(boolean inventoryScan, Container container, String holderPath)
    Convenience method for calling insert() after looking up the Holder from the specified holderPath .
    void
    insertIntrinsic(String ingredientId, Holder holder)
    Insert an intrinsic ingredient to a holder.
    void
    insertIntrinsic(String ingredientId, String holderPath)
    Insert an intrinsic ingredient to a holder.
    void
    insertLocked(String ingredientId, Holder holder)
    Insert a locked ingredient to a holder.
    void
    insertLocked(String ingredientId, String holderPath)
    Insert a locked ingredient to a holder.
    void
    markAndSweep(String source, String mark)
    Perform a mark-and-sweep cleanup of all containers associated with the specified source that have a mark other than the specified mark.
    boolean
     
    void
    Called when a line is replaced for the holder.
    void
    onPostInstall(com.tccc.kos.core.service.assembly.Assembly assembly)
     
    void
    onPostUninstall(com.tccc.kos.core.service.assembly.Assembly assembly)
     
    void
    onTroubleAdded(com.tccc.kos.commons.core.service.trouble.Trouble trouble)
     
    void
    onTroubleRemoved(com.tccc.kos.commons.core.service.trouble.Trouble trouble)
     
    void
    onTroubleResolved(com.tccc.kos.commons.core.service.trouble.Trouble trouble, boolean success)
     
    void
    Remove the container from the associated holder or from the pending insert list.
    void
    Remove a filter from the service.
    void
    Remove the container attached to the specified holder.
    void
    Remove the container attached to the specified holder.

    Methods inherited from class com.tccc.kos.commons.core.service.AbstractService

    getHandle, getHandlePrefix

    Methods inherited from class com.tccc.kos.commons.util.ready.ReadyBean

    getReady, onDependenciesReady

    Methods inherited from class java.lang.Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface com.tccc.kos.core.service.assembly.AssemblyListener

    onInstall, onPreInstall, onPreUninstall, onUninstall

    Methods inherited from interface com.tccc.kos.commons.core.context.CtxEventListener

    onCtxAutowiringCompleted, onCtxDestroyed, onCtxPhaseCompleted

    Methods inherited from interface com.tccc.kos.commons.core.service.handle.HandleAware

    addHandleChild, getName, getPath

    Methods inherited from interface com.tccc.kos.commons.util.ready.Ready

    isReady, setReady

    Methods inherited from interface com.tccc.kos.commons.util.ready.ReadyListener

    onDependenciesGroupReady
  • Field Details

  • Method Details

    • onBeanReady

      public boolean onBeanReady()
      Overrides:
      onBeanReady in class com.tccc.kos.commons.util.ready.ReadyBean
    • insertIntrinsic

      public void insertIntrinsic(String ingredientId, Holder holder)
      Insert an intrinsic ingredient to a holder. Intrinsic ingredients tend to be fixed ingredients like water and carb, which are physically plumbed to the wall and cannot ever be changed. An intrinsic insertion will bypass all insertion filters and will be locked so that it cannot be removed.

      Some ingredients like HFCS or NNS may have dedicated pumps and might be considered intrinsic, but they may rely on a setup process to initialize them which can be triggered by filters during the first insertion. In these cases it may be easier to use regular insert vs. intrinsic insert.

      Intrinsics use the holder path as the container id.

      Parameters:
      ingredientId - the id of the ingredient to be inserted
      holder - the holder to insert into
    • insertIntrinsic

      public void insertIntrinsic(String ingredientId, String holderPath)
      Insert an intrinsic ingredient to a holder. Intrinsic ingredients tend to be fixed ingredients like water and carb, which are physically plumbed to the wall and cannot ever be changed. An intrinsic insertion will bypass all insertion filters and will be locked so that it cannot be removed.

      Some ingredients like HFCS or NNS may have dedicated pumps and might be considered intrinsic, but they may rely on a setup process to initialize them which can be triggered by filters during the first insertion. In these cases it may be easier to use regular insert vs. intrinsic insert.

      Intrinsics use the holder path as the container id.

      Parameters:
      ingredientId - the id of the ingredient to be inserted
      holderPath - the holder path to insert into
    • insertLocked

      public void insertLocked(String ingredientId, Holder holder)
      Insert a locked ingredient to a holder. Locked ingredients tend to be fixed ingredients like nutritive or non-nutritive sweeteners that are locked to a given holder and while physically replaced, are never logically removed in software. Unlike intrinsics, locked insertions are subject to insertion filters which can trigger setup processes for first time use, providing this functionality for free without requiring custom setup logic.

      Locked insertions use the holder path as the container id.

      Parameters:
      ingredientId - the id of the ingredient to be inserted
      holder - the holder to insert into
    • insertLocked

      public void insertLocked(String ingredientId, String holderPath)
      Insert a locked ingredient to a holder. Locked ingredients tend to be fixed ingredients like nutritive or non-nutritive sweeteners that are locked to a given holder and while physically replaced, are never logically removed in software. Unlike intrinsics, locked insertions are subject to insertion filters which can trigger setup processes for first time use, providing this functionality for free without requiring custom setup logic.

      Locked insertions use the holder path as the container id.

      Parameters:
      ingredientId - the id of the ingredient to be inserted
      holderPath - the holder path to insert into
    • insert

      public void insert(boolean inventoryScan, Container container, String holderPath)
      Convenience method for calling insert() after looking up the Holder from the specified holderPath . See other insert() for more details.
      Parameters:
      inventoryScan - true if part of inventory scan at boot, vs inserted after boot
      container - the container to install
      holderPath - holder path to insert into
    • insert

      public void insert(boolean inventoryScan, Container container, Holder holder)
      Insert the specified container into the specified holder. If the container contains multiple slices then the following assumptions are made:
      • The holders support getNext() in order to identify the additional holders the container spans. An example of this is a Freestyle dual cartridge which consumes more than one holder in shelf.
      • The holder specified is the leftmost / topmost holder in the group. That is, all additional holders are identified by getNext() .

      When a device first boots there is a concept of an inventory scan of existing ingredients. For example, for assignments stored in a database, these would be the existing assignments vs assignments made after the system is running. For Freestyle, this would be rfid tags found in the shelves during the first few shelf scans. This flag allows filters to behave differently for ingredients that are assumed to have existed across a reboot and may not be subject to the same processes as a newly inserted ingredient.

      Parameters:
      inventoryScan - true if part of inventory scan at boot, vs inserted after boot
      container - the container to install
      holder - holder to insert into
    • removeFromHolder

      public void removeFromHolder(String holderPath)
      Remove the container attached to the specified holder.
      Parameters:
      holderPath - the holder to remove the container from
    • removeFromHolder

      public void removeFromHolder(Holder holder)
      Remove the container attached to the specified holder.
      Parameters:
      holder - the holder to remove the container from
    • removeContainer

      public void removeContainer(Container container)
      Remove the container from the associated holder or from the pending insert list.
      Parameters:
      container - the container to remove
    • addFilter

      public void addFilter(InsertionFilter<?> filter)
      Add a filter to the filter list. This will effectively append the filter to the default group group 0.0 with the next available position.
      Parameters:
      filter - the filter to add
    • addFilter

      public void addFilter(InsertionFilter<?> filter, double group)
      Add a filter to the filter list at the next available position for the specified group.

      Most filters are added in the order in which they should run, thus the default addFilter(filter) method is all that is needed. However, if there is a need to add a filter to the end of the chain and keep it there as new filters are added, this method can be used with a group number greater than 0.0 as addFilter(filter) always appends to the 0.0 group.

      Parameters:
      filter - the filter to add
      group - the group to add the filter to
    • addFilter

      public void addFilter(InsertionFilter<?> filter, double group, double position)
      Add a filter to the internal list in the specified group at the specified position. If there is already a filter at this group and position, the order of the two filters will be undefined. All filters are ordered by group and then position within the group.

      If the position has a greater value than the next available position for the group, the next available position will be set to the next value after the new position (any new appends will occur after this filter). If the value is lower than any existing filters (an insert between existing filters) then the next position for the group will remain unchanged.

      Most filters are added in the order in which they should run, thus the default addFilter(filter) method is all that is needed. However, if there is a need to insert a filter between two existing filters, this method can be used to position a filter anywhere in the chain. This requires examining the existing chain and picking the correct group / position combination to place the new filter in the desired location.

      Parameters:
      filter - the filter to add
      group - the group to add the filter to
      position - the position in the group for the filter
    • removeFilter

      public void removeFilter(InsertionFilter<?> filter)
      Remove a filter from the service.
    • asyncRetryPending

      public void asyncRetryPending()
      Trigger async retry all pending inserts
    • getPrevIngredientIds

      public Collection<String> getPrevIngredientIds(Pump<?> pump)
      Return all previously inserted ingredientId's for the pump.
      Parameters:
      pump - the pump to return ingredients for
    • markAndSweep

      public void markAndSweep(String source, String mark)
      Perform a mark-and-sweep cleanup of all containers associated with the specified source that have a mark other than the specified mark. This is typically used with self-identifying containers using technologies such as RFID. If a container is detected and inserted, but the device is then powered down and the container removed, there is no remove event to indicate that the container is gone. While not considered inserted, it leaves a remnant insertion record that may be used on a future insertion. This allows for cleaning up the records by inserting all the detected containers with a new mark and then performing a mark-and-sweep which will remove all the remaining records for the specified source, where a source may be something like the id of an RFID antenna. This tends to be a special use case and is not needed in most implementations.
    • onPostInstall

      public void onPostInstall(com.tccc.kos.core.service.assembly.Assembly assembly)
      Specified by:
      onPostInstall in interface com.tccc.kos.core.service.assembly.AssemblyListener
    • onPostUninstall

      public void onPostUninstall(com.tccc.kos.core.service.assembly.Assembly assembly)
      Specified by:
      onPostUninstall in interface com.tccc.kos.core.service.assembly.AssemblyListener
    • onTroubleAdded

      public void onTroubleAdded(com.tccc.kos.commons.core.service.trouble.Trouble trouble)
      Specified by:
      onTroubleAdded in interface com.tccc.kos.commons.core.service.trouble.TroubleAware
    • onTroubleResolved

      public void onTroubleResolved(com.tccc.kos.commons.core.service.trouble.Trouble trouble, boolean success)
      Specified by:
      onTroubleResolved in interface com.tccc.kos.commons.core.service.trouble.TroubleAware
    • onTroubleRemoved

      public void onTroubleRemoved(com.tccc.kos.commons.core.service.trouble.Trouble trouble)
      Specified by:
      onTroubleRemoved in interface com.tccc.kos.commons.core.service.trouble.TroubleAware
    • onLineReplaced

      public void onLineReplaced(Holder holder)
      Description copied from interface: ReplaceLineListener
      Called when a line is replaced for the holder.
      Specified by:
      onLineReplaced in interface ReplaceLineListener
      Parameters:
      holder - the holder with the line being replaced