All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Jackson moves from 2.21.5 to 2.22.2, with
jackson-annotationsfrom 2.21 to 2.22, the version the 2.22.2 bill of materials pairs it with. jakarta.annotation-apimoves from 2.1.1 to 3.0.0. The major bump is on the specification, not on anything the SDK relies on: 3.0.0 is still compiled for Java 11, and the only class it drops,jakarta.annotation.ManagedBean, is not one the generated code annotates with. The Java 11 baseline and the published API are unchanged.
1.1.0 - 2026-08-08
The static RegexSolver becomes an instantiable RegexSolverClient, with AsyncRegexSolverClient beside it, every operation moves from Term onto the client, and the SDK covers the whole API rather than the seven endpoints it knew about. See Compatibility below.
RegexSolverClient.builder()andAsyncRegexSolverClient.builder(), takingapiToken,baseUrl,autoBatchandmaxTermsPerRequest. Several clients, each with its own token, can exist in one process; the synchronous one blocks on the asynchronous one, whose operations returnCompletableFuture.- The operations the API gained since 1.0.2:
complement,concat,determinize,repeat,getCardinality,getDot,getLength,isEmpty,isEmptyString,isTotal,isDeterministicandgetAccountLimits. OperationOptionson every operation that returns a term, carryingresponseFormat(REGEX,FAIRorANY),deterministicandexecutionTimeout. Analyze operations anddeterminizehonourexecutionTimeoutalone.generateStrings(term, limit, offset, options), which pages through the language instead of returning a fixed count from the start, withpathOrder,characterOrder,seed,minLength,maxLengthandcharsetinGenerateStringsOptions. Paging is only consistent over a deterministic FAIR, hencedeterminize()andisDeterministic().Term.matches(str), evaluated locally withjava.util.regex— matched against the whole input, compiled withPattern.DOTALL— rather than by the API. It throws on a FAIR whose pattern is not known yet, and returnsfalsefor the empty language, which the engine writes as[].- An unchecked exception hierarchy under
RegexSolverException, so a caller can catch the case it handles instead of matching on a message.ApiExceptioncarriesstatusCode,errorCodeandbody, and splits per status down toRegexSyntaxException,TimeoutExceededException,QuotaExceededExceptionand the rest. - A rate limiter, shared by every client holding the same token: a 429 sets a deadline from
Retry-After, requests wait for it, and the operation is retried within a five-minute budget. - Automatic batching:
concat,intersectionandunionsplit a call carrying more terms than the account allows per request and fold the results back into one, each constituent request counting against the monthly quota. Disable withautoBatch(false), or lower the split withmaxTermsPerRequest. - A per-term cache of what the API has already returned — cardinality, length, pattern, dot, and the empty, empty-string, total and deterministic flags — so asking twice costs one request.
Term.serialize()/Term.deserialize(), round-tripping theregex=<pattern>/fair=<payload>form, plusequals(),hashCode(),getValue()andtoDto()/fromDto().AccountLimits,Cardinality(Integer,BigInteger,Infinite),Length,ResponseFormat,PathOrderandCharacterOrderas exported models.- A
module-info.java, so the SDK is a named module,com.regexsolver.api, on the module path. generate-api.sh, which regeneratessrc/main/java/com/regexsolver/api/generated/from the specification the API publishes athttps://api.regexsolver.com/openapi.json;.openapi-generator-ignoreprotects the hand-written files.- CI running the build and the tests on Java 11, 17 and 21, and a workflow publishing to Maven Central on a
v*tag. - A
CHANGELOG.md, this file, a pull request template, and Dependabot updates.
- The HTTP layer is code generated from the OpenAPI specification on
java.net.httpand Jackson, instead of hand-written Retrofit and OkHttp calls, withcom.regexsolver.apithe hand-written surface overcom.regexsolver.api.generated. Termis an abstract class withRegexTermandFairTermsubclasses,regex()andfair()unchanged.getPattern()andgetFair()returnOptional<String>, empty when the other format has not been resolved yet; resolving a pattern isclient.getPattern(term).- The tests are JUnit 5 with Mockito and AssertJ, driving the clients over the generated API, instead of JUnit 4 matching requests with
mockwebserverand loading fixtures fromsrc/test/resources/.
RegexSolver, with its staticinitialize(), andRegexSolverApiWrapper.- The operation methods on
Term:intersection(),union(),subtraction(),isEquivalentTo(),isSubsetOf(),generateStrings()andgetDetails(). Details, with thecom.regexsolver.api.dtopackage, and thecom.regexsolver.api.exceptionpackage, withApiErrorandMissingAPITokenException.
RegexSolver.initialize(token)becomesRegexSolverClient.builder().apiToken(token).build(), and a term method becomes a client method taking the terms as arguments:term1.union(term2)isclient.union(term1, term2),isEquivalentToisequivalent,isSubsetOfissubset,subtractionisdifference, andgetDetailsisgetCardinality(),getLength(),isEmpty()andisTotal().ApiErroris gone; catchApiException, or the subclass for the case at hand, and branch ongetStatusCode(). Since nothing is checked any more,catch (IOException | ApiError e)around a call no longer compiles.- The endpoints moved from
https://api.regexsolver.com/api/*to/v1/*, and/api/analyze/detailsis split into one/v1/analyze/*endpoint per property. 1.1.0 is the lowest version that works against the API. - The serialized
regex=/fair=form is unchanged, so a term persisted by 1.0.x deserializes.
1.0.2 - 2024-08-08
- The
User-Agentheader reports the version being released rather than the next one.
1.0.1 - 2024-07-27
RegexSolver, withinitialize(token)andinitialize(token, baseUrl).RegexSolverApiWrapperis package-private, so the SDK could not be initialized from outside its own package.
1.0.0 - 2024-07-27
Initial release.