comparison pkg/imports/stsh.go @ 4332:8080007d3c06

shape upload stretch import: Finished implementation (staging, summary).
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 05 Sep 2019 10:32:45 +0200
parents 3d6a2c6b436c
children eca3afe766d7 5e38667f740c
comparison
equal deleted inserted replaced
4331:98497ac4af3c 4332:8080007d3c06
17 "archive/zip" 17 "archive/zip"
18 "context" 18 "context"
19 "database/sql" 19 "database/sql"
20 "errors" 20 "errors"
21 "fmt" 21 "fmt"
22 "log"
23 "os" 22 "os"
24 "path" 23 "path"
25 "path/filepath" 24 "path/filepath"
26 "strings" 25 "strings"
27 "time" 26 "time"
28 27
29 shp "github.com/jonas-p/go-shp" 28 shp "github.com/jonas-p/go-shp"
30 29
31 "gemma.intevation.de/gemma/pkg/common" 30 "gemma.intevation.de/gemma/pkg/common"
31 "gemma.intevation.de/gemma/pkg/models"
32 ) 32 )
33 33
34 type StretchShape struct { 34 type StretchShape struct {
35 Dir string `json:"dir"` 35 Dir string `json:"dir"`
36 } 36 }
73 $7, 73 $7,
74 $8) 74 $8)
75 RETURNING id` 75 RETURNING id`
76 ) 76 )
77 77
78 // StageDone is merely the same as for the normal stretch import.
78 func (stshJobCreator) StageDone( 79 func (stshJobCreator) StageDone(
79 ctx context.Context, 80 ctx context.Context,
80 tx *sql.Tx, 81 tx *sql.Tx,
81 id int64, 82 id int64,
82 ) error { 83 ) error {
83 // TODO: Implement me! 84 return stJobCreator{}.StageDone(ctx, tx, id)
84 return nil
85 } 85 }
86 86
87 func (stsh *StretchShape) CleanUp() error { 87 func (stsh *StretchShape) CleanUp() error {
88 return os.RemoveAll(stsh.Dir) 88 return os.RemoveAll(stsh.Dir)
89 } 89 }
90 90
91 func fixAttribute(s string) string { 91 func fixAttribute(s string) string {
92 return strings.TrimRight(s, "\x00") 92 return strings.TrimRight(s, "\x00")
93 }
94
95 type stretchSummary struct {
96 ID int64 `json:"id"`
97 Name string `json:"name"`
98 From string `json:"from"`
99 To string `json:"to"`
100 ObjNam string `json:"objnam"`
101 NObjNam *string `json:"nobjnam"`
102 Date models.Date `json:"date-info"`
103 Countries models.UniqueCountries `json:"countries"`
104 }
105
106 func parseUniqueCountries(s string) (models.UniqueCountries, error) {
107 unique := map[models.Country]struct{}{}
108 var countries models.UniqueCountries
109 for _, c := range strings.Split(s, ",") {
110 if c = strings.ToUpper(strings.TrimSpace(c)); c == "" {
111 continue
112 }
113 n := models.Country(c)
114 if !n.Valid() {
115 return nil, fmt.Errorf("'%s' is not a valid country code", c)
116 }
117 if _, found := unique[n]; found {
118 return nil, fmt.Errorf("'%s' is not a unique country code", c)
119 }
120 countries = append(countries, n)
121 unique[n] = struct{}{}
122 }
123 return countries, nil
93 } 124 }
94 125
95 func (stsh *StretchShape) Do( 126 func (stsh *StretchShape) Do(
96 ctx context.Context, 127 ctx context.Context,
97 importID int64, 128 importID int64,
211 if err != nil { 242 if err != nil {
212 return nil, err 243 return nil, err
213 } 244 }
214 defer insCountryStmt.Close() 245 defer insCountryStmt.Close()
215 246
247 trackStmt, err := tx.PrepareContext(ctx, trackImportSQL)
248 if err != nil {
249 return nil, err
250 }
251 defer trackStmt.Close()
252
253 var stretches []*stretchSummary
254
216 for sr.Next() { 255 for sr.Next() {
217 256
218 _, p := sr.Shape() 257 _, p := sr.Shape()
219 if p == nil { 258 if p == nil {
220 feedback.Warn("Invalid NULL geometry found.") 259 feedback.Warn("Invalid NULL geometry found.")
225 feedback.Warn("Invalid geometry found: %v.", err) 264 feedback.Warn("Invalid geometry found: %v.", err)
226 continue 265 continue
227 } 266 }
228 267
229 var ( 268 var (
230 name = fixAttribute(sr.Attribute(nameIdx)) 269 name = fixAttribute(sr.Attribute(nameIdx))
231 objnam = fixAttribute(sr.Attribute(objnamIdx)) 270 objnam = fixAttribute(sr.Attribute(objnamIdx))
232 nobjnam = fixAttribute(sr.Attribute(nobjnamIdx)) 271 nobjnam = fixAttribute(sr.Attribute(nobjnamIdx))
233 lower = fixAttribute(sr.Attribute(lowerIdx)) 272 lower = fixAttribute(sr.Attribute(lowerIdx))
234 upper = fixAttribute(sr.Attribute(upperIdx)) 273 upper = fixAttribute(sr.Attribute(upperIdx))
235 dateInfo = fixAttribute(sr.Attribute(dateInfoIdx)) 274 dateInfo = fixAttribute(sr.Attribute(dateInfoIdx))
236 source = fixAttribute(sr.Attribute(sourceIdx)) 275 source = fixAttribute(sr.Attribute(sourceIdx))
237 countries = fixAttribute(sr.Attribute(countriesIdx)) 276 cnts = fixAttribute(sr.Attribute(countriesIdx))
238 ) 277 )
239 278
240 log.Printf("name : %+q\n", name) 279 feedback.Info("Importing stretch %s (%s - %s).",
241 log.Printf("objnam : %+q\n", objnam) 280 name, lower, upper)
242 log.Printf("nobjnam : %+q\n", nobjnam)
243 log.Printf("lower : %+q\n", lower)
244 log.Printf("upper : %+q\n", upper)
245 log.Printf("dateinfo : %+q\n", dateInfo)
246 log.Printf("source : %+q\n", source)
247 log.Printf("countries: %+q\n", countries)
248 281
249 date, err := common.ParseTime(dateInfo) 282 date, err := common.ParseTime(dateInfo)
250 if err != nil { 283 if err != nil {
251 feedback.Warn("Invalid time value: %v.", err) 284 feedback.Warn("Invalid time value: %v.", err)
285 continue
286 }
287
288 countries, err := parseUniqueCountries(cnts)
289 if err != nil {
290 feedback.Warn("Countries: %v.", err)
252 continue 291 continue
253 } 292 }
254 293
255 var nobjnamNull sql.NullString 294 var nobjnamNull sql.NullString
256 if nobjnam != "" { 295 if nobjnam != "" {
260 } 299 }
261 } 300 }
262 301
263 // Convert to a multi polygon. 302 // Convert to a multi polygon.
264 area := poly.MultiPolygonGeom().AsWKB() 303 area := poly.MultiPolygonGeom().AsWKB()
265
266 log.Printf("len geom: %d\n", len(area))
267 304
268 var id int64 305 var id int64
269 306
270 if err := insStmt.QueryRowContext( 307 if err := insStmt.QueryRowContext(
271 ctx, 308 ctx,
278 source, 315 source,
279 ).Scan(&id); err != nil { 316 ).Scan(&id); err != nil {
280 return nil, err 317 return nil, err
281 } 318 }
282 319
283 log.Println("after insert") 320 // Store the countries
284 321 for _, country := range countries {
285 for _, country := range strings.Split(countries, ",") {
286 if country = strings.TrimSpace(country); country == "" {
287 continue
288 }
289 if _, err := insCountryStmt.ExecContext(ctx, country); err != nil { 322 if _, err := insCountryStmt.ExecContext(ctx, country); err != nil {
290 return nil, err 323 return nil, err
291 } 324 }
292 } 325 }
293 326
294 // TODO: Implement me! 327 // Finally track the stretch
328
329 if _, err := trackStmt.ExecContext(
330 ctx,
331 importID,
332 "waterway.stretches",
333 id,
334 ); err != nil {
335 return nil, err
336 }
337
338 stretch := &stretchSummary{
339 ID: id,
340 Name: name,
341 From: lower,
342 To: upper,
343 ObjNam: objnam,
344 Date: models.Date{date},
345 Countries: countries,
346 }
347
348 if nobjnamNull.Valid {
349 stretch.NObjNam = &nobjnamNull.String
350 }
351
352 stretches = append(stretches, stretch)
295 } 353 }
296 354
297 if err := sr.Err(); err != nil { 355 if err := sr.Err(); err != nil {
298 return nil, err 356 return nil, err
299 } 357 }
300 358
301 return nil, errors.New("Not implemented, yet!") 359 if len(stretches) == 0 {
302 } 360 return nil, UnchangedError("No stretches written.")
361 }
362
363 if err := tx.Commit(); err != nil {
364 return nil, err
365 }
366
367 return stretches, nil
368 }