# HG changeset patch # User Sascha L. Teichmann # Date 1562171201 -7200 # Node ID 885eb90255ff695ca15c8752a0f350def2c8ebba # Parent 6028326b88d6d34a6adea1645ca42c37d00df92b Cleanup templating of styles [WIP]. diff -r 6028326b88d6 -r 885eb90255ff pkg/geoserver/boot.go --- a/pkg/geoserver/boot.go Wed Jul 03 17:48:47 2019 +0200 +++ b/pkg/geoserver/boot.go Wed Jul 03 18:26:41 2019 +0200 @@ -15,23 +15,18 @@ import ( "bytes" - "context" - "database/sql" "encoding/json" "encoding/xml" "fmt" "io" "log" - "math" "net/http" "net/url" - "strconv" "strings" - "text/template" + "sync" "golang.org/x/net/html/charset" - "gemma.intevation.de/gemma/pkg/auth" "gemma.intevation.de/gemma/pkg/config" "gemma.intevation.de/gemma/pkg/models" ) @@ -42,12 +37,11 @@ databaseScheme = "waterway" databaseType = "postgis" primaryKeyMetadataTbl = "waterway.gt_pk_metadata" - - bootRole = "sys_admin" +) - startupSQL = `SELECT public.setrole('${user,'||encode('waterway_user', 'hex')||'}')` - closeupSQL = `RESET ROLE` - selectClassBreaksSQL = `SELECT config_val FROM sys_admin.system_config WHERE config_key = 'morphology_classbreaks'` +const ( + startupSQL = `SELECT public.setrole('${user,'||encode('waterway_user', 'hex')||'}')` + closeupSQL = `RESET ROLE` ) func basicAuth(user, password string) func(req *http.Request) { @@ -398,112 +392,21 @@ return nil } -type classBreak struct { - Low string - High string - Color string -} - -func interpolateColor(i int, classBreaks [][]string) string { - var leftColor, rightColor string +var ( + stylePreprocessorsMu sync.Mutex + stylePreprocessors = map[string]func(string) (string, error){} +) - // look for next color to the left - lookLeft := i - for lookLeft >= 0 && leftColor == "" { - lookLeft -= 1 - if len(classBreaks[lookLeft]) == 2 { - leftColor = classBreaks[lookLeft][1] - } - } - // look for next color to the right - lookRight := i - for lookRight < len(classBreaks) && rightColor == "" { - lookRight += 1 - if len(classBreaks[lookRight]) == 2 { - rightColor = classBreaks[lookRight][1] - } - } - - // calculate interpolation factor - middle, left, right := float32(i), float32(lookLeft), float32(lookRight) - interpolationFactor := (middle - left) / (right - left) - - // convert colors to rgb - leftHex := []string{leftColor[1:3], leftColor[3:5], leftColor[5:7]} - leftR, _ := strconv.ParseFloat(leftHex[0], 32) - leftG, _ := strconv.ParseFloat(leftHex[1], 32) - leftB, _ := strconv.ParseFloat(leftHex[2], 32) - rightHex := []string{rightColor[1:3], rightColor[3:5], rightColor[5:7]} - rightR, _ := strconv.ParseFloat(rightHex[0], 32) - rightG, _ := strconv.ParseFloat(rightHex[1], 32) - rightB, _ := strconv.ParseFloat(rightHex[2], 32) - - interpolatedR := leftR + float64(interpolationFactor)*(rightR-leftR) - interpolatedG := leftG + float64(interpolationFactor)*(rightG-leftG) - interpolatedB := leftB + float64(interpolationFactor)*(rightB-leftB) - - // hexR := fmt.Sprintf("%x", math.Round(interpolatedR)) - // hexG := fmt.Sprintf("%x", math.Round(interpolatedG)) - // hexB := fmt.Sprintf("%x", math.Round(interpolatedB)) - log.Printf("#%x%x%x", int(math.Round(interpolatedR)), int(math.Round(interpolatedG)), int(math.Round(interpolatedB))) - - return "asd" +func RegisterStylePreprocessor(name string, processor func(string) (string, error)) { + stylePreprocessorsMu.Lock() + defer stylePreprocessorsMu.Unlock() + stylePreprocessors[name] = processor } -func getTemplateData(name string) interface{} { - if name == "sounding_results_contour_lines_geoserver" { - // get class breaks string from database - var classBreaksString string - ctx := context.Background() - err := auth.RunAs( - ctx, bootRole, - func(conn *sql.Conn) error { - return conn.QueryRowContext(ctx, selectClassBreaksSQL).Scan(&classBreaksString) - }) - if err != nil { - log.Printf("error: %v\n", err) - } - - // convert string to array of arrays [[num, color], [num], [num], [num, color] ...] - classBreaksTmp := strings.Split(classBreaksString, ",") - classBreaks := [][]string{} - for _, cb := range classBreaksTmp { - classBreaks = append(classBreaks, strings.Split(cb, ":")) - } - - // interpolate colors - for i, cb := range classBreaks { - if len(cb) == 1 { - classBreaks[i] = append(cb, interpolateColor(i, classBreaks)) - } - } - - classBreaksForTmpl := []classBreak{} - for i := range classBreaks { - // set low/high - var low, high string - if i == 0 { - high = classBreaks[i][0] - } else { - low = classBreaks[i-1][0] - high = classBreaks[i][0] - } - classBreaksForTmpl = append(classBreaksForTmpl, classBreak{ - Low: low, - High: high, - Color: classBreaks[i][1], - }) - } - // add last class break (> last value) - classBreaksForTmpl = append(classBreaksForTmpl, classBreak{ - Low: classBreaks[len(classBreaks)-1][0], - High: "", - Color: classBreaks[len(classBreaks)-1][1], - }) - log.Printf("%v", classBreaksForTmpl) - return classBreaksForTmpl - } - return nil +func FindStylePreprocessor(name string) func(string) (string, error) { + stylePreprocessorsMu.Lock() + defer stylePreprocessorsMu.Unlock() + return stylePreprocessors[name] } func updateStyle(entry *models.IntEntry, create bool) error { @@ -516,15 +419,10 @@ return err } - // Parse data as template - if entry.Name == "sounding_results_contour_lines_geoserver" { - tmpl, err := template.New(entry.Name).Parse(data) - if err != nil { + if processor := FindStylePreprocessor(entry.Name); processor != nil { + if data, err = processor(data); err != nil { return err } - var buffer bytes.Buffer - err = tmpl.Execute(&buffer, getTemplateData(entry.Name)) - data = buffer.String() } var ( diff -r 6028326b88d6 -r 885eb90255ff pkg/geoserver/templates.go --- a/pkg/geoserver/templates.go Wed Jul 03 17:48:47 2019 +0200 +++ b/pkg/geoserver/templates.go Wed Jul 03 18:26:41 2019 +0200 @@ -14,13 +14,31 @@ package geoserver import ( + "context" + "database/sql" + "fmt" "image/color" "math" "sort" "strconv" "strings" + "text/template" + + "gemma.intevation.de/gemma/pkg/auth" ) +const ( + selectClassBreaksSQL = ` +SELECT config_val FROM sys_admin.system_config +WHERE config_key = 'morphology_classbreaks'` +) + +func init() { + RegisterStylePreprocessor( + "sounding_results_contour_lines_geoserver", + templateSRContourLines) +} + type colorClass struct { value float64 color color.RGBA @@ -167,3 +185,72 @@ return final, err } + +func templateSRContourLines(data string) (string, error) { + tmpl, err := template.New("template").Parse(data) + if err != nil { + return "", err + } + + var cb []classBreak + + if cb, err = getSRContoursClassBreaks(); err != nil { + return "", err + } + + var buf strings.Builder + if err = tmpl.Execute(&buf, cb); err != nil { + return "", err + } + return buf.String(), nil +} + +type classBreak struct { + High float64 + HasHigh bool + Low float64 + HasLow bool + Color string +} + +func (cc colorClasses) toClassBreaks() []classBreak { + + cbs := make([]classBreak, len(cc)) + for i := range cc { + if i > 0 { + cbs[i].Low = cc[i-1].value + cbs[i].HasLow = true + } + if i < len(cc)-1 { + cbs[i].High = cc[i].value + cbs[i].HasHigh = true + } + cbs[i].Color = fmt.Sprintf("#%02x%02x%02x", + cc[i].color.R, + cc[i].color.G, + cc[i].color.B) + } + return cbs +} + +func getSRContoursClassBreaks() ([]classBreak, error) { + + var config string + ctx := context.Background() + if err := auth.RunAs( + ctx, + "sys_admin", + func(conn *sql.Conn) error { + return conn.QueryRowContext(ctx, selectClassBreaksSQL).Scan(&config) + }, + ); err != nil { + return nil, err + } + + cc, err := parseColorClasses(config) + if err != nil { + return nil, err + } + + return cc.toClassBreaks(), nil +} diff -r 6028326b88d6 -r 885eb90255ff pkg/geoserver/templates_test.go --- a/pkg/geoserver/templates_test.go Wed Jul 03 17:48:47 2019 +0200 +++ b/pkg/geoserver/templates_test.go Wed Jul 03 18:26:41 2019 +0200 @@ -14,7 +14,6 @@ package geoserver import ( - "fmt" "strings" "testing" "text/template" @@ -166,10 +165,10 @@ {{- range . }} {{ if .HasHigh -}} - {{ printf "%.1f" .High}}{{ printf "%.1f" .High}} - {{- else if .HasLow -}} - {{ printf "%.1f" .Low}}{{ printf "%.1f" .Low}} - {{- end }} + {{ printf "%.1f" .High}}{{ printf "%.1f" .High}} + {{- else if .HasLow -}} + {{ printf "%.1f" .Low}}{{ printf "%.1f" .Low}} + {{- end }} {{- end }} @@ -898,14 +897,6 @@ const classBreaksConfig = `1:#ff00dd,1.5,1.7,1.9,2.1,2.3,2.5:#f25f20,2.7,2.9,3.1,3.3,3.5,4:#8ad51a,4.5,5,5.5,6,6.5,7,7.5:#1414ff` -type classBreaks struct { - High float64 - HasHigh bool - Low float64 - HasLow bool - Color string -} - func TestTemplate(t *testing.T) { ccs, err := parseColorClasses(classBreaksConfig) @@ -923,21 +914,7 @@ } */ - cbs := make([]classBreaks, len(ccs)) - for i := range ccs { - if i > 0 { - cbs[i].Low = ccs[i-1].value - cbs[i].HasLow = true - } - if i < len(ccs)-1 { - cbs[i].High = ccs[i].value - cbs[i].HasHigh = true - } - cbs[i].Color = fmt.Sprintf("#%02x%02x%02x", - ccs[i].color.R, - ccs[i].color.G, - ccs[i].color.B) - } + cbs := ccs.toClassBreaks() tmpl, err := template.New("test").Parse(sldTmplTxt) if err != nil {