Mercurial > gemma
view pkg/geoserver/templates.go @ 5493:0cd4ff1066fe logging
Signal config readiness after logging is configured.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 20 Sep 2021 18:14:02 +0200 |
parents | 24156a964eaa |
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) 2019 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> // * Markus Kottländer <markus.kottlaender@intevation.de> // * Bernhard Reiter <bernhard.reiter@intevation.de> package geoserver import ( "context" "database/sql" "regexp" "strconv" "strings" "text/template" "gemma.intevation.de/gemma/pkg/auth" "gemma.intevation.de/gemma/pkg/models" ) const ( selectConfigValSQL = ` SELECT config_val FROM sys_admin.system_config WHERE config_key = $1` ) func init() { RegisterStylePreprocessor( "sounding_results_areas_geoserver", templateContourLinesFunc("morphology_classbreaks")) RegisterStylePreprocessor( "sounding_results_marking_points_geoserver", templateContourLinesFunc("morphology_classbreaks")) RegisterStylePreprocessor( "sounding_differences", templateContourLinesFunc("morphology_classbreaks_compare")) RegisterStylePreprocessor( "distance_marks_geoserver", templateConfigValues) RegisterStylePreprocessor( "distance_marks_ashore_geoserver", templateConfigValues) RegisterStylePreprocessor( "waterway_area", templateConfigValues) RegisterStylePreprocessor( "waterway_axis", templateConfigValues) // TODO: Add more layers. } func templateConfigValues(tmplTxt string) (string, error) { // As SLDs cannot handle opacity as hex part of the color setting // we split out the 7-8 chars of keys ending on "_fill" color settings // into keys ending on "_fill_opacity" tmpl, err := template.New("template").Parse(tmplTxt) if err != nil { return "", err } // Try to extract the needed keys from the template. keys := extractKeysFromTemplate(tmplTxt) // filter out keys ending on "_opacity" and put them in their own slice var opacityKeys []string n := 0 for _, key := range keys { if strings.HasSuffix(key, "_opacity") { opacityKeys = append(opacityKeys, key) } else { keys[n] = key n++ } } keys = keys[:n] kv, err := loadConfigValues(keys) if err != nil { return "", err } // if there convert opacity hex value into float between 0-1 // otherwise just use 1.0 for _, opacityKey := range opacityKeys { fillKey := opacityKey[0 : len(opacityKey)-8] fillValue := kv[fillKey] if fillValue != "" && len(fillValue) == 9 { opacity, err := strconv.ParseInt(fillValue[7:9], 16, 0) if err == nil { kv[opacityKey] = strconv.FormatFloat( float64(opacity)/255, 'f', 2, 64) kv[fillKey] = kv[fillKey][0:7] } else { return "", err } } else { kv[opacityKey] = "1.0" } } var buf strings.Builder if err = tmpl.Execute(&buf, kv); err != nil { return "", err } return buf.String(), nil } // TODO: Use the parse tree of the template to extract keys. var findKeysRe = regexp.MustCompile(`{{[-]?\s*\.([^-.\s]+)\s*[-]?}}`) func extractKeysFromTemplate(tmpl string) []string { parts := findKeysRe.FindAllStringSubmatch(tmpl, -1) keys := make(map[string]struct{}) for _, part := range parts { keys[part[1]] = struct{}{} } out := make([]string, len(keys)) var i int for key := range keys { out[i] = key i++ } return out } func loadConfigValues(keys []string) (map[string]string, error) { kv := make(map[string]string, len(keys)) if len(keys) == 0 { return kv, nil } ctx := context.Background() if err := auth.RunAs( ctx, "sys_admin", func(conn *sql.Conn) error { stmt, err := conn.PrepareContext(ctx, selectConfigValSQL) if err != nil { return err } defer stmt.Close() for _, key := range keys { var val string if err := stmt.QueryRowContext(ctx, key).Scan(&val); err != nil { return err } kv[key] = val } return nil }, ); err != nil { return nil, err } return kv, nil } func templateContourLinesFunc(configKey string) func(string) (string, error) { return func(data string) (string, error) { return templateContourLines(data, configKey) } } func templateContourLines(data, configKey string) (string, error) { tmpl, err := template.New("template").Parse(data) if err != nil { return "", err } var cb []models.ClassBreak if cb, err = countourLinesClassBreaks(configKey); err != nil { return "", err } var buf strings.Builder if err = tmpl.Execute(&buf, cb); err != nil { return "", err } return buf.String(), nil } func countourLinesClassBreaks(configKey string) ([]models.ClassBreak, error) { var config string ctx := context.Background() if err := auth.RunAs( ctx, "sys_admin", func(conn *sql.Conn) error { return conn.QueryRowContext( ctx, selectConfigValSQL, configKey, ).Scan(&config) }, ); err != nil { return nil, err } cc, err := models.ParseColorValues(config) if err != nil { return nil, err } return cc.ClassBreaks(), nil }