comparison pkg/imports/wx.go @ 1785:614c6c766691

Waterway area import: Implemented.
author Sascha L. Teichmann <teichmann@intevation.de>
date Sat, 12 Jan 2019 19:53:31 +0100
parents bb4348ac52ab
children 1333f96f18d0
comparison
equal deleted inserted replaced
1784:724758455a4e 1785:614c6c766691
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de> 12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de>
13 13
14 package imports 14 package imports
15 15
16 import ( 16 import (
17 "bytes"
18 "context" 17 "context"
19 "database/sql" 18 "database/sql"
20 "encoding/binary"
21 "encoding/json" 19 "encoding/json"
22 "errors" 20 "errors"
23 "fmt" 21 "fmt"
24 "io" 22 "io"
25 "math"
26 "strings"
27 "time" 23 "time"
28 24
29 "gemma.intevation.de/gemma/pkg/common" 25 "gemma.intevation.de/gemma/pkg/common"
30 "gemma.intevation.de/gemma/pkg/wfs" 26 "gemma.intevation.de/gemma/pkg/wfs"
31 ) 27 )
73 // StageDone is a NOP for waterway axis imports. 69 // StageDone is a NOP for waterway axis imports.
74 func (wxJobCreator) StageDone(context.Context, *sql.Tx, int64) error { 70 func (wxJobCreator) StageDone(context.Context, *sql.Tx, int64) error {
75 return nil 71 return nil
76 } 72 }
77 73
78 // CleanUp for waterway imports is a NOP. 74 // CleanUp for waterway axis imports is a NOP.
79 func (*WaterwayAxis) CleanUp() error { return nil } 75 func (*WaterwayAxis) CleanUp() error { return nil }
80 76
81 type waterwayAxisProperties struct { 77 type waterwayAxisProperties struct {
82 ObjNam string `json:"hydro_objnam"` 78 ObjNam string `json:"hydro_objnam"`
83 NObjNnm *string `json:"hydro_nobjnm"` 79 NObjNnm *string `json:"hydro_nobjnm"`
84 }
85
86 type line [][]float64
87
88 const wkbLineString uint32 = 2
89
90 func (l line) asWKB() []byte {
91
92 size := 1 + 4 + 4 + len(l)*(2*8)
93
94 buf := bytes.NewBuffer(make([]byte, 0, size))
95
96 binary.Write(buf, binary.LittleEndian, wkbNDR)
97 binary.Write(buf, binary.LittleEndian, wkbLineString)
98 binary.Write(buf, binary.LittleEndian, uint32(len(l)))
99
100 for _, c := range l {
101 var lat, lon float64
102 if len(c) > 0 {
103 lat = c[0]
104 }
105 if len(c) > 1 {
106 lon = c[1]
107 }
108 binary.Write(buf, binary.LittleEndian, math.Float64bits(lat))
109 binary.Write(buf, binary.LittleEndian, math.Float64bits(lon))
110 }
111
112 return buf.Bytes()
113 } 80 }
114 81
115 const ( 82 const (
116 deleteWaterwayAxisSQL = `DELETE FROM waterway.waterway_axis` 83 deleteWaterwayAxisSQL = `DELETE FROM waterway.waterway_axis`
117 insertWaterwayAxisSQL = ` 84 insertWaterwayAxisSQL = `
121 $3, 88 $3,
122 $4 89 $4
123 )` 90 )`
124 ) 91 )
125 92
126 // Do executes the actual waterway exis import. 93 // Do executes the actual waterway axis import.
127 func (wx *WaterwayAxis) Do( 94 func (wx *WaterwayAxis) Do(
128 ctx context.Context, 95 ctx context.Context,
129 importID int64, 96 importID int64,
130 conn *sql.Conn, 97 conn *sql.Conn,
131 feedback Feedback, 98 feedback Feedback,
182 if _, err := tx.ExecContext(ctx, deleteWaterwayAxisSQL); err != nil { 149 if _, err := tx.ExecContext(ctx, deleteWaterwayAxisSQL); err != nil {
183 return nil, err 150 return nil, err
184 } 151 }
185 152
186 var ( 153 var (
187 unsupportedTypes = map[string]int{} 154 unsupported = stringCounter{}
188 missingProperties int 155 missingProperties int
189 badProperties int 156 badProperties int
190 features int 157 features int
191 ) 158 )
192 159
228 nobjnam = sql.NullString{String: *props.NObjNnm, Valid: true} 195 nobjnam = sql.NullString{String: *props.NObjNnm, Valid: true}
229 } 196 }
230 197
231 switch feature.Geometry.Type { 198 switch feature.Geometry.Type {
232 case "LineString": 199 case "LineString":
233 var l line 200 var l lineSlice
234 if err := json.Unmarshal(*feature.Geometry.Coordinates, &l); err != nil { 201 if err := json.Unmarshal(*feature.Geometry.Coordinates, &l); err != nil {
235 return err 202 return err
236 } 203 }
237 if _, err := insertStmt.ExecContext( 204 if _, err := insertStmt.ExecContext(
238 ctx, 205 ctx,
243 ); err != nil { 210 ); err != nil {
244 return err 211 return err
245 } 212 }
246 features++ 213 features++
247 case "MultiLineString": 214 case "MultiLineString":
248 var ls []line 215 var ls []lineSlice
249 if err := json.Unmarshal(*feature.Geometry.Coordinates, &ls); err != nil { 216 if err := json.Unmarshal(*feature.Geometry.Coordinates, &ls); err != nil {
250 return err 217 return err
251 } 218 }
252 for _, l := range ls { 219 for _, l := range ls {
253 if _, err := insertStmt.ExecContext( 220 if _, err := insertStmt.ExecContext(
260 return err 227 return err
261 } 228 }
262 features++ 229 features++
263 } 230 }
264 default: 231 default:
265 unsupportedTypes[feature.Geometry.Type]++ 232 unsupported[feature.Geometry.Type]++
266 } 233 }
267 } 234 }
268 return nil 235 return nil
269 }); err != nil { 236 }); err != nil {
270 feedback.Error("Downloading features failed: %v", err) 237 feedback.Error("Downloading features failed: %v", err)
283 250
284 if missingProperties > 0 { 251 if missingProperties > 0 {
285 feedback.Warn("Missing properties: %d", missingProperties) 252 feedback.Warn("Missing properties: %d", missingProperties)
286 } 253 }
287 254
288 if len(unsupportedTypes) != 0 { 255 if len(unsupported) != 0 {
289 var b strings.Builder 256 feedback.Warn("Unsupported types found: %s", unsupported)
290 for t, c := range unsupportedTypes {
291 if b.Len() > 0 {
292 b.WriteString(", ")
293 }
294 b.WriteString(fmt.Sprintf("%s: %d", t, c))
295 }
296 feedback.Warn("Unsupported types found: %s", b.String())
297 } 257 }
298 258
299 if err = tx.Commit(); err == nil { 259 if err = tx.Commit(); err == nil {
300 feedback.Info("Storing %d features took %s", 260 feedback.Info("Storing %d features took %s",
301 features, time.Since(start)) 261 features, time.Since(start))