R/StateManager.R

#==============================================================================#
#                                 StateManager                                 #
#==============================================================================#
#' StateManager
#'
#' \code{StateManager} Class for managing persistence and states of objects
#' within the NLPStudio package.
#'
#' \strong{StateManager Class Overview:}
#' The StateManager class object provides overall management of object state
#' within the NLPStudio package. It accepts a save or restore request from
#' a client object, statess the request, dispatches the appropriate StateManager
#' (and, if requested, StateArchiver) object(s). Once the request is fulfilled
#' by the subclass(es), the object is returned to the StateManager.  The
#' StateManager adds the object with a designated stateId to its inventory
#' of states. A summary of the request is also stored for query and
#' restore purposes.
#'
#' \strong{State Class Family  Overview:}
#' The State family of classes is responsible for managing object persistence
#' and an archive / restore capability within the NLPStudio objects.
#'
#' \strong{State Class Family Participants:}
#' The participants of the family are as follows:
#' \itemize{
#'  \item StateManager: This class accepts save / restore requests from object
#'  methods, statess the request and dispatches requests to the StateManager, and,
#'  if the client requests that files be saved or restored, the StateArchiver
#'  class.
#'  \item StateManager: This class is responsible for saving and restoring
#'  objects from and to existing objects.
#'  \item StateArchiver: This class is responsible for archiving and
#'  restoring any files associated with an object being saved or restored.
#'  }
#'
#' \strong{StateManager Methods:}
#' The methods for the StateManager class are as follows:
#' \describe{
#'  \item{\code{getState(stateId)}}{Returns the object at the state designated by the stateId parameter.}
#'  \item{\code{restoreState(stateId, files = FALSE)}}{Restores the object at the state designated by the stateId parameter to the global environment. If files is set TRUE, previously archived directories and files are restored. If the object is part of a composite, e.g. Document or DocumentCollection class object, and its parent does not exist, the files will be restored to an orphan object according to the class of the object, the files will be restored to the orphan object directory, and the parent will be changed accordingly. In this case the restored object may then be moved to another parent as required.}
#'  \item{\code{saveState(object, files = FALSE)}}{Saves the current state of an object and dispatches a StateManager object to save the state to disk. If the files parameter is set to true, a VisitorArchive object will be instantiated to compress and save the  files associated with the object to an archive directory.}
#' }
#'
#' @param object The object to be loaded or saved. Required parameter for the saveState method.
#' @param stateId The unique identifier for the object and state. Required parameter for the restoreState method.
#' @param files statesical indicating whether the files associated with an object should be archived.
#' @param dateFrom Character string containing a date in any ISO 8601 format, from which state records should be returned.
#' @param dateTo Character string containing a date in any ISO 8601 format, from which state records should be returned.
#' @param class Character string indicating the class for which state records should be returned.
#' @param object Character string indicating the name of the object for which state records should be returned.
#'
#' @return stateId From the setState function, a character string with the stateId assigned by the stateManager
#' @return object From the restoreState method the object returned from the state archive.
#'
#' @docType class
#' @author John James, \email{jjames@@datasciencesalon.org}
#' @family State Classes
#' @export
StateManager <- R6::R6Class(
  "SingletonContainer",
  portable = FALSE,
  inherit = Singleton,
  public = list(
    initialize = function(...) {
      Class <<- R6::R6Class(
        classname = "StateManager",
        private = list(
          ..name = "stateManager",
          ..desc = "StateManager NLPStudio Object State Manager",
          ..states = list(),
          ..stateClasses = character(0),
          ..statesFile = character(0),
          ..created = character(0),
          ..modified = character(0),

          getConstants = function() {
            constants <- Constants$new()
            private$..stateClasses <- constants$getStateClasses()
          },

          assignStateId = function(name) {
            seqNum <- 1
            states <- as.data.frame(private$..states)

            if (nrow(states) > 0 ) {
              if (nrow(subset(states,
                              as.Date(created) == as.Date(Sys.time()) &
                              objectName == name)) > 0) {
                seqNum <- states %>%
                  filter(as.Date(created) == as.Date(Sys.time()) &
                           objectName == name) %>%
                  summarise(max(seqNum))
                seqNum <- seqNum + 1
              }
            }

            stateId <- paste0(name,"-", as.Date(Sys.time()), "-", seqNum)
            return(stateId)
          }
        ),

        public = list(

          initialize = function() {
            private$getConstants()
            private$..created <- Sys.time()
            private$..modified <- Sys.time()
            invisible(self)
          },

          getInstance = function() invisible(self),

          #-------------------------------------------------------------------#
          #                        saveState Method                           #
          #-------------------------------------------------------------------#
          saveState = function(object, stateNote = NULL) {

            #TODO: Validate request to save state through validator
            #TODO: Validate request to explose object through validator

            # Obtain object information and format stateId
            o <- object$exposeObject()
            o$class <- class(object)[1]
            stateId <- assignStateId(paste(o$class,"-",o$name))

            # Generate key
            t <- Tools$new()
            key <- t$makeRandomString()

            # Create state object and dispatch save request
            state <- State$new(key)
            path <- state$save(key = key, stateId = stateId, object = object)

            #  Create log entry for new saved state
            state <- list(
              stateId = stateId,
              class = o$class,
              name = o$name,
              desc = o$desc,
              note = stateNote,
              path = path,
              created = Sys.time())

            # Save state to memory list and to the serialized list on file
            private$..states[[stateId]] <- state
            statesFile <- readRDS(private$..statesFile)
            statesFile[[stateId]] <- state
            saveRDS(statesFile, file = private$..statesFile)

            invisible(stateId)

          },

          restoreState = function(stateId) {

            #TODO: Validate request to restore through validator class

            # Generate key
            t <- Tools$new()
            key <- t$makeRandomString()

            # Create state object and dispatch restore request
            state <- State$new(key)
            object <- state$restoreState(key = key, stateId = stateId)

            return(object)
          },

          #-------------------------------------------------------------------#
          #                        State Query Methods                        #
          #-------------------------------------------------------------------#

          getStates = function(){
            #TODO: VAlidate request to read states through validator class and visitor
            return(private$..states)
          }
        )
      )
      super$initialize(...)
    }
  ),lock_objects = FALSE
)#$new()
j2scode/NLPStudio documentation built on May 7, 2019, 8:58 p.m.