diff --git a/docs/templates/paris/stakeholder.json b/docs/templates/paris/stakeholder.json index 38de76e2cb8045027109bd39247929ada550402a..1faa9b5bbad42bfcea997473b47175703d13b21e 100644 --- a/docs/templates/paris/stakeholder.json +++ b/docs/templates/paris/stakeholder.json @@ -66,9 +66,10 @@ "kann", "wird" ], - "size": "small", - "optional": true, - "ignoreMissingWhenOptional": true + "extra": { + "allowOthers": true + }, + "size": "small" }, "begruendung": { "name": "Begründung", diff --git a/src/app/eiffel/parser.go b/src/app/eiffel/parser.go index c0bbc2e01d77b4ce04fde937217478adb447379a..9c6fb28434d04e5865fdedf2404751b031e8e33a 100644 --- a/src/app/eiffel/parser.go +++ b/src/app/eiffel/parser.go @@ -494,12 +494,21 @@ func (p EqualsRuleParser) DisplayType(rule BasicRule) TemplateDisplayType { // Parse implements the RuleParser interface for the EqualsAnyRuleParser. It is used to parse rules of the type 'equalsAny'. // The equalsAny rule expects a slice of strings as value, converts each string to lowercase and compares it to the lowercase segment's value. // If any of the values are equal, no parsing error is reported. +// +// The equalsAny rule has an extra property 'allowOthers' that can be set to true or false. +// If set to true, the equalsAny rule will allow any other value than the ones defined in the rule's value, as long as the segment's value is not empty. +// For allowing empty use the optional + ignoreMissingWhenOptional flags. func (p EqualsAnyRuleParser) Parse(ctx context.Context, rule BasicRule, segment parser.ParsingSegment) ([]parser.ParsingLog, error) { rv, err := toStringSlice(rule.Value) if err != nil { return nil, RuleInvalidValueError{Rule: &rule, Msg: err.Error()} } + allowOthers, ok := rule.Extra["allowOthers"].(bool) + if !ok { + allowOthers = false + } + segmentValue := strings.ToLower(segment.Value) for _, v := range rv { ruleValue := strings.ToLower(v) @@ -509,6 +518,10 @@ func (p EqualsAnyRuleParser) Parse(ctx context.Context, rule BasicRule, segment } } + if allowOthers && segmentValue != "" { + return nil, nil + } + return []parser.ParsingLog{{ Segment: &segment, Level: parser.ParsingLogLevelError, @@ -518,8 +531,13 @@ func (p EqualsAnyRuleParser) Parse(ctx context.Context, rule BasicRule, segment } // Validate implements the RuleParser interface for the EqualsAnyRuleParser. It is used to validate rules of the type 'equalsAny'. -// The equalsAny rule expects a slice of strings as value. +// The equalsAny rule expects a slice of strings as value. If the 'allowOthers' extra property is set it expects a boolean value. func (p EqualsAnyRuleParser) Validate(v validation.V, rule BasicRule) []error { + allowExtra, ok := rule.Extra["allowOthers"] + if _, aeOk := allowExtra.(bool); ok && !aeOk { + return []error{RuleInvalidValueError{Rule: &rule, Msg: "eiffel.parser.equals-any.invalid-allow-others"}} + } + _, err := toStringSlice(rule.Value) if err == nil { return nil diff --git a/translations/de.json b/translations/de.json index f74b45df9732d67a511d9eafdaa5650906c0c4e1..04d71a78ded25fa28fa6460d5f84262188bc9ae8 100644 --- a/translations/de.json +++ b/translations/de.json @@ -113,7 +113,10 @@ "not-a-string": "Der Wert \"value\" für die Regel \"{{ .rule }}\" vom Typ \"{{ .type }}\" sollte aus einer Zeichenkette oder einer Liste an Zeichenketten bestehen, jedoch wurde ein anderer Typ gefunden. Bitte überprüfen Sie die Schablonen-Dokumentation." }, "equals.error": "Erwarteter Wert: \"{{ .expected }}\".", - "equals-any.error": "Erwarteter Wert: {{ .expected }}." + "equals-any": { + "error": "Erwarteter Wert: {{ .expected }}.", + "invalid-allow-others": "Der Wert \"allowOthers\" für die Regel \"{{ .rule }}\" vom Typ \"{{ .type }}\" ist ungültig. Es wird ein Boolean (true/false) erwartet." + } }, "elicitation": { "call-to-action": "Anforderungen mit EIFFEL erfassen",