From d5bb909339ef206cf4d8029a331b169e619c09fc Mon Sep 17 00:00:00 2001
From: aheinri5 <Anna@netzkritzler.de>
Date: Mon, 18 Jan 2021 21:28:34 +0100
Subject: [PATCH] [base] Switched .gml class to R6

---
 R/gml.R | 348 ++++++++++++++++++++++++++++++++------------------------
 1 file changed, 201 insertions(+), 147 deletions(-)

diff --git a/R/gml.R b/R/gml.R
index 64914d8..732c4a2 100644
--- a/R/gml.R
+++ b/R/gml.R
@@ -1,106 +1,174 @@
 
-#===== r2ogs6_gml =====
+#===== OGS6_gml =====
 
 
-#'r2ogs6_gml
-#'@description S3 class describing the .gml file
-#'@param name The name of the geometry
-#'@param points A tibble of points
-#'@param polylines Optional: A list of polylines
-#'@param surfaces Optional: A list of surfaces
+#'OGS6_gml
+#'@description Constructor for the OGS6_gml base class
 #'@export
-r2ogs6_gml <- function(name,
-                       points,
-                       polylines = NULL,
-                       surfaces = NULL){
-
-    #Make this more user friendly
-    #...
-
-    validate_r2ogs6_gml(new_r2ogs6_gml(name,
-                                       points,
-                                       polylines,
-                                       surfaces))
-}
-
+OGS6_gml <- R6::R6Class(
+    "OGS6_gml",
+    public = list(
+
+        #'@description
+        #'Creates new OGS6_gml object
+        #'@param gml_path string: Optional: Path to .gml file
+        #'@param name string: Geometry name
+        #'@param points tibble: Must have 3 vectors named 'x', 'y' and 'z', may
+        #' have optional 'name' vector
+        #'@param polylines list(list("foo", c(1, 2))):
+        #'@param surfaces list(list("foo", c(1, 2, 3), c(2, 3, 4))):
+        initialize = function(gml_path = NULL,
+                              name = NULL,
+                              points = NULL,
+                              polylines = NULL,
+                              surfaces = NULL) {
+
+            if(is.null(gml_path)){
+                self$name <- name
+                self$points <- points
+                self$polylines <- polylines
+                self$surfaces <- surfaces
+            }else{
+                if(!is.null(name) ||
+                   !is.null(points) ||
+                   !is.null(polylines) ||
+                   !is.null(surfaces)){
+                    warning(paste("`gml_path` was specified for OGS6_gml",
+                                  "initialization, so all other parameters",
+                                  "will be ignored!"), call. = FALSE)
+                }
+
+                xml_doc <- validate_read_in_xml(gml_path)
+
+                self$name <- xml2::xml_text(xml2::xml_find_first(xml_doc,
+                                                                 "//name"))
+                self$points <- read_in_points(xml_doc)
+                self$polylines <- read_in_polylines(xml_doc)
+                self$surfaces <- read_in_surfaces(xml_doc)
+            }
 
-#'new_r2ogs6_gml
-#'@description Constructor for S3 class new_r2ogs6_gml
-#'@param name The name of the geometry
-#'@param points A tibble of points
-#'@param polylines Optional: A list of polylines
-#'@param surfaces Optional: A list of surfaces
-new_r2ogs6_gml <- function(name,
-                           points,
-                           polylines = NULL,
-                           surfaces = NULL) {
+            private$.gml_path <- gml_path
+            private$validate()
+        }
+    ),
+
+    active = list(
+
+        #'@field gml_path
+        #'Getter for private parameter '.gml_path'
+        gml_path = function(value) {
+            private$gml_path
+        },
+
+        #'@field name
+        #'Access to private parameter '.name'
+        name = function(value) {
+            if(missing(value)) {
+                private$.name
+            }else{
+                assertthat::assert_that(assertthat::is.string(value))
+                private$.name <- value
+            }
+        },
+
+        #'@field points
+        #'Access to private parameter '.points'
+        points = function(value) {
+            if(missing(value)) {
+                private$.points
+            }else{
+                private$.points <- validate_points(value)
+            }
+        },
+
+        #'@field polylines
+        #'Access to private parameter '.polylines'
+        polylines = function(value) {
+            if(missing(value)) {
+                private$.polylines
+            }else{
+                if(!is.null(value)){
+                    value <- validate_polylines(value)
+                }
+
+                private$.polylines <- value
+            }
+        },
+
+        #'@field surfaces
+        #'Access to private parameter '.surfaces'
+        surfaces = function(value) {
+            if(missing(value)) {
+                private$.surfaces
+            }else{
+                if(!is.null(value)){
+                    value <- validate_surfaces(value)
+                }
+                private$.surfaces <- value
+            }
+        },
+
+        #'@field is_subclass
+        #'Getter for private parameter '.is_subclass'
+        is_subclass = function(value) {
+            private$.is_subclass
+        },
+
+        #'@field attr_names
+        #'Getter for private parameter '.attr_names'
+        attr_names = function(value) {
+            private$.attr_names
+        },
+
+        #'@field flatten_on_exp
+        #'Getter for private parameter '.flatten_on_exp'
+        flatten_on_exp = function(value) {
+            private$.flatten_on_exp
+        }
+    ),
 
-    assertthat::assert_that(assertthat::is.string(name))
+    private = list(
 
-    points <- validate_points(points)
+        validate = function(){
+            maximal_point_id <- length(self$points[[1]]) - 1
 
-    if(!is.null(polylines)){
-        polylines <- validate_polylines(polylines)
-    }
+            check_pnt <- function(pnt){
+                if(pnt > maximal_point_id ||
+                   pnt < 0){
+                    stop(paste("Point with ID", pnt, "does not exist"),
+                         call. = FALSE)
+                }
+            }
 
-    if(!is.null(surfaces)){
-        surfaces <- validate_surfaces(surfaces)
-    }
-
-    structure(
-        list(name = name,
-             points = points,
-             polylines = polylines,
-             surfaces = surfaces,
-             is_subclass = TRUE,
-             attr_names = c("point", "name", "id", "element"),
-             flatten_on_exp = character()
-             ),
-
-        class = "r2ogs6_gml")
-}
+            #Check if polylines reference existing points
+            lapply(self$polylines, function(x){
+                lapply(x[[2]], check_pnt)
+            })
+
+            #Check if surfaces reference existing points
+            lapply(self$surfaces, function(x){
+                lapply(x[[2]], check_pnt)
+                if(length(x) == 3){
+                    lapply(x[[3]], check_pnt)
+                }
+            })
+        },
+
+        .gml_path = NULL,
+        .name = NULL,
+        .points = NULL,
+        .polylines = NULL,
+        .surfaces = NULL,
+        .is_subclass = TRUE,
+        .attr_names = c("point", "name", "id", "element"),
+        .flatten_on_exp = character()
+    )
+)
 
 
 #===== Validation utility =====
 
 
-#'validate_r2ogs6_gml
-#'@description Validator for class r2ogs6_gml. Checks if the defined polylines
-#' and surfaces reference existing points.
-#'@param r2ogs6_gml r2ogs6_gml:
-validate_r2ogs6_gml <- function(r2ogs6_gml) {
-
-    maximal_point_id <- length(r2ogs6_gml$points[[1]]) - 1
-
-    #Check if polylines reference existing points
-    for(i in seq_len(length(r2ogs6_gml$polylines))){
-        for(j in seq_len(length(r2ogs6_gml$polylines[[i]][[2]]))){
-            if(r2ogs6_gml$polylines[[i]][[2]][[j]] > maximal_point_id ||
-               r2ogs6_gml$polylines[[i]][[2]][[j]] < 0){
-                stop("Polyline references point ID which does not exist",
-                     call. = FALSE)
-            }
-        }
-    }
-
-    #Check if surfaces reference existing points
-    for(i in seq_len(length(r2ogs6_gml$surfaces))){
-        for(j in seq_len(length(r2ogs6_gml$surfaces[[i]][[2]]))){
-            if(r2ogs6_gml$surfaces[[i]][[2]][[j]] > maximal_point_id ||
-               r2ogs6_gml$surfaces[[i]][[2]][[j]] < 0 ||
-               (length(r2ogs6_gml$surfaces[[i]]) == 3 &&
-                (r2ogs6_gml$surfaces[[i]][[3]][[j]] > maximal_point_id ||
-                 r2ogs6_gml$surfaces[[i]][[3]][[j]] < 0))){
-                stop("Surface references point ID which does not exist",
-                     call. = FALSE)
-            }
-        }
-    }
-
-    return(invisible(r2ogs6_gml))
-}
-
-
 #'validate_points
 #'@description Checks if the input is a tibble, if this tibble has the right
 #' number of elements, if those elements are named correctly and if there are
@@ -159,21 +227,17 @@ validate_polylines <- function(polylines) {
 
     assertthat::assert_that(is.list(polylines))
 
-    for(i in seq_len(length(polylines))){
-
-        assertthat::assert_that(is.list(polylines[[i]]))
-        assertthat::assert_that(length(polylines[[i]]) == 2)
-        assertthat::assert_that(assertthat::is.string(polylines[[i]][[1]]))
-        assertthat::assert_that(is.numeric(polylines[[i]][[2]]))
-        names(polylines[[i]])[[1]] <- c("name")
-        names(polylines[[i]][[2]]) <- rep("pnt",
-                                          length(names(polylines[[i]][[2]])))
-
-        #Check for duplicate points / polylines?
-    }
+    polylines <- lapply(polylines, function(x){
+        assertthat::assert_that(is.list(x))
+        assertthat::assert_that(length(x) == 2)
+        assertthat::assert_that(assertthat::is.string(x[[1]]))
+        assertthat::assert_that(is.numeric(x[[2]]))
+        names(x)[[1]] <- c("name")
+        names(x[[2]]) <- rep("pnt", length(names(x[[2]])))
+        return(x)
+    })
 
     names(polylines) <- rep("polyline", length(polylines))
-
     return(invisible(polylines))
 }
 
@@ -188,38 +252,29 @@ validate_surfaces <- function(surfaces) {
 
     assertthat::assert_that(is.list(surfaces))
 
-    for(i in seq_len(length(surfaces))){
-
-        assertthat::assert_that(is.list(surfaces[[i]]))
-
-        assertthat::assert_that(length(surfaces[[i]]) == 2 ||
-                                length(surfaces[[i]]) == 3)
-
-        validate_surface <- function(surface){
+    validate_element <- function(element){
+        assertthat::assert_that(is.numeric(element))
+        assertthat::assert_that(length(element) == 3)
+        names(element) <- c("p1", "p2", "p3")
+        return(invisible(element))
+    }
 
-            names(surface)[[1]] <- c("name")
-            assertthat::assert_that(is.numeric(surface[[2]]))
-            assertthat::assert_that(length(surface[[2]]) == 3)
-            names(surface)[[2]] <- c("element")
-            names(surface[[2]]) <- c("p1", "p2", "p3")
+    surfaces <- lapply(surfaces, function(x){
 
-            if(length(surface) == 3){
-                assertthat::assert_that(is.numeric(surface[[3]]))
-                assertthat::assert_that(length(surface[[3]]) == 3)
-                names(surface)[[3]] <- c("element")
-                names(surface[[3]]) <- c("p1", "p2", "p3")
+        assertthat::assert_that(is.list(x))
+        assertthat::assert_that(length(x) == 2 ||
+                                    length(x) == 3)
 
-                validate_surface_elements(surface[[2]],
-                                          surface[[3]])
-            }
+        names(x) <- c("name", rep("element", (length(x)-1)))
+        x[[2]] <- validate_element(x[[2]])
 
-            return(invisible(surface))
+        if(length(x) == 3){
+            x[[3]] <- validate_element(x[[3]])
+            # validate_pnt_values(x[[2]], x[[3]])
         }
 
-        surfaces[[i]] <- validate_surface(surfaces[[i]])
-
-        #Check for duplicate points / surfaces?
-    }
+        return(x)
+    })
 
     names(surfaces) <- rep("surface", length(surfaces))
 
@@ -227,31 +282,30 @@ validate_surfaces <- function(surfaces) {
 }
 
 
-#'validate_surface_elements
-#'@description Helper function, checks if two numerical vectors of length 3
-#' (two surface elements) each consist of 3 different elements and also have
-#' exactly 2 matching elements between them which means they describe a valid
-#' surface. You can think of the two vectors as two triangles, and the two
-#' triangles together form a square which is our surface.
-#'@param surface_element_1 numeric, length = 3
-#'@param surface_element_2 numeric, length = 3
-validate_surface_elements = function (surface_element_1, surface_element_2) {
-
-    if(surface_element_1[[1]] == surface_element_1[[2]] ||
-       surface_element_1[[1]] == surface_element_1[[3]] ||
-       surface_element_1[[2]] == surface_element_1[[3]] ||
-       surface_element_2[[1]] == surface_element_2[[2]] ||
-       surface_element_2[[1]] == surface_element_2[[3]] ||
-       surface_element_2[[2]] == surface_element_2[[3]]) {
+#'validate_pnt_values
+#'@description Checks if two numerical vectors of length 3
+#' (two surface elements) each consist of 3 different elements and have
+#' exactly 2 matching elements between them. Think of the two vectors as
+#' triangles, and the triangles together form a square which is our surface.
+#'@param element_1 numeric, length = 3
+#'@param element_2 numeric, length = 3
+validate_pnt_values = function (element_1, element_2) {
+
+    if(element_1[[1]] == element_1[[2]] ||
+       element_1[[1]] == element_1[[3]] ||
+       element_1[[2]] == element_1[[3]] ||
+       element_2[[1]] == element_2[[2]] ||
+       element_2[[1]] == element_2[[3]] ||
+       element_2[[2]] == element_2[[3]]) {
         stop("A surface element must consist of 3 different points",
              call. = FALSE)
     }
 
     equal_count <- 0
 
-    for(i in 1:length(surface_element_1)) {
-        for(j in 1:length(surface_element_2)) {
-            if(surface_element_1[[i]] == surface_element_2[[j]]) {
+    for(i in 1:length(element_1)) {
+        for(j in 1:length(element_2)) {
+            if(element_1[[i]] == element_2[[j]]) {
                 equal_count <- equal_count + 1
                 break
             }
-- 
GitLab