diff --git a/internal/config/errors.go b/internal/config/errors.go index 7ed4597..2a2df17 100644 --- a/internal/config/errors.go +++ b/internal/config/errors.go @@ -41,6 +41,9 @@ const ErrMissingDescription = cerr("missing description") // ErrIllegalOptionalURIParam - an URI parameter cannot be optional const ErrIllegalOptionalURIParam = cerr("URI parameter cannot be optional") +// ErrOptionalOption - an output is optional +const ErrOptionalOption = cerr("output cannot be optional") + // ErrMissingParamDesc - a parameter is missing its description const ErrMissingParamDesc = cerr("missing parameter description") diff --git a/internal/config/parameter.go b/internal/config/parameter.go index 757a09e..1f8be92 100644 --- a/internal/config/parameter.go +++ b/internal/config/parameter.go @@ -1,6 +1,8 @@ package config -import "git.xdrm.io/go/aicra/datatype" +import ( + "git.xdrm.io/go/aicra/datatype" +) // Validate implements the validator interface func (param *Parameter) Validate(datatypes ...datatype.T) error { @@ -21,16 +23,14 @@ func (param *Parameter) Validate(datatypes ...datatype.T) error { } // assign the datatype - datatypeFound := false for _, dtype := range datatypes { param.Validator = dtype.Build(param.Type, datatypes...) + param.ExtractType = dtype.Type() if param.Validator != nil { - datatypeFound = true - param.ExtractType = dtype.Type() break } } - if !datatypeFound { + if param.Validator == nil { return ErrUnknownDataType } diff --git a/internal/config/service.go b/internal/config/service.go index 0fc3164..87815d7 100644 --- a/internal/config/service.go +++ b/internal/config/service.go @@ -108,6 +108,12 @@ func (svc *Service) Validate(datatypes ...datatype.T) error { } } + // check output + err = svc.validateOutput(datatypes) + if err != nil { + return fmt.Errorf("field 'out': %w", err) + } + return nil } @@ -257,3 +263,52 @@ func (svc *Service) validateInput(types []datatype.T) error { return nil } + +func (svc *Service) validateOutput(types []datatype.T) error { + + // ignore no parameter + if svc.Output == nil || len(svc.Output) < 1 { + svc.Output = make(map[string]*Parameter, 0) + return nil + } + + // for each parameter + for paramName, param := range svc.Output { + if len(paramName) < 1 { + return fmt.Errorf("%s: %w", paramName, ErrIllegalParamName) + } + + // use param name if no rename + if len(param.Rename) < 1 { + param.Rename = paramName + } + + err := param.Validate(types...) + if err != nil { + return fmt.Errorf("%s: %w", paramName, err) + } + + if param.Optional { + return fmt.Errorf("%s: %w", paramName, ErrOptionalOption) + } + + // fail on name/rename conflict + for paramName2, param2 := range svc.Output { + // ignore self + if paramName == paramName2 { + continue + } + + // 3.2.1. Same rename field + // 3.2.2. Not-renamed field matches a renamed field + // 3.2.3. Renamed field matches name + if param.Rename == param2.Rename || paramName == param2.Rename || paramName2 == param.Rename { + return fmt.Errorf("%s: %w", paramName, ErrParamNameConflict) + } + + } + + } + + return nil +}