-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathWFSFeatureTypeElement.R
148 lines (136 loc) · 5.1 KB
/
WFSFeatureTypeElement.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#' WFSFeatureTypeElement
#'
#' @docType class
#' @export
#' @keywords OGC WFS FeatureType
#' @return Object of \code{\link[R6]{R6Class}} modelling a WFS feature type element
#' @format \code{\link[R6]{R6Class}} object.
#'
#' @note Abstract class used by \pkg{ows4R}
#'
#' @author Emmanuel Blondel <emmanuel.blondel1@@gmail.com>
#'
WFSFeatureTypeElement <- R6Class("WFSFeatureTypeElement",
inherit = OGCAbstractObject,
private = list(
#fetchElement
fetchElement = function(xmlObj, namespaces){
#minOccurs
elementMinOccurs <- xmlGetAttr(xmlObj, "minOccurs")
#maxOccurs
elementMaxOccurs <- xmlGetAttr(xmlObj, "maxOccurs")
#nillable
elementNillable <- ifelse(xmlGetAttr(xmlObj, "nillable") == "true", TRUE, FALSE)
#name
elementName <- xmlGetAttr(xmlObj, "name")
#type
elementType <- "character"
type <- xmlGetAttr(xmlObj, "type")
#geometry
geometry <- FALSE
if(length(type)==0){
#try a basic parsing for types in type restriction
#TODO study further WFS Schema (through GML geometa?) to propose generic solution
type <- try(xpathSApply(xmlDoc(xmlObj), "//xs:restriction",
namespaces = c(xs = "http://www.w3.org/2001/XMLSchema"),
xmlGetAttr, "base"))
if(is(type,"try-error")) type <- NULL
}
if(is.null(type)){
stop(sprintf("Unknown data type for type '%s' while parsing FeatureType description!", type))
}
gml_xmlns = namespaces[regexpr("gml", namespaces$uri)>0,] #may include app-schema GML secondary namespace
if(length(type)>0){
if(any(startsWith(type, gml_xmlns$id))){
gml_xmlns = gml_xmlns[startsWith(type, gml_xmlns$id),]
elementType <- unlist(strsplit(unlist(strsplit(type, paste0(gml_xmlns$id,":")))[2], "PropertyType"))[1]
geometry <- TRUE
}else{
baseType <- tolower(type)
#detect namespace xs/xsd (normal behavior)
#primitive types that are not prefixed with xsd (http://www.w3.org/2001/XMLSchema) schema are not handled well
#ows4R is permissive and controls it, although it is an issue of XML compliance on service providers side
if(regexpr(":", baseType)>0) baseType <- unlist(strsplit(baseType,":"))[2]
elementType <- switch(baseType,
"string" = "character",
"long" = "numeric",
"int" = "integer",
"short" = "integer",
"decimal" = "double",
"double" = "double",
"float" = "double",
"boolean" = "logical",
"date" = "Date",
"datetime" = "POSIXct",
NULL
)
}
}
element <- list(
minOccurs = elementMinOccurs,
maxOccurs = elementMaxOccurs,
nillable = elementNillable,
name = elementName,
type = elementType,
geometry = geometry
)
return(element)
}
),
public = list(
#'@field minOccurs minOccurs
minOccurs = NA,
#'@field maxOccurs maxOccurs
maxOccurs = NA,
#'@field nillable nillable
nillable = NA,
#'@field name name
name = NA,
#'@field type type
type = NA,
#'@field geometry geometry
geometry = FALSE,
#'@description Initializes a \link{WFSFeatureTypeElement}
#'@param xmlObj object of class \link[XML]{XMLInternalNode-class} from \pkg{XML}
#'@param namespaces namespaces definitions inherited from parent XML, as \code{data.frame}
initialize = function(xmlObj, namespaces){
element = private$fetchElement(xmlObj, namespaces)
self$minOccurs = element$minOccurs
self$maxOccurs = element$maxOccurs
self$nillable = element$nillable
self$name = element$name
self$type = element$type
self$geometry = element$geometry
},
#'@description get min occurs
#'@return an object of class \code{character}
getMinOccurs = function(){
return(self$minOccurs)
},
#'@description get max occurs
#'@return an object of class \code{character}
getMaxOccurs = function(){
return(self$maxOccurs)
},
#'@description get if nillable
#'@return an object of class \code{logical}
isNillable = function(){
return(self$nillable)
},
#'@description get name
#'@return an object of class \code{character}
getName = function(){
return(self$name)
},
#'@description get type
#'@return an object of class \code{character}
getType = function(){
return(self$type)
},
#'@description Is geometry
#'@param return object of class \code{logical}
isGeometry = function(){
return(self$geometry)
}
)
)