view pkg/imports/fm_notmrk.go @ 4945:97533bbfaa2d fairway-marks-import

Add missing fairway mark types to layer group
author Tom Gottfried <tom@intevation.de>
date Tue, 18 Feb 2020 13:00:25 +0100
parents df6c8a485979
children
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) 2020 by via donau
//   – Österreichische Wasserstraßen-Gesellschaft mbH
// Software engineering by Intevation GmbH
//
// Author(s):
//  * Tom Gottfried <tom.gottfried@intevation.de>

package imports

import (
	"context"
	"database/sql"
	"strings"

	"gemma.intevation.de/gemma/pkg/pgxutils"
)

// Notmrk is an import job to import
// fairway marks of type NOTMRK in form of point geometries
// and attribute data from a WFS service.
type Notmrk struct {
	FairwayMarks
}

// Description gives a short info about relevant facts of this import.
func (notmrk *Notmrk) Description() (string, error) {
	return notmrk.URL + "|" + notmrk.FeatureType, nil
}

// NOTMRKJobKind is the import queue type identifier.
const NOTMRKJobKind JobKind = "fm_notmrk"

type notmrkJobCreator struct{}

func init() {
	RegisterJobCreator(NOTMRKJobKind, notmrkJobCreator{})
}

func (notmrkJobCreator) Description() string { return "fairway marks notmrk" }

func (notmrkJobCreator) AutoAccept() bool { return true }

func (notmrkJobCreator) Create() Job { return new(Notmrk) }

func (notmrkJobCreator) Depends() [2][]string {
	return [2][]string{
		{"fairway_marks_notmrk"},
		{},
	}
}

// StageDone is a NOP for fairway marks imports.
func (notmrkJobCreator) StageDone(context.Context, *sql.Tx, int64) error {
	return nil
}

// CleanUp for fairway marks imports is a NOP.
func (*Notmrk) CleanUp() error { return nil }

type notmrkProperties struct {
	fairwayMarksProperties
	Condtn *int     `json:"hydro_condtn"`
	Marsys *int     `json:"hydro_bcnshp"`
	Dirimp *string  `json:"ienc_dirimp"`
	Orient *float64 `json:"hydro_orient"`
	Status *string  `json:"hydro_status"`
	Addmrk *string  `json:"ienc_addmrk"`
	Catnmk *int     `json:"ienc_catnmk"`
	Disipd *float64 `json:"ienc_disipd"`
	Disipu *float64 `json:"ienc_disipu"`
	Disbk1 *float64 `json:"ienc_disbk1"`
	Disbk2 *float64 `json:"ienc_disbk2"`
	Fnctnm *int     `json:"ienc_fnctnm"`
	Bnkwtw *int     `json:"ienc_bnkwtw"`
}

type notmrkFeaturetype struct {
	geom  pointSlice
	props *notmrkProperties
}

const (
	insertNotmrkDirimpSQL = `
INSERT INTO waterway.fairway_marks_notmrk_dirimps (fm_notmrk_id, dirimp)
  VALUES ($1, $2)
`
)

// Do executes the actual import.
func (fm *Notmrk) Do(
	ctx context.Context,
	importID int64,
	conn *sql.Conn,
	feedback Feedback,
) (interface{}, error) {

	err := getFMFeatures(
		ctx,
		conn,
		feedback,
		fm.FairwayMarks,
		func() interface{} { return new(notmrkProperties) },
		func(p pointSlice, props interface{}) interface{} {
			return &notmrkFeaturetype{p, props.(*notmrkProperties)}
		},
		func(
			tx *sql.Tx, epsg int, fms []interface{},
		) (outsideOrDup int, features int, err error) {

			feedback.Info("Store fairway marks of type NOTMRK")

			insertStmt, err := tx.PrepareContext(
				ctx,
				getFMInsertSQL("notmrk",
					"condtn", "marsys", "orient",
					"status", "addmrk", "catnmk",
					"disipd", "disipu", "disbk1",
					"disbk2", "fnctnm", "bnkwtw"),
			)
			if err != nil {
				return
			}
			defer insertStmt.Close()

			insertNotmrkDirimpStmt, err := tx.PrepareContext(
				ctx, insertNotmrkDirimpSQL)
			if err != nil {
				return
			}
			defer insertNotmrkDirimpStmt.Close()

			savepoint := Savepoint(ctx, tx, "feature")

			for _, fm := range fms {

				f := fm.(*notmrkFeaturetype)

				var fmid int64
				err := savepoint(func() error {
					err := insertStmt.QueryRowContext(
						ctx,
						f.geom.asWKB(),
						epsg,
						f.props.Datsta,
						f.props.Datend,
						f.props.Persta,
						f.props.Perend,
						f.props.Objnam,
						f.props.Nobjnm,
						f.props.Inform,
						f.props.Ninfom,
						f.props.Scamin,
						f.props.Picrep,
						f.props.Txtdsc,
						f.props.Sordat,
						f.props.Sorind,
						f.props.Condtn,
						f.props.Marsys,
						f.props.Orient,
						f.props.Status,
						f.props.Addmrk,
						f.props.Catnmk,
						f.props.Disipd,
						f.props.Disipu,
						f.props.Disbk1,
						f.props.Disbk2,
						f.props.Fnctnm,
						f.props.Bnkwtw,
					).Scan(&fmid)
					return err
				})
				switch {
				case err == sql.ErrNoRows:
					outsideOrDup++
					// ignore -> filtered by responsibility area or a duplicate
					// TODO: handle eventual changes to dirimp
				case err != nil:
					feedback.Error(pgxutils.ReadableError{Err: err}.Error())
				default:
					features++

					if f.props.Dirimp != nil && *f.props.Dirimp != "" {
						dirimps := strings.Split(*f.props.Dirimp, ",")
						for _, dirimp := range dirimps {
							if err := savepoint(func() error {
								_, err := insertNotmrkDirimpStmt.ExecContext(
									ctx, fmid, dirimp)
								return err
							}); err != nil {
								feedback.Warn(
									pgxutils.ReadableError{Err: err}.Error())
								feedback.Info(
									"Tried to import '%s' as dirimp value",
									dirimp)
							}
						}
					}
				}
			}
			return
		})

	return nil, err
}