Skip to content

Commit

Permalink
Added AppFilePropertySource and AppFileParse to hold and parse the pr… (
Browse files Browse the repository at this point in the history
#3)

Add file property file support.
  • Loading branch information
burakkoken authored Jun 17, 2021
1 parent 4afc203 commit 9dcfbb0
Show file tree
Hide file tree
Showing 23 changed files with 492 additions and 128 deletions.
4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ go:
- 1.14.x
- 1.15.x

branches:
only:
- master

before_install:
- go get -t -v ./...

Expand Down
145 changes: 145 additions & 0 deletions app_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package core

import (
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
"strings"
)

const ProcyonAppFilePropertySource = "ProcyonAppFilePropertySource"

const ProcyonAppFilePrefix = "procyon"
const ProcyonAppFilePath = "test-resources/"
const ProcyonAppFileSuffix = ".yaml"
const ProcyonDefaultProfile = "default"

type AppFilePropertySource struct {
propertyMap map[string]interface{}
}

func NewAppFilePropertySource(profiles string) *AppFilePropertySource {
if profiles == "" {
profiles = ProcyonDefaultProfile
}

profileArr := strings.FieldsFunc(profiles, func(r rune) bool {
return r == ','
})

filePaths := make([]string, 0)

for _, profile := range profileArr {
path := ProcyonAppFilePath + ProcyonAppFilePrefix

if profile == ProcyonDefaultProfile {
path = path + ProcyonAppFileSuffix
} else {
path = path + "." + strings.Trim(profile, " ") + ProcyonAppFileSuffix
}

filePaths = append(filePaths, path)
}

propertyMap, err := NewAppFileParser().Parse(filePaths)

if err != nil {
panic(err)
}

propertySource := &AppFilePropertySource{
propertyMap: propertyMap,
}

return propertySource
}

func (propertySource *AppFilePropertySource) GetName() string {
return ProcyonAppFilePropertySource
}

func (propertySource *AppFilePropertySource) GetSource() interface{} {
return propertySource.propertyMap
}

func (propertySource *AppFilePropertySource) GetProperty(name string) interface{} {
if propertySource.ContainsProperty(name) {
return propertySource.propertyMap[name]
}

return nil
}

func (propertySource *AppFilePropertySource) ContainsProperty(name string) bool {
if _, ok := propertySource.propertyMap[name]; ok {
return true
}

return false
}

func (propertySource *AppFilePropertySource) GetPropertyNames() []string {
keys := make([]string, 0, len(propertySource.propertyMap))

for key, _ := range propertySource.propertyMap {
keys = append(keys, key)
}

return keys
}

type AppFileParser struct {
}

func NewAppFileParser() *AppFileParser {
return &AppFileParser{}
}

func (parser *AppFileParser) Parse(filePaths []string) (map[string]interface{}, error) {
propertyMap := make(map[string]interface{})

for _, filePath := range filePaths {
resultMap, err := parser.parseFile(filePath)

if err != nil {
return nil, err
}

propertyMap = parser.mergeFlattenMap(propertyMap, resultMap)
}

return propertyMap, nil
}

func (parser *AppFileParser) parseFile(filePath string) (map[string]interface{}, error) {
if _, err := os.Stat(filePath); err != nil {
return nil, fmt.Errorf("app file does not exist : %s", filePath)
}

data, err := ioutil.ReadFile(filePath)

if err != nil {
return nil, fmt.Errorf("could not open app file '%s', %s", filePath, err.Error())
}

propertyMap := make(map[string]interface{})

err = yaml.Unmarshal(data, propertyMap)

if err != nil {
return nil, fmt.Errorf("could not read app file '%s', %s", filePath, err.Error())
}

flattenMap := FlatMap(propertyMap)

return flattenMap, nil
}

func (parser *AppFileParser) mergeFlattenMap(map1, map2 map[string]interface{}) map[string]interface{} {
for key, value := range map2 {
map1[key] = value
}

return map1
}
69 changes: 69 additions & 0 deletions app_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package core

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestAppFilePropertySource(t *testing.T) {
propertySource := NewAppFilePropertySource("dev, db")
value := propertySource.GetProperty("procyon.application.name")
if value == "" {

}
}

func TestAppFileParser_Parse(t *testing.T) {
parser := NewAppFileParser()

filePaths := []string{"test-resources/procyon.test.yaml", "test-resources/procyon.db.yaml"}

propertyMap, err := parser.Parse(filePaths)
assert.NoError(t, err)
assert.NotNil(t, propertyMap)

assert.Contains(t, propertyMap, "procyon.application.name")
assert.Equal(t, "Procyon Test Application", propertyMap["procyon.application.name"])

assert.Contains(t, propertyMap, "logging.level")
assert.Equal(t, "INFO", propertyMap["logging.level"])

assert.Contains(t, propertyMap, "server.port")
assert.Equal(t, 8095, propertyMap["server.port"])

assert.Contains(t, propertyMap, "procyon.datasource.url")
assert.Equal(t, "test-url", propertyMap["procyon.datasource.url"])

assert.Contains(t, propertyMap, "procyon.datasource.username")
assert.Equal(t, "test-username", propertyMap["procyon.datasource.username"])

assert.Contains(t, propertyMap, "procyon.datasource.password")
assert.Equal(t, "test-password", propertyMap["procyon.datasource.password"])
}

func TestAppFileParser_ContainsProperty(t *testing.T) {
propertySource := NewAppFilePropertySource("dev, db")
assert.True(t, propertySource.ContainsProperty("procyon.application.name"))
assert.False(t, propertySource.ContainsProperty("procyon.server.timeout"))
}

func TestAppFileParser_GetProperty(t *testing.T) {
propertySource := NewAppFilePropertySource("dev")
assert.NotNil(t, propertySource.GetProperty("procyon.application.name"))
assert.Equal(t, "Procyon Dev Application", propertySource.GetProperty("procyon.application.name"))
}

func TestAppFileParser_GetPropertyNames(t *testing.T) {
propertySource := NewAppFilePropertySource("dev")
assert.NotNil(t, propertySource.GetPropertyNames())
}

func TestAppFileParser_GetName(t *testing.T) {
propertySource := NewAppFilePropertySource("dev")
assert.Equal(t, ProcyonAppFilePropertySource, propertySource.GetName())
}

func TestAppFileParser_GetSource(t *testing.T) {
propertySource := NewAppFilePropertySource("dev")
assert.NotNil(t, propertySource.GetSource())
}
4 changes: 4 additions & 0 deletions args.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@ func (args CommandLineArgs) addOptionArgs(name string, value string) {
if args.optionArgs[name] == nil {
args.optionArgs[name] = make([]string, 0)
}

args.optionArgs[name] = append(args.optionArgs[name], value)
}

func (args CommandLineArgs) getOptionNames() []string {
argMapKeys := goo.GetType(args.optionArgs).GetGoValue().MapKeys()

mapKeys := make([]string, len(argMapKeys))

for i := 0; i < len(argMapKeys); i++ {
mapKeys[i] = argMapKeys[i].String()
}

return mapKeys
}

Expand Down
64 changes: 63 additions & 1 deletion cmdline.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package core

import "strings"
import (
"errors"
"flag"
"strings"
)

const ProcyonApplicationCommandLinePropertySource = "ProcyonApplicationCommandLinePropertySource"
const NonOptionArgsPropertyName = "nonOptionArgs"
Expand All @@ -18,12 +22,15 @@ type SimpleCommandLinePropertySource struct {

func NewSimpleCommandLinePropertySource(args []string) SimpleCommandLinePropertySource {
cmdLineArgs, err := NewCommandLineArgsParser().Parse(args)

if err != nil {
panic(err)
}

cmdlinePropertySource := SimpleCommandLinePropertySource{
source: cmdLineArgs,
}

return cmdlinePropertySource
}

Expand All @@ -38,22 +45,28 @@ func (cmdLineSource SimpleCommandLinePropertySource) GetSource() interface{} {
func (cmdLineSource SimpleCommandLinePropertySource) GetProperty(name string) interface{} {
if NonOptionArgsPropertyName == name {
nonOptValues := cmdLineSource.GetNonOptionArgs()

if nonOptValues != nil {
return strings.Join(nonOptValues, ",")
}

return nil
}

optValues := cmdLineSource.GetOptionValues(name)

if optValues != nil {
return strings.Join(optValues, ",")
}

return nil
}

func (cmdLineSource SimpleCommandLinePropertySource) ContainsProperty(name string) bool {
if NonOptionArgsPropertyName == name {
return len(cmdLineSource.GetNonOptionArgs()) != 0
}

return cmdLineSource.ContainsOption(name)
}

Expand All @@ -72,3 +85,52 @@ func (cmdLineSource SimpleCommandLinePropertySource) GetNonOptionArgs() []string
func (cmdLineSource SimpleCommandLinePropertySource) GetPropertyNames() []string {
return cmdLineSource.source.getOptionNames()
}

type SimpleCommandLineArgsParser struct {
}

func NewCommandLineArgsParser() SimpleCommandLineArgsParser {
return SimpleCommandLineArgsParser{}
}

func (parser SimpleCommandLineArgsParser) Parse(args []string) (CommandLineArgs, error) {
cmdLineArgs := NewCommandLineArgs()
appArgumentFlagSet := flag.NewFlagSet("ProcyonApplicationArguments", flag.ContinueOnError)

err := appArgumentFlagSet.Parse(args)

if err != nil {
return cmdLineArgs, err
}

for _, arg := range appArgumentFlagSet.Args() {

if strings.HasPrefix(arg, "--") {
optionText := arg[2:]
indexOfEqualSign := strings.Index(optionText, "=")
optionName := ""
optionValue := ""

if indexOfEqualSign > -1 {
optionName = optionText[0:indexOfEqualSign]
optionValue = optionText[indexOfEqualSign+1:]
} else {
optionName = optionText
}

optionName = strings.TrimSpace(optionName)
optionValue = strings.TrimSpace(optionValue)

if optionName == "" {
return cmdLineArgs, errors.New("Invalid argument syntax : " + arg)
}

cmdLineArgs.addOptionArgs(optionName, optionValue)
} else {
cmdLineArgs.addNonOptionArgs(arg)
}

}

return cmdLineArgs, nil
}
Loading

0 comments on commit 9dcfbb0

Please sign in to comment.