diff pkg/models/intservices.go @ 4935:c64dba002726 fairway-marks-import

Load and prepare data models for layer groups. TODO: Feed config to GeoServer.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sun, 16 Feb 2020 15:16:22 +0100
parents 4a9a1e323e11
children 4a816ecf70de
line wrap: on
line diff
--- a/pkg/models/intservices.go	Sat Feb 15 21:29:38 2020 +0100
+++ b/pkg/models/intservices.go	Sun Feb 16 15:16:22 2020 +0100
@@ -27,21 +27,29 @@
 
 const DatabaseScheme = "waterway"
 
-type IntEntry struct {
-	Schema    string  `json:"schema"`
-	Name      string  `json:"name"`
-	SQL       *string `json:"sql"`
-	KeyColumn *string `json:"keycolumn"`
-	SRS       *string `json:"srs"`
-	Style     bool    `json:"style"`
-	WMS       bool    `json:"wms"`
-	WFS       bool    `json:"wfs"`
-}
+type (
+	IntEntry struct {
+		Schema    string  `json:"schema"`
+		Name      string  `json:"name"`
+		SQL       *string `json:"sql"`
+		KeyColumn *string `json:"keycolumn"`
+		SRS       *string `json:"srs"`
+		Style     bool    `json:"style"`
+		WMS       bool    `json:"wms"`
+		WFS       bool    `json:"wfs"`
+	}
 
-type IntServices struct {
-	entries []IntEntry
-	mu      sync.Mutex
-}
+	LayerGroup struct {
+		Name   string   `json:"name"`
+		Layers []string `json:"layers"`
+	}
+
+	IntServices struct {
+		mu          sync.Mutex
+		entries     []IntEntry
+		layerGroups []LayerGroup
+	}
+)
 
 const (
 	selectServicesSQL = `
@@ -53,6 +61,11 @@
 WHERE schema = $1
 ORDER by name`
 
+	selectGroupedLayersSQL = `
+SELECT group_name, name
+FROM sys_admin.grouped_layers
+ORDER BY group_name, ord`
+
 	selectStyleSQL = `
 SELECT style
 FROM sys_admin.published_services
@@ -91,6 +104,28 @@
 	})
 }
 
+func (ps *IntServices) LayerGroups() []LayerGroup {
+	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
+		}
+	}
+
+	// To avoid races we simple make a deep copy.
+	// As we don't have such many of them it light weight enough for now.
+	groups := make([]LayerGroup, len(ps.layerGroups))
+	for i := range groups {
+		layers := make([]string, len(ps.layerGroups[i].Layers))
+		copy(layers, ps.layerGroups[i].Layers)
+		groups[i] = LayerGroup{Name: ps.layerGroups[i].Name, Layers: layers}
+	}
+	return groups
+}
+
 func (ps *IntServices) Find(name string) (string, bool) {
 	ps.mu.Lock()
 	defer ps.mu.Unlock()
@@ -129,33 +164,63 @@
 func (ps *IntServices) load() error {
 	// make empty slice to prevent retry if slice is empty.
 	ps.entries = []IntEntry{}
+	ps.layerGroups = []LayerGroup{}
 	ctx := context.Background()
-	return auth.RunAs(ctx, "sys_admin",
-		func(conn *sql.Conn) error {
-			rows, err := conn.QueryContext(
-				ctx, selectServicesSQL, DatabaseScheme)
-			if err != nil {
+
+	// Load the internal layers.
+	entries := func(conn *sql.Conn) error {
+		rows, err := conn.QueryContext(
+			ctx, selectServicesSQL, DatabaseScheme)
+		if err != nil {
+			return err
+		}
+		defer rows.Close()
+		for rows.Next() {
+			var entry IntEntry
+			if err := rows.Scan(
+				&entry.Schema, &entry.Name,
+				&entry.SQL, &entry.KeyColumn, &entry.SRS, &entry.Style,
+				&entry.WMS, &entry.WFS,
+			); err != nil {
 				return err
 			}
-			defer rows.Close()
-			for rows.Next() {
-				var entry IntEntry
-				if err := rows.Scan(
-					&entry.Schema, &entry.Name,
-					&entry.SQL, &entry.KeyColumn, &entry.SRS, &entry.Style,
-					&entry.WMS, &entry.WFS,
-				); err != nil {
-					return err
-				}
-				ps.entries = append(ps.entries, entry)
+			ps.entries = append(ps.entries, entry)
+		}
+		return rows.Err()
+	}
+
+	// Load the layer groups.
+	groups := func(conn *sql.Conn) error {
+		rows, err := conn.QueryContext(ctx, selectGroupedLayersSQL)
+		if err != nil {
+			return err
+		}
+		defer rows.Close()
+
+		for rows.Next() {
+			var group, layer string
+			if err := rows.Scan(&group, &layer); err != nil {
+				return err
 			}
-			return rows.Err()
-		})
+			if n := len(ps.layerGroups); n > 0 && ps.layerGroups[n-1].Name == group {
+				ps.layerGroups[n-1].Layers = append(ps.layerGroups[n-1].Layers, layer)
+			} else {
+				ps.layerGroups = append(ps.layerGroups, LayerGroup{
+					Name:   group,
+					Layers: []string{layer},
+				})
+			}
+		}
+		return rows.Err()
+	}
+
+	return auth.RunAllAs(ctx, "sys_admin", entries, groups)
 }
 
 func (ps *IntServices) Invalidate() {
 	ps.mu.Lock()
 	ps.entries = nil
+	ps.layerGroups = nil
 	ps.mu.Unlock()
 }