Skip to content

Package: MappingContext

MappingContext

nameinstructionbranchcomplexitylinemethod
MappingContext(JsonbContext)
M: 20 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
createParseClassModelFunction(ClassModel, ClassParser, JsonbContext)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getClassModel(Class)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getOrCreateClassModel(Class)
M: 67 C: 0
0%
M: 10 C: 0
0%
M: 6 C: 0
0%
M: 17 C: 0
0%
M: 1 C: 0
0%
lambda$createParseClassModelFunction$1(JsonbContext, ClassModel, ClassParser, Class)
M: 35 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
lambda$getOrCreateClassModel$0(Class)
M: 8 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0 which is available at
6: * http://www.eclipse.org/legal/epl-2.0,
7: * or the Eclipse Distribution License v. 1.0 which is available at
8: * http://www.eclipse.org/org/documents/edl-v10.php.
9: *
10: * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
11: */
12:
13: package org.eclipse.yasson.internal;
14:
15: import java.util.ArrayDeque;
16: import java.util.Deque;
17: import java.util.Objects;
18: import java.util.concurrent.ConcurrentHashMap;
19: import java.util.function.Function;
20:
21: import org.eclipse.yasson.internal.model.ClassModel;
22: import org.eclipse.yasson.internal.model.JsonbAnnotatedElement;
23: import org.eclipse.yasson.internal.model.customization.ClassCustomization;
24:
25: /**
26: * JSONB mappingContext. Created once per {@link jakarta.json.bind.Jsonb} instance. Represents a global scope.
27: * Holds internal model.
28: *
29: * Thread safe.
30: */
31: public class MappingContext {
32: private final JsonbContext jsonbContext;
33:
34: private final ConcurrentHashMap<Class<?>, ClassModel> classes = new ConcurrentHashMap<>();
35:
36: private final ClassParser classParser;
37:
38: /**
39: * Create mapping context which is scoped to jsonb runtime.
40: *
41: * @param jsonbContext Context. Required.
42: */
43: public MappingContext(JsonbContext jsonbContext) {
44: Objects.requireNonNull(jsonbContext);
45: this.jsonbContext = jsonbContext;
46: this.classParser = new ClassParser(jsonbContext);
47: }
48:
49: /**
50: * Searches for class model for given class. Returns the existing instance. Creates a new instance if
51: * it doesn't exist.
52: *
53: * @param clazz Class to search by or parse, not null.
54: * @return {@link ClassModel} for given class.
55: */
56: public ClassModel getOrCreateClassModel(Class<?> clazz) {
57: ClassModel classModel = classes.get(clazz);
58:• if (classModel != null) {
59: return classModel;
60: }
61:
62: Deque<Class<?>> newClassModels = new ArrayDeque<>();
63:• for (Class<?> classToParse = clazz; classToParse != Object.class; classToParse = classToParse.getSuperclass()) {
64:• if (classToParse == null) {
65: break;
66: }
67: newClassModels.push(classToParse);
68: }
69:• if (clazz == Object.class) {
70: return classes.computeIfAbsent(clazz, (c) -> new ClassModel(c, ClassCustomization.empty(), null, null));
71: }
72:
73: ClassModel parentClassModel = null;
74:• while (!newClassModels.isEmpty()) {
75: Class<?> toParse = newClassModels.pop();
76: parentClassModel = classes
77: .computeIfAbsent(toParse, createParseClassModelFunction(parentClassModel, classParser, jsonbContext));
78: }
79: return classes.get(clazz);
80: }
81:
82: private static Function<Class<?>, ClassModel> createParseClassModelFunction(ClassModel parentClassModel,
83: ClassParser classParser,
84: JsonbContext jsonbContext) {
85: return aClass -> {
86: JsonbAnnotatedElement<Class<?>> clsElement = jsonbContext.getAnnotationIntrospector().collectAnnotations(aClass);
87: ClassCustomization customization = jsonbContext.getAnnotationIntrospector()
88: .introspectCustomization(clsElement,
89:• parentClassModel == null
90: ? ClassCustomization.empty()
91: : parentClassModel.getClassCustomization());
92: // PolymorphismSupport configPolymorphism = jsonbContext.getConfigProperties().getPolymorphismSupport();
93: // if (configPolymorphism != null) {
94: // customization = mergeConfigAndAnnotationPolymorphism(configPolymorphism,
95: // configPolymorphism.getClassPolymorphism(aClass),
96: // customization,
97: // aClass);
98: // }
99: ClassModel newClassModel = new ClassModel(aClass,
100: customization,
101: parentClassModel,
102: jsonbContext.getConfigProperties().getPropertyNamingStrategy());
103:• if (!BuiltInTypes.isKnownType(aClass)) {
104: classParser.parseProperties(newClassModel, clsElement);
105: }
106: return newClassModel;
107: };
108: }
109:
110: // private static ClassCustomization mergeConfigAndAnnotationPolymorphism(PolymorphismSupport generalPolymorphism,
111: // Optional<Polymorphism> maybeClassPolymorphism,
112: // ClassCustomization customization,
113: // Class<?> aClass) {
114: // PolymorphismConfig polymorphismConfig = customization.getPolymorphismConfig();
115: // PolymorphismConfig.Builder polyConfigBuilder;
116: // if (polymorphismConfig != null) {
117: // polyConfigBuilder = PolymorphismConfig.builder().of(polymorphismConfig);
118: // } else {
119: // polyConfigBuilder = PolymorphismConfig.builder();
120: // maybeClassPolymorphism.ifPresent(classPolymorphism -> polyConfigBuilder
121: // .inherited(!classPolymorphism.getBoundClass().equals(aClass)));
122: // }
123: // generalPolymorphism.getKeyName().filter(s -> !s.isEmpty()).ifPresent(polyConfigBuilder::fieldName);
124: // generalPolymorphism.useClassNames().ifPresent(polyConfigBuilder::useClassNames);
125: // polyConfigBuilder.whitelistedPackages(generalPolymorphism.getWhitelistedPackages());
126: //
127: // maybeClassPolymorphism.ifPresent(classPolymorphism -> {
128: // classPolymorphism.getKeyName().filter(s -> !s.isEmpty()).ifPresent(polyConfigBuilder::fieldName);
129: // classPolymorphism.useClassNames().ifPresent(polyConfigBuilder::useClassNames);
130: // classPolymorphism.getFormat().ifPresent(polyConfigBuilder::format);
131: // classPolymorphism.getAliases().forEach(polyConfigBuilder::alias);
132: // polyConfigBuilder.whitelistedPackages(classPolymorphism.getWhitelistedPackages());
133: // });
134: // PolymorphismConfig polyConfigMerged = polyConfigBuilder.build();
135: // if (polyConfigMerged.getFieldName() == null || polyConfigMerged.getFieldName().isEmpty()) {
136: // throw new JsonbException("Polymorphism type field name cannot be null or empty: " + aClass);
137: // }
138: // return ClassCustomization.builder()
139: // .of(customization)
140: // .polymorphismConfig(polyConfigMerged)
141: // .build();
142: // }
143:
144: /**
145: * Search for class model, without parsing if not found.
146: *
147: * @param clazz Class to search by or parse, not null.
148: * @return Model of a class if found.
149: */
150: public ClassModel getClassModel(Class<?> clazz) {
151: return classes.get(clazz);
152: }
153:
154: }