Simplify NewMapper by using mapping lists instead of configuration files
diff --git a/cmd/termmapper/fuzz_test.go b/cmd/termmapper/fuzz_test.go
index 8d63d53..e5dd7a5 100644
--- a/cmd/termmapper/fuzz_test.go
+++ b/cmd/termmapper/fuzz_test.go
@@ -8,11 +8,10 @@
"net/http"
"net/http/httptest"
"net/url"
- "os"
- "path/filepath"
"strings"
"testing"
+ tmconfig "github.com/KorAP/KoralPipe-TermMapper/config"
"github.com/KorAP/KoralPipe-TermMapper/mapper"
"github.com/gofiber/fiber/v2"
"github.com/stretchr/testify/assert"
@@ -31,26 +30,21 @@
}
func FuzzTransformEndpoint(f *testing.F) {
- // Create a temporary config file with valid mappings
- tmpDir := f.TempDir()
- configFile := filepath.Join(tmpDir, "test-config.yaml")
-
- configContent := `- id: test-mapper
- foundryA: opennlp
- layerA: p
- foundryB: upos
- layerB: p
- mappings:
- - "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]"
- - "[DET] <> [opennlp/p=DET]"`
-
- err := os.WriteFile(configFile, []byte(configContent), 0644)
- if err != nil {
- f.Fatal(err)
+ // Create test mapping list
+ mappingList := tmconfig.MappingList{
+ ID: "test-mapper",
+ FoundryA: "opennlp",
+ LayerA: "p",
+ FoundryB: "upos",
+ LayerB: "p",
+ Mappings: []tmconfig.MappingRule{
+ "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]",
+ "[DET] <> [opennlp/p=DET]",
+ },
}
// Create mapper
- m, err := mapper.NewMapper(configFile)
+ m, err := mapper.NewMapper([]tmconfig.MappingList{mappingList})
if err != nil {
f.Fatal(err)
}
@@ -141,19 +135,16 @@
}
func TestLargeInput(t *testing.T) {
- // Create a temporary config file
- tmpDir := t.TempDir()
- configFile := filepath.Join(tmpDir, "test-config.yaml")
-
- configContent := `- id: test-mapper
- mappings:
- - "[A] <> [B]"`
-
- err := os.WriteFile(configFile, []byte(configContent), 0644)
- require.NoError(t, err)
+ // Create test mapping list
+ mappingList := tmconfig.MappingList{
+ ID: "test-mapper",
+ Mappings: []tmconfig.MappingRule{
+ "[A] <> [B]",
+ },
+ }
// Create mapper
- m, err := mapper.NewMapper(configFile)
+ m, err := mapper.NewMapper([]tmconfig.MappingList{mappingList})
require.NoError(t, err)
// Create fiber app
diff --git a/cmd/termmapper/main.go b/cmd/termmapper/main.go
index 664471d..4b29825 100644
--- a/cmd/termmapper/main.go
+++ b/cmd/termmapper/main.go
@@ -7,6 +7,7 @@
"strings"
"syscall"
+ "github.com/KorAP/KoralPipe-TermMapper/config"
"github.com/KorAP/KoralPipe-TermMapper/mapper"
"github.com/alecthomas/kong"
"github.com/gofiber/fiber/v2"
@@ -19,14 +20,14 @@
maxParamLength = 1024 // 1KB
)
-type config struct {
+type appConfig struct {
Port int `kong:"short='p',default='8080',help='Port to listen on'"`
Config string `kong:"short='c',required,help='YAML configuration file containing mapping directives'"`
LogLevel string `kong:"short='l',default='info',help='Log level (debug, info, warn, error)'"`
}
-func parseConfig() *config {
- cfg := &config{}
+func parseConfig() *appConfig {
+ cfg := &appConfig{}
ctx := kong.Parse(cfg,
kong.Description("A web service for transforming JSON objects using term mapping rules."),
kong.UsageOnError(),
@@ -58,8 +59,14 @@
// Set up logging
setupLogger(cfg.LogLevel)
+ // Load configuration file
+ yamlConfig, err := config.LoadConfig(cfg.Config)
+ if err != nil {
+ log.Fatal().Err(err).Msg("Failed to load configuration")
+ }
+
// Create a new mapper instance
- m, err := mapper.NewMapper(cfg.Config)
+ m, err := mapper.NewMapper(yamlConfig.Lists)
if err != nil {
log.Fatal().Err(err).Msg("Failed to create mapper")
}
diff --git a/cmd/termmapper/main_test.go b/cmd/termmapper/main_test.go
index 6460ae7..7b83811 100644
--- a/cmd/termmapper/main_test.go
+++ b/cmd/termmapper/main_test.go
@@ -6,10 +6,9 @@
"io"
"net/http"
"net/http/httptest"
- "os"
- "path/filepath"
"testing"
+ tmconfig "github.com/KorAP/KoralPipe-TermMapper/config"
"github.com/KorAP/KoralPipe-TermMapper/mapper"
"github.com/gofiber/fiber/v2"
"github.com/stretchr/testify/assert"
@@ -17,24 +16,21 @@
)
func TestTransformEndpoint(t *testing.T) {
- // Create a temporary config file
- tmpDir := t.TempDir()
- configFile := filepath.Join(tmpDir, "test-config.yaml")
-
- configContent := `- id: test-mapper
- foundryA: opennlp
- layerA: p
- foundryB: upos
- layerB: p
- mappings:
- - "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]"
- - "[DET] <> [opennlp/p=DET]"`
-
- err := os.WriteFile(configFile, []byte(configContent), 0644)
- require.NoError(t, err)
+ // Create test mapping list
+ mappingList := tmconfig.MappingList{
+ ID: "test-mapper",
+ FoundryA: "opennlp",
+ LayerA: "p",
+ FoundryB: "upos",
+ LayerB: "p",
+ Mappings: []tmconfig.MappingRule{
+ "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]",
+ "[DET] <> [opennlp/p=DET]",
+ },
+ }
// Create mapper
- m, err := mapper.NewMapper(configFile)
+ m, err := mapper.NewMapper([]tmconfig.MappingList{mappingList})
require.NoError(t, err)
// Create fiber app
@@ -255,18 +251,16 @@
}
func TestHealthEndpoint(t *testing.T) {
- // Create a temporary config file for the mapper
- tmpDir := t.TempDir()
- configFile := filepath.Join(tmpDir, "test-config.yaml")
- configContent := `- id: test-mapper
- mappings:
- - "[A] <> [B]"`
+ // Create test mapping list
+ mappingList := tmconfig.MappingList{
+ ID: "test-mapper",
+ Mappings: []tmconfig.MappingRule{
+ "[A] <> [B]",
+ },
+ }
- err := os.WriteFile(configFile, []byte(configContent), 0644)
- require.NoError(t, err)
-
- // Create mapper with config
- m, err := mapper.NewMapper(configFile)
+ // Create mapper
+ m, err := mapper.NewMapper([]tmconfig.MappingList{mappingList})
require.NoError(t, err)
// Create fiber app
diff --git a/config/config.go b/config/config.go
index be9860b..6bafaad 100644
--- a/config/config.go
+++ b/config/config.go
@@ -22,13 +22,13 @@
Mappings []MappingRule `yaml:"mappings"`
}
-// Config represents the root configuration containing multiple mapping lists
-type Config struct {
+// MappingLists represents the root configuration containing multiple mapping lists
+type MappingLists struct {
Lists []MappingList
}
// LoadConfig loads a YAML configuration file and returns a Config object
-func LoadConfig(filename string) (*Config, error) {
+func LoadConfig(filename string) (*MappingLists, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %w", err)
@@ -69,7 +69,7 @@
}
}
- return &Config{Lists: lists}, nil
+ return &MappingLists{Lists: lists}, nil
}
// ParseMappings parses all mapping rules in a list and returns a slice of parsed rules
diff --git a/mapper/mapper.go b/mapper/mapper.go
index b7c8066..852ed83 100644
--- a/mapper/mapper.go
+++ b/mapper/mapper.go
@@ -24,37 +24,29 @@
parsedRules map[string][]*parser.MappingResult
}
-// NewMapper creates a new Mapper instance
-func NewMapper(configFiles ...string) (*Mapper, error) {
+// NewMapper creates a new Mapper instance from a list of MappingLists
+func NewMapper(lists []config.MappingList) (*Mapper, error) {
m := &Mapper{
mappingLists: make(map[string]*config.MappingList),
parsedRules: make(map[string][]*parser.MappingResult),
}
- // Load and parse all config files
- for _, file := range configFiles {
- cfg, err := config.LoadConfig(file)
+ // Store mapping lists by ID
+ for _, list := range lists {
+ if _, exists := m.mappingLists[list.ID]; exists {
+ return nil, fmt.Errorf("duplicate mapping list ID found: %s", list.ID)
+ }
+
+ // Create a copy of the list to store
+ listCopy := list
+ m.mappingLists[list.ID] = &listCopy
+
+ // Parse the rules immediately
+ parsedRules, err := list.ParseMappings()
if err != nil {
- return nil, fmt.Errorf("failed to load config from %s: %w", file, err)
+ return nil, fmt.Errorf("failed to parse mappings for list %s: %w", list.ID, err)
}
-
- // Store mapping lists by ID
- for _, list := range cfg.Lists {
- if _, exists := m.mappingLists[list.ID]; exists {
- return nil, fmt.Errorf("duplicate mapping list ID found: %s", list.ID)
- }
-
- // Create a copy of the list to store
- listCopy := list
- m.mappingLists[list.ID] = &listCopy
-
- // Parse the rules immediately
- parsedRules, err := list.ParseMappings()
- if err != nil {
- return nil, fmt.Errorf("failed to parse mappings for list %s: %w", list.ID, err)
- }
- m.parsedRules[list.ID] = parsedRules
- }
+ m.parsedRules[list.ID] = parsedRules
}
return m, nil
diff --git a/mapper/mapper_test.go b/mapper/mapper_test.go
index d5d4020..a83586d 100644
--- a/mapper/mapper_test.go
+++ b/mapper/mapper_test.go
@@ -2,35 +2,31 @@
import (
"encoding/json"
- "os"
- "path/filepath"
"testing"
"github.com/KorAP/KoralPipe-TermMapper/ast"
+ "github.com/KorAP/KoralPipe-TermMapper/config"
"github.com/KorAP/KoralPipe-TermMapper/matcher"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMapper(t *testing.T) {
- // Create a temporary config file
- tmpDir := t.TempDir()
- configFile := filepath.Join(tmpDir, "test-config.yaml")
-
- configContent := `- id: test-mapper
- foundryA: opennlp
- layerA: p
- foundryB: upos
- layerB: p
- mappings:
- - "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]"
- - "[DET] <> [opennlp/p=DET]"`
-
- err := os.WriteFile(configFile, []byte(configContent), 0644)
- require.NoError(t, err)
+ // Create test mapping list
+ mappingList := config.MappingList{
+ ID: "test-mapper",
+ FoundryA: "opennlp",
+ LayerA: "p",
+ FoundryB: "upos",
+ LayerB: "p",
+ Mappings: []config.MappingRule{
+ "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]",
+ "[DET] <> [opennlp/p=DET]",
+ },
+ }
// Create a new mapper
- m, err := NewMapper(configFile)
+ m, err := NewMapper([]config.MappingList{mappingList})
require.NoError(t, err)
tests := []struct {
@@ -318,23 +314,20 @@
}
func TestInvalidPatternReplacement(t *testing.T) {
- // Create a temporary config file
- tmpDir := t.TempDir()
- configFile := filepath.Join(tmpDir, "test-config.yaml")
-
- configContent := `- id: test-mapper
- foundryA: opennlp
- layerA: p
- foundryB: upos
- layerB: p
- mappings:
- - "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]"`
-
- err := os.WriteFile(configFile, []byte(configContent), 0644)
- require.NoError(t, err)
+ // Create test mapping list
+ mappingList := config.MappingList{
+ ID: "test-mapper",
+ FoundryA: "opennlp",
+ LayerA: "p",
+ FoundryB: "upos",
+ LayerB: "p",
+ Mappings: []config.MappingRule{
+ "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]",
+ },
+ }
// Create a new mapper
- m, err := NewMapper(configFile)
+ m, err := NewMapper([]config.MappingList{mappingList})
require.NoError(t, err)
tests := []struct {