Loading…
Loading…
Learn how the RegexExampleGenerator creates representative example strings from XSD patterns, handling length constraints and common regex constructs.
The RegexExampleGenerator is a utility that generates a single, representative string value that conforms to a given regular expression.
This component solves a specific problem encountered during the import of API contracts (e.g., from WSDL files). When a contract field specifies a data type (like xsd:int) and a constraining regular expression (xsd:pattern), standard example generators might produce a value that satisfies the type (e.g., 1) but not the pattern (e.g., a YYYYMMDD format). This mismatch causes contract import to fail with a validation error (S2R-ADM-0612), blocking an otherwise valid API definition.
The RegexExampleGenerator is invoked by the contract import service to seed example values for fields with xsd:pattern facets. It takes a regular expression and optional length constraints as input and produces a matching string. The calling service must then re-validate this generated string against all other facets of the field (such as numeric ranges or total digit counts) before use.
The generator processes a regular expression in two main phases: parsing the pattern into an internal structure and then rendering that structure into an output string according to specific policies.
flowchart TD
A[API Contract with xsd:pattern] --> B(Regex Example Generator);
B -- 1. Parse Regex --> C(Internal Representation - AST);
C -- 2. Render with Policies --> D{Apply Quantifier & Length Policies};
D -- Smallest non-empty count --> E;
D -- Respect maxLength budget --> E;
D -- Grow toward targetLength --> E(Generated Example String);
E --> F{Is generation successful?};
F -- Yes --> G[Return generated string];
F -- No --> H[Return empty];^ (start of string) and $ (end of string) anchors.pattern facets:
a, 1).)\d, \w, \s, \D, \W, \S) and literal escapes (\-, \.)[...]) and negated character classes ([^...]), including ranges ([a-z])(...)) and non-capturing ((?:...))|)?, *, +, {m}, {m,}, {m,n})NOTE
The generator intentionally does not support advanced regex features like backreferences or lookarounds, as these are not part of the XSD pattern specification. If a pattern contains unsupported syntax, parsing will fail, and no example will be generated.
If the parser cannot process the entire input string, it is considered a syntax error, and the generator returns an empty result.
Once the AST is built, the generator traverses the tree to render the final string. The rendering process is guided by a set of deterministic policies to produce a useful, representative example.
To generate a meaningful example, the generator follows a "smallest non-empty" rule for quantifiers.
min value).* or ?), it renders one repetition instead of zero. This prevents the generation of an empty string, which, while technically matching the pattern, is often an invalid value for a typed field (e.g., a number).64 to prevent excessive output from unbounded quantifiers (e.g., a{5,}).The generate(String, Integer, Integer) method provides length-aware generation to satisfy co-declared minLength and maxLength facets.
maxLength: This acts as a hard budget. If a repetition would cause the generated string to exceed this length, the number of repetitions is reduced, potentially down to the quantifier's minimum. Optional groups that do not fit within the budget are omitted.targetLength: This acts as a preferred length. The generator will increase the number of repetitions for a group beyond its minimum to approach this target, as long as the maxLength budget is not exceeded.When a pattern allows for multiple characters, the generator makes a deterministic choice:
[...]: It prefers a digit, then a letter, then the first character defined in the class.[^...]: It selects the first character from the pool 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz that is not in the negated set.0 for \d, A for \w)..: It renders the character A.|)For alternation, the generator first attempts to use the first branch in the sequence (e.g., a in a|b). If the minimum length of the first branch exceeds the available length budget, it will iterate through subsequent branches to find one that fits.
Consider a field PelephoneNo with the following constraints in an API contract:
0\d([\d]{0,1})([-]{0,1})\d{7}minLength: 9maxLength: 10A length-blind generation might produce "000-0000000". This string is 11 characters long, which matches the pattern but violates the maxLength of 10. This would cause the contract import to fail.
By using the length-aware generator, we can produce a compliant example.
// The pattern for the field
String pattern = "0\\d([\\d]{0,1})([-]{0,1})\\d{7}";
// The length constraints from the contract
Integer minLength = 9; // Used as the targetLength
Integer maxLength = 10;
// Generate the example
Optional<String> example = RegexExampleGenerator.generate(pattern, minLength, maxLength);
// Expected result: Optional.of("0000000000")
// This string is 10 characters long, satisfying both the pattern and the maxLength.
// The generator shrinks the optional groups (the extra digit and the hyphen) to fit the budget.
The RegexExampleGenerator class exposes two static methods for generating examples.
generate(String rawPattern)Generates a representative string from a regular expression without considering external length constraints.
| Parameter | Type | Description |
|---|---|---|
rawPattern | String | The regular expression pattern to process. |
Returns: An Optional<String> containing the generated example. Returns Optional.empty() if the pattern is null, blank, or contains unsupported constructs.
generate(String rawPattern, Integer targetLength, Integer maxLength)Generates a representative string that attempts to adhere to minLength and maxLength constraints.
| Parameter | Type | Description |
|---|---|---|
rawPattern | String | The regular expression pattern to process. |
targetLength | Integer | The desired length for the output string, typically corresponding to a field's minLength. The generator will grow repetitions to meet this target. A null or non-positive value disables this. |
maxLength | Integer | The maximum permitted length for the output string. This is a hard budget. Repetitions are shrunk to fit. A null or non-positive value indicates no upper bound. |
Returns: An Optional<String> containing the generated example. Returns Optional.empty() if the pattern is null, blank, contains unsupported constructs, or is unsatisfiable within the given constraints. With both targetLength and maxLength set to null, the output is identical to generate(String).
The generate methods return Optional.empty() to signal that an example could not be produced. This allows the calling service to fall back to a different example generation strategy. This can happen for several reasons:
rawPattern is null or consists only of whitespace.( or character class [.[^...] is unsatisfiable because it excludes all characters in the generator's fallback pool.IMPORTANT
Callers must always re-validate the string produced by this generator against the field's full contract.
The generator guarantees that the output string will match the subset of regex syntax it supports. It does not guarantee that the string will satisfy other, co-declared contract facets. For example, for a pattern like \d{5} on an xsd:int field with a maxInclusive bound of 50000, the generator might produce "00000" or "11111", but it is not aware of the numeric bound. The caller is responsible for this final validation step.
S2R-ADM-0612 Error on ImportThe S2R-ADM-0612 error ("value does not match pattern") is precisely what this generator is designed to prevent. If you still encounter this error on contract import for a field with a pattern, it may indicate:
RegexExampleGenerator failed to produce a value for the pattern (see "Generation Returns Empty"), and the system fell back to a non-compliant default example.