Skip to content

Commit 1f12089

Browse files
committed
Refactor SchemaRegistry
1 parent bbff591 commit 1f12089

File tree

142 files changed

+577
-662
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+577
-662
lines changed

src/main/java/com/networknt/schema/Schema.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
/**
4242
* Used for creating a schema with validators for validating inputs. This is
43-
* created using {@link SchemaRegistry#getInstance(Version, Consumer)}
43+
* created using {@link SchemaRegistry#withDefaultDialect(Version, Consumer)}
4444
* and should be cached for performance.
4545
* <p>
4646
* This is the core of json constraint implementation. It parses json constraint

src/main/java/com/networknt/schema/SchemaRegistry.java

Lines changed: 87 additions & 197 deletions
Large diffs are not rendered by default.

src/main/java/com/networknt/schema/Specification.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
import java.util.Optional;
1919

20+
import com.networknt.schema.dialect.Dialect;
2021
import com.networknt.schema.dialect.DialectId;
22+
import com.networknt.schema.dialect.Dialects;
2123

2224
/**
2325
* The JSON Schema specification which defines the standard dialects.
@@ -95,4 +97,56 @@ public static Optional<Version> fromDialectId(String dialectId) {
9597
return Optional.empty();
9698
}
9799
}
100+
101+
/**
102+
* Gets the dialect given the specification version.
103+
*
104+
* @param version the schema specification version
105+
* @return the dialect or null if not found
106+
*/
107+
public static Dialect getDialect(Specification.Version version) {
108+
if (null == version) {
109+
return null;
110+
}
111+
switch (version) {
112+
case DRAFT_2020_12:
113+
return Dialects.getDraft202012();
114+
case DRAFT_2019_09:
115+
return Dialects.getDraft201909();
116+
case DRAFT_7:
117+
return Dialects.getDraft7();
118+
case DRAFT_6:
119+
return Dialects.getDraft6();
120+
case DRAFT_4:
121+
return Dialects.getDraft4();
122+
default:
123+
return null;
124+
}
125+
}
126+
127+
/**
128+
* Gets the dialect given the dialect id.
129+
*
130+
* @param version the schema specification version
131+
* @return the dialect or null if not found
132+
*/
133+
public static Dialect getDialect(String dialectId) {
134+
if (null == dialectId) {
135+
return null;
136+
}
137+
switch (dialectId) {
138+
case DialectId.DRAFT_2020_12:
139+
return Dialects.getDraft202012();
140+
case DialectId.DRAFT_2019_09:
141+
return Dialects.getDraft201909();
142+
case DialectId.DRAFT_7:
143+
return Dialects.getDraft7();
144+
case DialectId.DRAFT_6:
145+
return Dialects.getDraft6();
146+
case DialectId.DRAFT_4:
147+
return Dialects.getDraft4();
148+
default:
149+
return null;
150+
}
151+
}
98152
}

src/main/java/com/networknt/schema/SpecificationVersionDetector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public static Optional<Version> detectOptionalVersion(JsonNode jsonNode, boolean
7575
return Optional.ofNullable(jsonNode.get(SCHEMA_TAG)).map(schemaTag -> {
7676

7777
String schemaTagValue = schemaTag.asText();
78-
String schemaUri = SchemaRegistry.normalizeMetaSchemaUri(schemaTagValue);
78+
String schemaUri = SchemaRegistry.normalizeDialectId(schemaTagValue);
7979

8080
if (throwIfUnsupported) {
8181
return Version.fromDialectId(schemaUri)
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024 the original author or authors.
2+
* Copyright (c) 2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,33 +15,32 @@
1515
*/
1616
package com.networknt.schema.dialect;
1717

18+
import java.util.function.Function;
19+
1820
import com.networknt.schema.Error;
1921
import com.networknt.schema.InvalidSchemaException;
2022
import com.networknt.schema.SchemaRegistry;
2123
import com.networknt.schema.SchemaValidatorsConfig;
2224

23-
/**
24-
* A {@link DialectRegistry} that does not meta-schemas that aren't
25-
* explicitly configured in the {@link SchemaRegistry}.
26-
*/
27-
public class DisallowUnknownDialectFactory implements DialectRegistry {
28-
@Override
29-
public Dialect getDialect(String dialectId, SchemaRegistry schemaFactory, SchemaValidatorsConfig config) {
30-
throw new InvalidSchemaException(Error.builder()
31-
.message("Unknown dialect ''{0}''. Only dialects that are explicitly configured can be used.")
32-
.arguments(dialectId).build());
25+
public class BasicDialectRegistry implements DialectRegistry {
26+
private Function<String, Dialect> dialects;
27+
28+
public BasicDialectRegistry(Function<String, Dialect> dialects) {
29+
this.dialects = dialects;
3330
}
3431

35-
private static class Holder {
36-
private static final DisallowUnknownDialectFactory INSTANCE = new DisallowUnknownDialectFactory();
32+
public BasicDialectRegistry(Dialect dialect) {
33+
this.dialects = dialectId -> dialect.getIri().equals(dialectId) ? dialect : null;
3734
}
3835

39-
/**
40-
* Gets the instance of {@link DisallowUnknownDialectFactory}.
41-
*
42-
* @return the json meta schema factory
43-
*/
44-
public static DisallowUnknownDialectFactory getInstance() {
45-
return Holder.INSTANCE;
36+
@Override
37+
public Dialect getDialect(String dialectId, SchemaRegistry schemaRegistry, SchemaValidatorsConfig config) {
38+
Dialect dialect = dialects.apply(dialectId);
39+
if (dialect != null) {
40+
return dialect;
41+
}
42+
throw new InvalidSchemaException(Error.builder()
43+
.message("Unknown dialect ''{0}''. Only dialects that are explicitly configured can be used.")
44+
.arguments(dialectId).build());
4645
}
4746
}

src/main/java/com/networknt/schema/dialect/DefaultDialectRegistry.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import java.util.Map;
1919
import java.util.Map.Entry;
20+
import java.util.concurrent.ConcurrentHashMap;
21+
import java.util.concurrent.ConcurrentMap;
2022

2123
import com.fasterxml.jackson.databind.JsonNode;
2224
import com.networknt.schema.Error;
@@ -32,13 +34,16 @@
3234
* Default {@link DialectRegistry}.
3335
*/
3436
public class DefaultDialectRegistry implements DialectRegistry {
37+
private final ConcurrentMap<String, Dialect> dialects = new ConcurrentHashMap<>();
38+
3539
@Override
3640
public Dialect getDialect(String dialectId, SchemaRegistry schemaFactory, SchemaValidatorsConfig config) {
3741
// Is it a well-known dialect?
38-
return Specification.Version.fromDialectId(dialectId).map(SchemaRegistry::checkVersion).orElseGet(() -> {
39-
// Custom dialect
40-
return loadDialect(dialectId, schemaFactory, config);
41-
});
42+
Dialect dialect = Specification.getDialect(dialectId);
43+
if (dialect != null) {
44+
return dialect;
45+
}
46+
return dialects.computeIfAbsent(dialectId, id -> loadDialect(id, schemaFactory, config));
4247
}
4348

4449
protected Dialect loadDialect(String iri, SchemaRegistry schemaFactory, SchemaValidatorsConfig config) {

src/main/java/com/networknt/schema/dialect/DialectRegistry.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ public interface DialectRegistry {
2929
* Gets the dialect given the dialect id which is the IRI that indicates the
3030
* meta-schema that can be used to validate the schema conforms to the dialect.
3131
*
32-
* @param dialectId the dialect id of the dialect which IRI that indicates
33-
* the meta-schema that can be used to validate the schema
34-
* conforms to the dialect
35-
* @param schemaFactory the schema factory
36-
* @param config the config
32+
* @param dialectId the dialect id of the dialect which IRI that indicates
33+
* the meta-schema that can be used to validate the schema
34+
* conforms to the dialect
35+
* @param schemaRegistry the schema registry to fetch and load unknown dialect's
36+
* meta-schema
37+
* @param config the config
3738
* @return the dialect
3839
*/
39-
Dialect getDialect(String dialectId, SchemaRegistry schemaFactory, SchemaValidatorsConfig config);
40+
Dialect getDialect(String dialectId, SchemaRegistry schemaRegistry, SchemaValidatorsConfig config);
4041
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.networknt.schema.serialization;
18+
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
22+
import com.fasterxml.jackson.databind.JsonNode;
23+
import com.fasterxml.jackson.databind.ObjectMapper;
24+
import com.networknt.schema.InputFormat;
25+
26+
/**
27+
* BasicJsonNodeReader.
28+
*/
29+
public class BasicJsonNodeReader implements JsonNodeReader {
30+
private static class Holder {
31+
private static final BasicJsonNodeReader INSTANCE = new BasicJsonNodeReader();
32+
}
33+
34+
public static BasicJsonNodeReader getInstance() {
35+
return Holder.INSTANCE;
36+
}
37+
38+
protected BasicJsonNodeReader() {
39+
}
40+
41+
@Override
42+
public JsonNode readTree(String content, InputFormat inputFormat) throws IOException {
43+
return getObjectMapper(inputFormat).readTree(content);
44+
}
45+
46+
@Override
47+
public JsonNode readTree(InputStream content, InputFormat inputFormat) throws IOException {
48+
return getObjectMapper(inputFormat).readTree(content);
49+
}
50+
51+
/**
52+
* Gets the object mapper for the input format.
53+
*
54+
* @param inputFormat the input format
55+
* @return the object mapper
56+
*/
57+
protected ObjectMapper getObjectMapper(InputFormat inputFormat) {
58+
if (InputFormat.JSON.equals(inputFormat)) {
59+
return JsonMapperFactory.getInstance();
60+
} else if (InputFormat.YAML.equals(inputFormat)) {
61+
return YamlMapperFactory.getInstance();
62+
}
63+
throw new IllegalArgumentException("Unsupported input format "+inputFormat);
64+
}
65+
66+
}

src/test/java/com/networknt/schema/AbstractJsonSchemaTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ private JsonNode getJsonNodeFromPath(String dataPath) {
6060

6161
private Schema getJsonSchema(JsonNode schemaNode) {
6262
return SchemaRegistry
63-
.getInstance(SpecificationVersionDetector.detectOptionalVersion(schemaNode, false).orElse(DEFAULT_VERSION_FLAG))
63+
.withDefaultDialect(SpecificationVersionDetector.detectOptionalVersion(schemaNode, false).orElse(DEFAULT_VERSION_FLAG))
6464
.getSchema(schemaNode);
6565
}
6666

src/test/java/com/networknt/schema/AbstractJsonSchemaTestSuite.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ public InputStreamSource getSchema(AbsoluteIri absoluteIri) {
202202
}
203203
};
204204
Version specVersion = detectVersion(testCase.getSchema(), testCase.getSpecification(), defaultVersion, false);
205-
SchemaRegistry base = SchemaRegistry.getInstance(specVersion);
205+
SchemaRegistry base = SchemaRegistry.withDefaultDialect(specVersion);
206206
return SchemaRegistry
207207
.builder(base)
208208
.schemaMappers(schemaMappers -> schemaMappers

0 commit comments

Comments
 (0)