Newer
Older
#===== Implementation utility =====
#' get_class_from_xpath
#' @description Gets r2ogs6 class name from an xpath-like expression
#' @param xpath string: An xpath expression. Works for path-like xpaths only
#' @return string: The class name.
get_class_from_xpath <- function(xpath){
assertthat::assert_that(assertthat::is.string(xpath))
xpaths_for_classes <- xpaths_for_classes
for(i in seq_len(length(xpaths_for_classes))){
if((assertthat::is.string(xpaths_for_classes[[i]]) &&
xpaths_for_classes[[i]] == xpath) ||
(length(xpaths_for_classes[[i]]) > 1 &&
xpath %in% xpaths_for_classes[[i]])){
return(names(xpaths_for_classes)[[i]])
}
}
#' get_tag_from_class
#' @description Utility function, returns the tag name of a r2ogs6 class
#' @param class_name string: The name of a r2ogs6 class
#' @return string: The tag name corresponding to \code{class_name}
get_tag_from_class <- function(class_name) {
assertthat::assert_that(assertthat::is.string(class_name))
xpaths_for_classes <- xpaths_for_classes
xpath <- xpaths_for_classes[[class_name]]
split_xpath <- unlist(strsplit(xpath[[1]], "/", fixed = TRUE))
tag_name <- split_xpath[[length(split_xpath)]]
return(tag_name)
#' get_tag_from_xpath
#' @description Gets the XML tag name from an xpath expression
#' @param xpath string: An xpath expression. Works for path-like xpaths only
#' @return string: The XML tag name
get_tag_from_xpath <- function(xpath){
xpath_split <- unlist(strsplit(xpath, "/", fixed = TRUE))
tag_name <- xpath_split[[length(xpath_split)]]
}
#' @description Gets top level .prj tags along with info if they are required.
#' @return list: List of lists.
prj_reduxml <- system.file("extdata/xml_redux/", "prj_redu.xml",
package = "r2ogs6")
xml_doc <- xml2::read_xml(prj_reduxml)
prj_tag_info <- lapply(xml2::xml_children(xml_doc), function(x){
list(tag_name = xml2::xml_name(x),
is_required = as.logical(xml2::xml_attrs(x)[["required"]]))
})
Ruben Heinrich
committed
#' coerce_string_to_numeric
#' @description If an object is of type string, coerces it to a numeric type
#' @param obj object: Any object
#' @return numeric if \code{obj} was a string, else unchanged \code{obj}
coerce_string_to_numeric <- function(obj){
obj <- trimws(gsub("\r?\n|\r|\\s+", " ", obj))
obj <- as.double(unlist(strsplit(obj, " ")))
}
#' coerce_names
#' @description Validator function for a parameter vector
#' @param vector vector: Vector of parameters
#' @param names character: How the vector elements will be named as
#' @return vector: Named vector where the names correspond to \code{names}
coerce_names <- function(vector, names) {
assertthat::assert_that(is.vector(vector))
assertthat::assert_that(is.character(names))
assertthat::assert_that(length(vector) == length(names))
sorted_param_names <- sort(names(vector))
sorted_names <- sort(names)
if(is.null(names(vector)) ||
(!is.null(names(vector)) &&
any(sorted_param_names != sorted_names))){
message(paste0(
"Renaming elements of ",
deparse(quote(vector)),
" to fit their default names: '",
paste(names, collapse = "', '"),
"'"))
}
return(invisible(vector))
}
#' is_null_or_coerce_names
#' @description Validator function for a parameter list or vector or \code{NULL}
#' @param obj A list (or vector) of parameters
#' @param names How the list elements will be named as per default
is_null_or_coerce_names <- function(obj, names){
if(!is.null(obj)){
obj <- coerce_names(obj, names)
#' clean_imported_list
#' @description Cleans an imported list because sometimes strings containing
Ruben Heinrich
committed
#' only newline characters and spaces get imported in
#' @param list list: A list
clean_imported_list <- function(list){
Ruben Heinrich
committed
assertthat::assert_that(is.list(list))
Ruben Heinrich
committed
cleaned_list <- list()
for(i in seq_len(length(list))){
if(assertthat::is.string(list[[i]]) &&
stringr::str_remove_all(list[[i]], "[\n|[:space:]]") == ""){
Ruben Heinrich
committed
}
cleaned_list <- c(cleaned_list, list(list[[i]]))
names(cleaned_list)[[length(cleaned_list)]] <- names(list)[[i]]
Ruben Heinrich
committed
}
return(invisible(cleaned_list))
}
#' as_dir_path
#' @description Checks if a given path ends on \code{/}
#' @param path string: A path
assertthat::assert_that(assertthat::is.string(path))
path <- gsub("\\", "/", path, fixed = TRUE)
if(substring(path, nchar, nchar) != "/"){
path <- paste0(path, "/")
#' as_dir_path2
#' @description Removes leading \code{./} from a given path
#' @param file_path string: A path
#' @noRd
as_dir_path2 <- function(file_path){
assertthat::assert_that(assertthat::is.string(file_path))
if(substr(file_path,1,2) %>% stringr::str_detect("./")){
file_path <- sub("\\./", "", file_path)
}
return(invisible(file_path))
}
#' filter_invalid_xml
#' @description Filters invalid XML paths out of a vector
#' @param paths character: Vector of (maybe-)XML paths
#' @param encoding string: Optional: XML encoding. Defaults to ISO-8859-1
#' @param print_messages flag: Optional: Print error messages? Defaults to
#' \code{TRUE}
#' @return character: Vector of invalid XML paths
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
filter_invalid_xml <- function(paths,
encoding = "ISO-8859-1",
print_messages = TRUE){
invalid_paths <- character()
for(i in seq_len(length(paths))){
out <- tryCatch(
{
xml2::read_xml(paths[[i]],
encoding = encoding)
},
error = function(cond){
if(print_messages){
message(paste("\nxml2::read_xml() failed for",
paths[[i]], ". Original error message:"))
message(cond)
}
invalid_paths <<- c(invalid_paths, paths[[i]])
}
)
}
return(invalid_paths)
}
#===== Validation utility =====
#' are_numbers
#' @description Checks if objects are numbers
#' @param ... Ellipsis
lapply(list(...), function(x){
assertthat::assert_that(assertthat::is.number(x))
})
return(invisible(TRUE))
}
#' are_null_or_numbers
#' @description Checks if objects are either \code{NULL} or numbers
#' @param ... Ellipsis
are_null_or_numbers <- function(...){
lapply(list(...), function(x){
if(!is.null(x)){
assertthat::assert_that(assertthat::is.number(x))
}
})
#' are_numeric
#' @description Checks if objects are numeric
#' @param ... Ellipsis
lapply(list(...), function(x){
assertthat::assert_that(is.numeric(x))
#' are_null_or_numeric
#' @description Checks if objects are either \code{NULL} or numeric
#' @param ... Ellipsis
are_null_or_numeric <- function(...){
lapply(list(...), function(x){
if(!is.null(x)){
assertthat::assert_that(is.numeric(x))
}
})
#' are_strings
#' @description Checks if objects are strings
#' @param ... Ellipsis
lapply(list(...), function(x){
assertthat::assert_that(assertthat::is.string(x))
})
return(invisible(TRUE))
}
#' are_null_or_strings
#' @description Checks if objects are either \code{NULL} or strings
#' @param ... Ellipsis
are_null_or_strings <- function(...){
lapply(list(...), function(x){
if(!is.null(x)){
assertthat::assert_that(assertthat::is.string(x))
return(invisible(TRUE))
}
#' are_string_flags
#' @description Checks if objects are strings reading either "true" or "false"
#' @param ... Ellipsis
are_string_flags <- function(...){
lapply(list(...), function(x){
assertthat::assert_that(assertthat::is.string(x))
assertthat::assert_that(x %in% c("true", "false"))
})
return(invisible(TRUE))
Ruben Heinrich
committed
#' are_null_or_string_flags
#' @description Checks if objects are either \code{NULL} or strings reading
#' either "true" or "false"
#' @param ... Ellipsis
are_null_or_string_flags <- function(...){
lapply(list(...), function(x){
if(!is.null(x)){
are_string_flags(x)
return(invisible(TRUE))
}
#' is_wrapper_list
#' @description Checks if a list consists only of elements of class
#' \code{element_class}
#' @param list list: List to check
#' @param element_class string: Class each element of \code{list} should have
is_wrapper_list <- function(list, element_class) {
assertthat::assert_that(is.list(list))
lapply(list, function(x){
assertthat::assert_that(any(grepl(element_class, class(x), fixed = TRUE)))
})
return(invisible(TRUE))
#' is_null_or_wrapper_list
#' @description Checks if an object is either \code{NULL} or a list of elements
#' of class \code{element_class}
#' @param obj list | NULL: Object to check
#' @param element_class string: Class each element of \code{obj} should have
is_null_or_wrapper_list <- function(obj, element_class) {
Ruben Heinrich
committed
if(!is.null(obj)){
assertthat::assert_that(is.list(obj))
Ruben Heinrich
committed
lapply(obj, function(x){
assertthat::assert_that(any(grepl(element_class, class(x), fixed = TRUE)))
})
}
Ruben Heinrich
committed
Ruben Heinrich
committed
#' is_null_or_has_class
#' @description Checks if an object is either \code{NULL} or a class object of
#' class \code{class_name}
#' @param obj The object to check
#' @param class_name The name of the expected class
is_null_or_has_class <- function(obj, class_name){
Ruben Heinrich
committed
if(!is.null(obj)){
assertthat::assert_that(class(obj) == class_name)
Ruben Heinrich
committed
}
Ruben Heinrich
committed
}
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
#--- File utility ------------------------------------------------------------
#' make_abs_path
#' @description Creates an absolute file path based on a given file name or path
#' and a reference path. The reference path will be adjusted if the file path
#' is relative (e.g. \code{../foo/bar.baz}). A file with the created absolute
#' path should exist.
#' @param file_path string: Name or path to file.
#' @param ref_path string: Reference path whre file_path will be combined with.
#' Will be made absolute if relative path is given.
#' @noRd
make_abs_path <- function(file_path, ref_path, force=F){
assertthat::assert_that(assertthat::is.string(file_path))
assertthat::assert_that(assertthat::is.string(ref_path))
# make shure that ref_path is absolute and ends with "/"
ref_path <- normalizePath(ref_path, mustWork = T)
ref_path <- as_dir_path(ref_path)
file_path <- as_dir_path2(file_path)
# case1: if file_path is absolute
if((substr(file_path,1,1)=="/")| # abspath on unix
(substr(file_path,1,3) %>% stringr::str_detect("[:alpha:]:\\\\"))){ # windows?
message(paste("file_path", file_path, "is already asolute."))
if(isTRUE(force)){
file_path <- paste0(ref_path, basename(file_path))
message(paste0("Forced to convert to: ", ref_path, file_path))
}
}
# case2: if file_path consist of filename only
else if(basename(file_path)==file_path){
file_path <- paste0(ref_path,file_path)
}
# case3: if file_path is in parent dir(s) (contains "../")
else if(stringr::str_detect(file_path, "\\.\\./")){
cds <- stringr::str_count(file_path, "\\.\\./")
file_path <- gsub("\\.\\./", "", file_path)
# cd.. through ref_path
for(i in seq(cds)){
ref_path <- sub("\\w+/$", "", ref_path)
}
file_path <- paste0(ref_path,file_path)
}
# case4: file is in child dir
else {
file_path_norm <- normalizePath(dirname(file_path), mustWork = T)
assertthat::assert_that(
stringr::str_detect(file_path_norm, ref_path),
msg = paste(file_path, "is neither an absolute path nor a reference to",
"a file in", ref_path, "or in a child or parent directory."))
file_path <- paste0(ref_path,file_path)
}
assertthat::assert_that(file.exists(file_path))
return(file_path)
}