Mercurial > gemma
view pkg/models/intservices.go @ 876:8b9bd9ccdd93 geo-style
Upload style during boot. TODO: Connect with layer.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Sun, 30 Sep 2018 19:42:16 +0200 |
parents | ad9272460ef3 |
children | 254cd247826d |
line wrap: on
line source
package models import ( "context" "database/sql" "fmt" "log" "net/http" "strings" "sync" "gemma.intevation.de/gemma/pkg/auth" "gemma.intevation.de/gemma/pkg/config" ) type IntEntry struct { Name string `json:"name"` Style sql.NullString `json:"-"` // This should be done separately. WMS bool `json:"wms"` WFS bool `json:"wfs"` } type IntServices struct { entries []IntEntry mu sync.Mutex } const ( selectPublishedServices = `SELECT relname, style, as_wms, as_wfs FROM sys_admin.published_services JOIN pg_class ON name = oid ORDER by relname` updateStyleSQL = ` UPDATE sys_admin.published_services SET style = xslt_process($1, $2, $3)::bytea WHERE name IN (SELECT oid FROM pg_class WHERE relname = $4)` ) const ( replaceNameXSLT = `<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sld="http://www.opengis.net/sld" xmlns:se="http://www.opengis.net/se"> <xsl:param name="name"/> <xsl:template match="/sld:StyledLayerDescriptor/sld:NamedLayer/sld:Name/text()"> <xsl:value-of select="$name"/> </xsl:template> <xsl:template match="/sld:StyledLayerDescriptor/sld:NamedLayer/se:Name/text()"> <xsl:value-of select="$name"/> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>` ) var InternalServices = &IntServices{} func UpdateInternalStyle(req *http.Request, name, style string) error { return auth.RunAsSessionUser(req, func(conn *sql.Conn) error { param := fmt.Sprintf("name='%s'", strings.Replace(name, ",", "", -1)) _, err := conn.ExecContext( req.Context(), updateStyleSQL, style, replaceNameXSLT, param, name) if err == nil { InternalServices.Invalidate() } return err }) } func (ps *IntServices) Find(name string) (string, bool) { ps.mu.Lock() defer ps.mu.Unlock() if ps.entries == nil { if err := ps.load(); err != nil { log.Printf("error: %v\n", err) return "", false } } if ps.has(name) { return config.GeoServerURL() + "/" + name, true } return "", false } func (ps *IntServices) has(service string) bool { var check func(*IntEntry) bool switch service { case "wms": check = func(e *IntEntry) bool { return e.WMS } case "wfs": check = func(e *IntEntry) bool { return e.WFS } default: return false } for i := range ps.entries { if check(&ps.entries[i]) { return true } } return false } func (ps *IntServices) load() error { // make empty slice to prevent retry if slice is empty. ps.entries = []IntEntry{} return auth.RunAs("sys_admin", context.Background(), func(conn *sql.Conn) error { rows, err := conn.QueryContext( context.Background(), selectPublishedServices) if err != nil { return err } defer rows.Close() for rows.Next() { var entry IntEntry if err := rows.Scan( &entry.Name, &entry.Style, &entry.WMS, &entry.WFS, ); err != nil { return err } ps.entries = append(ps.entries, entry) } return rows.Err() }) } func (ps *IntServices) Invalidate() { ps.mu.Lock() ps.entries = nil ps.mu.Unlock() } func InternalAll(IntEntry) bool { return true } func IntWMS(entry IntEntry) bool { return entry.WMS } func IntWFS(entry IntEntry) bool { return entry.WFS } func IntByName(name string) func(IntEntry) bool { return func(entry IntEntry) bool { return entry.Name == name } } func IntAnd(a, b func(IntEntry) bool) func(IntEntry) bool { return func(entry IntEntry) bool { return a(entry) && b(entry) } } func IntWithStyle(entry IntEntry) bool { return entry.Style.Valid } func (ps *IntServices) Filter(accept func(IntEntry) bool) []IntEntry { ps.mu.Lock() defer ps.mu.Unlock() if ps.entries == nil { if err := ps.load(); err != nil { log.Printf("error: %v\n", err) return nil } } pe := make([]IntEntry, 0, len(ps.entries)) for _, e := range ps.entries { if accept(e) { pe = append(pe, e) } } return pe }