Mercurial > gemma
view pkg/imports/dmv.go @ 2104:c9af355d4a2c
staging: display stretch name
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Mon, 04 Feb 2019 14:35:47 +0100 |
parents | a7c4005b723f |
children | b868cb653c4d |
line wrap: on
line source
// This is Free Software under GNU Affero General Public License v >= 3.0 // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // // Copyright (C) 2018 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> package imports import ( "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 { // URL is the URL of the SOAP service. URL string `json:"url"` // Username is the username used to authenticate. Username string `json:"username"` // Passwort is the password to authenticate. Password string `json:"password"` // Insecure indicates if HTTPS traffic // should validate certificates or not. Insecure bool `json:"insecure"` } const DMVJobKind JobKind = "dmv" type dmvJobCreator struct{} func init() { RegisterJobCreator(DMVJobKind, dmvJobCreator{}) } func (dmvJobCreator) Description() string { return "distance marks virtual" } func (dmvJobCreator) AutoAccept() bool { return true } func (dmvJobCreator) Create(_ JobKind, data string) (Job, error) { dmv := new(DistanceMarksVirtual) if err := common.FromJSONString(data, dmv); err != nil { return nil, err } return dmv, nil } func (dmvJobCreator) Depends() []string { return []string{ "distance_marks_virtual", } } // StageDone does nothing as there is no staging for distance marks virtual. func (dmvJobCreator) StageDone(context.Context, *sql.Tx, int64) error { return nil } // 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, conn *sql.Conn, feedback Feedback, ) (interface{}, error) { 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 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 relenc: %s", code) ignored++ continue } if _, err := insertStmt.ExecContext( ctx, code.CountryCode, code.LoCode, code.FairwaySection, code.Orc, code.Hectometre, float64(*dr.Lon), float64(*dr.Lat), 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 distance marks (virtual) successfully took %s.", time.Since(start)) } else { feedback.Error("Refreshing distance marks (virtual) failed after %s.", time.Since(start)) } return nil, nil }