Loading…
Loading…
Generate example string values that satisfy schema constraints such as pattern, minLength, and maxLength. Ensures API specification examples are valid.
The ConstrainedStringSampler is a stateless utility component that generates example string values satisfying a given set of schema constraints. It takes a base string and schema facets—such as pattern, minLength, maxLength, and length—and produces a new string that complies with all of them.
This component solves a critical problem in API contract generation: ensuring that example values within a specification are themselves valid according to the schema they document. Without this, an API gateway or validation tool might reject a specification because its own examples violate its rules (e.g., an example string is longer than the specified maxLength).
ConstrainedStringSampler is a shared utility used by other internal components, such as ContractExampleService (for general contract example generation) and OpenApiService (for OpenAPI specification generation), to ensure consistent and valid example data.
The ConstrainedStringSampler operates through a single static method, sample, which follows a deterministic process of candidate generation and validation to find a suitable example string.
flowchart TD
subgraph "Input"
A[baseValue, pattern, length constraints]
end
subgraph "Processing"
B{Any constraints present?}
A --> B
B -- No --> C[Return baseValue]
B -- Yes --> D[Resolve target length]
D --> E[Generate candidate strings]
subgraph "Candidate Generation Order"
direction LR
E1[1. Pattern-based heuristics]
E2[2. Length-adjusted baseValue]
E3[3. Generic fallbacks (e.g., "111", "AAA")]
E4[4. Regex-based generator (last resort)]
end
E --> E1 --> E2 --> E3 --> E4
F{Loop through candidates}
E4 --> F
subgraph "Validation"
G{Is candidate valid?}
H[Check length constraints]
I[Check pattern match]
G --> H --> I
end
F -- For each candidate --> G
I -- Yes --> J[Return valid candidate]
I -- No --> F
end
subgraph "Output"
F -- No valid candidate found --> K[Return length-adjusted baseValue as final fallback]
C --> L[Final String]
J --> L
K --> L
endThe process is as follows:
Input & Initial Check: The sample method receives a baseValue string and several nullable constraint parameters (pattern, exactLength, minLength, maxLength). If no constraints are provided, it immediately returns the original baseValue.
Resolve Target Length: If constraints are present, the method first determines a targetLength for the output string. It prioritizes exactLength, then considers minLength and maxLength in relation to the baseValue's length or a fallbackLength. The resulting length is always at least 1.
Generate Candidates: The sampler creates an ordered list of potential example strings. The order is crucial, as the first valid candidate is always chosen.
pattern is provided, it first attempts to generate simple, predictable strings based on common regex forms like \d{5}, [A-Z]+, or [0-9]{1,9}. This is handled by the patternCandidates method, which produces strings like "11111" or "AAAA". It includes a generic handler for any pattern of the form [character-class]{quantifier}.baseValue is adjusted to fit the targetLength and added to the list.'1' characters, a string of repeating 'A' characters, and an alternating alphanumeric string (e.g., "A1A1A").RegexExampleGenerator to produce a matching string. This is added to the end of the candidate list to ensure that simpler, more readable heuristic-based examples are preferred.Validate and Return: The method iterates through the list of candidates. For each one, it checks:
exactLength, minLength, and maxLength.pattern is specified, that the string matches the pattern (using ContractPatternValidator).The first candidate to pass all checks is immediately returned.
Final Fallback: If no candidate in the list satisfies all constraints, the method returns the baseValue adjusted for length, even if it does not match the pattern. This ensures the sampler always returns a string that at least meets the length requirements.
Consider generating an example for a field with a maxLength of 10, where the unconstrained sample value is "sample-SHILDA" (13 characters).
The ConstrainedStringSampler would be invoked as follows:
String result = ConstrainedStringSampler.sample(
"sample-SHILDA", // baseValue
null, // pattern
null, // exactLength
null, // minLength
10, // maxLength
8 // fallbackLength
);
Expected Result: "sample-SHI"
Explanation:
sample method identifies that maxLength is 10.targetLength is resolved to 10, because the base value's length (13) is greater than the maxLength.baseValue adjusted for length. The adjustToLength function truncates "sample-SHILDA" to the first 10 characters."sample-SHIL", is validated. Its length (10) is not greater than maxLength (10), so it passes the length check.pattern was specified, this candidate is considered valid."sample-SHIL" as the result.The component exposes a single public static method.
sampleGenerates a string that satisfies the supplied schema constraints.
public static String sample(
String baseValue,
String pattern,
Integer exactLength,
Integer minLength,
Integer maxLength,
int fallbackLength
)
| Parameter | Type | Required | Description |
|---|---|---|---|
baseValue | String | No | The unconstrained candidate string (e.g., sample-fieldName). Used as-is if no constraints are present. Can be null. |
pattern | String | No | The regular expression pattern (XSD/OpenAPI pattern facet) the string must match. Can be null or blank. |
exactLength | Integer | No | The exact required length of the string (xs:length facet). If set, this overrides minLength and maxLength. Can be null. |
minLength | Integer | No | The minimum required length of the string (xs:minLength facet). Can be null. |
maxLength | Integer | No | The maximum required length of the string (xs:maxLength facet). Can be null. |
fallbackLength | int | Yes | The target length to use when baseValue is blank and no exactLength or minLength constraint provides a floor. Must be > 0. |
A String that satisfies as many of the provided constraints as possible. In cases where no candidate can be found to satisfy all constraints (e.g., a complex pattern), it returns a best-effort string that meets the length requirements.
The ConstrainedStringSampler is designed to always return a string and does not throw exceptions. However, the output may sometimes be unexpected.
Symptom: The generated example does not match the pattern constraint.
pattern and the length constraints. In this scenario, its final fallback behavior is to return a length-adjusted version of the baseValue (or a default like "value"), which may not match the pattern. This prioritizes providing a value that fits length constraints over one that fits the pattern.Symptom: The generated example is a simple repeating string like "11111" or "AAAAA".
RegexExampleGenerator as a last resort if none of the simpler candidates are valid.ContractExampleService: A service that uses this sampler to generate examples for API contracts.OpenApiService: A service that uses this sampler to generate examples within OpenAPI specifications.ContractPatternValidator: The internal utility used to check if a candidate string matches a given regular expression.RegexExampleGenerator: An internal utility used to generate example strings from complex regular expressions when simpler heuristics fail.