diff pkg/imports/dmv.go @ 1859:9780cb4ef6a6

Distance marks virtual import: Implemented.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 17 Jan 2019 13:12:37 +0100
parents bbd653a43a6a
children 2fda3f17e47c
line wrap: on
line diff
--- a/pkg/imports/dmv.go	Thu Jan 17 12:42:19 2019 +0100
+++ b/pkg/imports/dmv.go	Thu Jan 17 13:12:37 2019 +0100
@@ -17,8 +17,15 @@
 	"context"
 	"database/sql"
 	"errors"
+	"fmt"
+	"log"
+	"strings"
+	"time"
 
 	"gemma.intevation.de/gemma/pkg/common"
+	"gemma.intevation.de/gemma/pkg/models"
+	"gemma.intevation.de/gemma/pkg/soap"
+	"gemma.intevation.de/gemma/pkg/soap/erdms"
 )
 
 type DistanceMarksVirtual struct {
@@ -65,6 +72,27 @@
 // CleanUp does nothing as there is nothing to cleanup with distance marks virtual.
 func (*DistanceMarksVirtual) CleanUp() error { return nil }
 
+const (
+	deleteDistanceMarksVirtualSQL = `
+DELETE FROM waterway.distance_marks_virtual
+WHERE (location_code).country_code = $1
+`
+	insertDistanceMarksVirtualSQL = `
+INSERT INTO waterway.distance_marks_virtual (
+  location_code,
+  geom,
+  related_enc
+)
+VALUES (
+  ($1::char(2), $2::char(3), $3::char(5), $4::char(5), $5::int),
+  ST_SetSRID(ST_MakePoint($6, $7), 4326)::geography,
+  $8
+) ON CONFLICT (location_code) DO UPDATE SET
+  geom = ST_SetSRID(ST_MakePoint($6, $7), 4326)::geography,
+  related_enc = $8
+`
+)
+
 func (dmv *DistanceMarksVirtual) Do(
 	ctx context.Context,
 	importID int64,
@@ -72,7 +100,115 @@
 	feedback Feedback,
 ) (interface{}, error) {
 
-	// TODO: Implement me!
+	start := time.Now()
+
+	tx, err := conn.BeginTx(ctx, nil)
+	if err != nil {
+		return nil, err
+	}
+	defer tx.Rollback()
+
+	var country string
+	err = tx.QueryRowContext(ctx, selectCurrentUserCountrySQL).Scan(&country)
+	switch {
+	case err == sql.ErrNoRows:
+		return nil, errors.New("Cannot figure out user country")
+	case err != nil:
+		return nil, err
+	}
+
+	country = strings.ToUpper(country)
+	feedback.Info("Using country '%s'.", country)
+
+	var auth *soap.BasicAuth
+	if dmv.Username != "" {
+		auth = &soap.BasicAuth{
+			Login:    dmv.Username,
+			Password: dmv.Password,
+		}
+	}
+
+	client := erdms.NewRefService(dmv.URL, dmv.Insecure, auth)
+
+	request := &erdms.GetRisDataXML{
+		GetRisDataXMLType: &erdms.GetRisDataXMLType{
+			Subcode: erdms.NoNS{Text: country + "%"},
+			Funcode: erdms.NoNS{Text: "DISMAR"},
+		},
+	}
+
+	data, err := client.GetRisDataXML(request)
+
+	if err != nil {
+		log.Printf("error: %v\n", err)
+		return nil, fmt.Errorf("Error requesting ERDMS service: %v", err)
+	}
+
+	if _, err := tx.ExecContext(ctx, deleteDistanceMarksVirtualSQL, country); err != nil {
+		return nil, err
+	}
+
+	insertStmt, err := tx.PrepareContext(ctx, insertDistanceMarksVirtualSQL)
+	if err != nil {
+		return nil, err
+	}
+	defer insertStmt.Close()
+
+	var ignored, features int
 
-	return nil, errors.New("Not implemented, yet!")
+	for _, dr := range data.RisdataReturn {
+		if dr.RisidxCode == nil {
+			ignored++
+			continue
+		}
+
+		code, err := models.IsrsFromString(string(*dr.RisidxCode))
+		if err != nil {
+			feedback.Warn("invalid ISRS code %v", err)
+			ignored++
+			continue
+		}
+
+		if dr.Lat == nil || dr.Lon == nil {
+			feedback.Warn("missing lat/lon: %s", code)
+			ignored++
+			continue
+		}
+
+		if dr.Relenc == nil {
+			feedback.Warn("missing relnec: %s", code)
+			ignored++
+			continue
+		}
+
+		if _, err := insertStmt.ExecContext(
+			ctx,
+			code.CountryCode,
+			code.LoCode,
+			code.FairwaySection,
+			code.Orc,
+			code.Hectometre,
+			float64(*dr.Lat), float64(*dr.Lon),
+			string(*dr.Relenc),
+		); err != nil {
+			return nil, err
+		}
+		features++
+	}
+	feedback.Info("ignored: %d", ignored)
+	feedback.Info("features: %d", features)
+
+	if features == 0 {
+		return nil, errors.New("No features found")
+	}
+
+	if err = tx.Commit(); err == nil {
+		feedback.Info("Refreshing distant marks virtual successfully took %s.",
+			time.Since(start))
+	} else {
+		feedback.Error("Refreshing distant marks virtual failed after %s.",
+			time.Since(start))
+	}
+
+	return nil, nil
 }