view pkg/controllers/common.go @ 5490:5f47eeea988d logging

Use own logging package.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 20 Sep 2021 17:45:39 +0200
parents 6521c962a7b6
children 6270951dda28
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) 2019 by via donau
//   – Österreichische Wasserstraßen-Gesellschaft mbH
// Software engineering by Intevation GmbH
//
// Author(s):
//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>

package controllers

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/jackc/pgx/pgtype"

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

type (
	filterNode interface {
		serialize(*strings.Builder, *[]interface{})
	}

	filterTerm struct {
		format string
		args   []interface{}
	}

	filterNot struct {
		filterNode
	}

	filterAnd []filterNode
	filterOr  []filterNode
)

func (ft *filterTerm) serialize(stmt *strings.Builder, args *[]interface{}) {
	indices := make([]interface{}, len(ft.args))
	for i := range indices {
		indices[i] = len(*args) + i + 1
	}
	fmt.Fprintf(stmt, ft.format, indices...)
	*args = append(*args, (*ft).args...)
}

func buildFilterTerm(format string, args ...interface{}) *filterTerm {
	return &filterTerm{format: format, args: args}
}

func (fa filterAnd) serialize(stmt *strings.Builder, args *[]interface{}) {
	for i, node := range fa {
		if i > 0 {
			stmt.WriteString(" AND ")
		}
		stmt.WriteByte('(')
		node.serialize(stmt, args)
		stmt.WriteByte(')')
	}
}

func (fo filterOr) serialize(stmt *strings.Builder, args *[]interface{}) {
	for i, node := range fo {
		if i > 0 {
			stmt.WriteString(" OR ")
		}
		stmt.WriteByte('(')
		node.serialize(stmt, args)
		stmt.WriteByte(')')
	}
}

func (fn *filterNot) serialize(stmt *strings.Builder, args *[]interface{}) {
	stmt.WriteString("NOT (")
	fn.filterNode.serialize(stmt, args)
	stmt.WriteByte(')')
}

func toInt8Array(txt string) *pgtype.Int8Array {
	parts := strings.Split(txt, ",")
	var ints []int64
	for _, part := range parts {
		part = strings.TrimSpace(part)
		v, err := strconv.ParseInt(part, 10, 64)
		if err != nil {
			continue
		}
		ints = append(ints, v)
	}
	var ia pgtype.Int8Array
	if err := ia.Set(ints); err != nil {
		log.Warnf("%v\n", err)
		return nil
	}
	return &ia
}

func sliceToTextArray(s []string) *pgtype.TextArray {
	if len(s) == 0 {
		return nil
	}
	var ta pgtype.TextArray
	if err := ta.Set(s); err != nil {
		log.Warnf("%v\n", err)
		return nil
	}
	return &ta
}

func toTextArray(txt string, allowed []string) *pgtype.TextArray {
	parts := strings.Split(txt, ",")
	var accepted []string
	for _, part := range parts {
		if part = strings.ToLower(strings.TrimSpace(part)); len(part) == 0 {
			continue
		}
		for _, a := range allowed {
			if part == a {
				accepted = append(accepted, part)
				break
			}
		}
	}
	return sliceToTextArray(accepted)
}

func splitUpper(s string) []string {
	s = strings.Map(func(r rune) rune {
		if ('A' <= r && r <= 'Z') || r == ',' {
			return r
		}
		return -1
	}, strings.ToUpper(s))
	return strings.FieldsFunc(s, func(r rune) bool { return r != ',' })
}