Skip to content
Snippets Groups Projects
utils.R 7.71 KiB
Newer Older
#This script contains some useful methods for a developer.


#============================== INFO UTILITY ================================


#'@description Helper function for get_status() to check if a list has at least one element.
#'@param flag Boolean flag to keep track of missing components
#'@param obj_list The specified list
#'@param element_type Optional: What kind of elements are in the list?
#'@param is_opt Does the list need at least one element?
get_list_status <- function(flag, obj_list, element_type = "list element", is_opt = FALSE){

  sim_ready <- flag
    if(!is_opt){
      cat(crayon::red("\u2717"))
      sim_ready <- FALSE
    }else{
      cat(crayon::yellow("()"))
    }
  }else{
    cat(crayon::green("\u2713"))
  }

  cat(" At least one", element_type, "was defined", "\n")

#'@description Helper function for get_status() to check if an object was defined.
#'@param flag Boolean flag to keep track of missing components
#'@param obj The specified object
#'@param obj_type Optional: What kind of object is this?
obj_is_defined <- function(flag, obj, obj_type = ""){
  is_defined <- flag

  if(is.null(obj)){
    cat(crayon::red("\u2717"))
  }else{
    cat(crayon::green("\u2713"))
  }

  cat(" ", obj_type, "object is not NULL", "\n")

  return(invisible(is_defined))
}
#============================== VALIDATION UTILITY ================================

#'validate_paths
#'@description Helper function to pull path validation out of already large class OGS6
#'@param sim_path The path where all relevant files for the simulation will be saved
#'@param ogs_bin_path Path to OpenGeoSys6 /bin directory
validate_paths <- function(sim_path, ogs_bin_path){
  if(!dir.exists(sim_path)){
    dir.create(sim_path)
  }else{
    if(length(dir(sim_path, all.files = TRUE)) != 0){
      warning(paste0("The sim_path directory you defined ('", sim_path,
                     "') already exists (that is ok). However, ",
                     "it is not empty. Files may be overwritten."), call. = FALSE)
    }
  }

  if(!file.exists(paste0(ogs_bin_path, "generateStructuredMesh.exe"))) {
    stop(paste("Could not find executable file generateStructuredMesh.exe at location",
               ogs_bin_path), call. = FALSE)
  }
}


#'validate_param_list
#'@description Validator function for a parameter list
#'@param param_list A list of parameters
#'@param expected_length The expected list length
#'@param possible_names How the list elements may be named (if the user DID name them)
validate_param_list <- function(param_list, expected_length, possible_names) {

  if(!is.list(param_list)){
    stop("Argument param_list passed to validate_param_list must be a list", call. = FALSE)
  }

  if(length(param_list) != expected_length){
    stop(paste(deparse(quote(param_list)), "must be a list of length", expected_length),
         call. = FALSE)
  }

  if(!is.null(names(param_list)) &&
     names(param_list) != possible_names){
    stop(paste0("If you do name the elements of ", deparse(quote(param_list)), ", stick to their default
              values to avoid confusion: '", paste(possible_names, collapse="', '"), "'"),
         call. = FALSE)
  }
}


#'@description Helper function, checks if a lists consists only of elements of a specific class
#'@param wrapper_list The list to check
#'@param expected_element_class The class each element of the wrapper list should have
validate_wrapper_list <- function(wrapper_list, expected_element_class) {

  assertthat::assert_that(is.list(wrapper_list))

  for(i in seq_len(length(wrapper_list))){
    if(class(wrapper_list[[i]]) != expected_element_class){
      stop(paste("List has at least one element whose class is not", expected_element_class),
#============================== XML UTILITY ================================

#'simple_list_to_node
#'@description Helper to turn a simple vector into the corresponding node structure
#' with the vector elements as children. This works for lists too (as they are vectors).
#'@param parent_name The name of the parent node
#'@param simple_vector The vector to turn into the node structure
simple_vector_to_node <- function(parent_name, simple_vector){

  assertthat::assert_that(assertthat::is.string(parent_name))
  assertthat::assert_that(is.vector(simple_vector))

  for(i in seq_len(length(simple_vector))){
    if(length(simple_vector[[i]]) != 1){
      stop(paste("simple_vector_to_node 'simple_vector' parameter may only contain",
                 "atomic values!"), call. = FALSE)
    }
  }

  node <- list(structure(list()))
  names(node)[[1]] <- parent_name

  for(i in seq_len(length(simple_vector))){
    element_name <- names(simple_vector)[[i]]
    element_list <- list(list(simple_vector[[i]]))
    names(element_list)[[1]] <- element_name

    node[[1]] <- c(node[[1]], element_list)
  }
#'adopt_nodes
#'@description Takes a homogenous list of r2ogs6_* objects and creates a wrapper node
#' using the generic function as_node
#'@param parent_name The name of the new parent node
#'@param obj_list A list of class objects (class should have method for generic function as_node)
adopt_nodes <- function(parent_name, obj_list) {

  if(length(obj_list) == 0){
    return(invisible(NULL))
  }

  node <- list(list())
  names(node)[[1]] <- parent_name
  for(i in seq_len(length(obj_list))) {
    #cat(class(obj_list[[i]]), " ", obj_list[[i]], "\n")
    node[[1]] <- c(node[[1]], list(as_node(obj_list[[i]])))
#'add_attr
#'@description Adds an attribute to a node attribute list
#'@param node The node the attribute should be added to
#'@param obj_parameter The value of the attribute to be added
#'@param attr_name The name of the attribute to be added
add_attr <- function(node, obj_parameter, attr_name) {
  if(!is.null(obj_parameter)) {
    attributes(node[[1]])[[attr_name]] <- obj_parameter
#'add_children
#'@description Adds one or more children to a node child list
#'@param node The node the children should be added to
#'@param children The children to be added (a partially named list)
add_children <- function(node, children) {
  assertthat::assert_that(is.list(children))

  for(i in seq_len(length(children))){

    #If the child is a r2ogs6 class object, call as_node on it
    if(any(grepl("r2ogs6", class(child)))){
      node[[1]][[length(node[[1]]) + 1]] <- as_node(child)
      #If the child is a wrapper, leave it alone
      if(is.list(child)){
        node[[1]][[length(node[[1]]) + 1]] <- child
      #If the child has a name
      }else if(!is.null(child_name) && child_name != "") {
        new_node <- as_node(child, child_name)
        node[[1]][[length(node[[1]]) + 1]] <- new_node
        stop(paste("add_children: Trying to add an unnamed child which is not",
                   "already a node (list) or an r2ogs6_* class object"), call. = FALSE)


#================================Test if S3 object in R6 class inherits reference semantics

# A <- R6::R6Class("A",
#   public = list(
#
#       b_obj = NULL,
#
#       initialize = function(b_obj) {
#           self$b_obj <- b_obj
#         }
#   )
# )
#
# b <- function(x){
#     structure(x,
#               class = "b")
# }
#
# mod_func_a <- function(a_obj){
#     a_obj$b_obj$x <- 100
# }
#
# a_obj <- A$new(b(42))
#
# mod_func_a(a_obj)
#
# a_obj$b_obj$x
#
#
# mod_func_b <- function(b_obj){
#     b_obj$x <- 100
# }
#
# b_obj <- b(42)
#
# mod_func_b(b_obj)
#
# b_obj