• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Adyen / adyen-java-api-library / #3755

13 Nov 2024 12:20PM CUT coverage: 12.206%. First build
#3755

push

web-flow
Merge 01fcec3b9 into 964c7f7a4

12945 of 106057 relevant lines covered (12.21%)

0.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/com/adyen/model/acswebhooks/JSON.java
1
package com.adyen.model.acswebhooks;
2

3
import com.adyen.serializer.ByteArraySerializer;
4
import com.adyen.serializer.ByteArrayDeserializer;
5
import com.fasterxml.jackson.annotation.*;
6
import com.fasterxml.jackson.databind.*;
7
import com.fasterxml.jackson.databind.json.JsonMapper;
8
import com.fasterxml.jackson.databind.module.SimpleModule;
9
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
10
import com.adyen.model.acswebhooks.*;
11

12
import java.text.DateFormat;
13
import java.util.HashMap;
14
import java.util.HashSet;
15
import java.util.Map;
16
import java.util.Set;
17
import jakarta.ws.rs.core.GenericType;
18
import jakarta.ws.rs.ext.ContextResolver;
19

20
public class JSON implements ContextResolver<ObjectMapper> {
21
  private static ObjectMapper mapper;
22

23
  public JSON() {
×
24
    mapper = new ObjectMapper();
×
25
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
×
26
    JsonMapper.builder().configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false);
×
27
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
×
28
    mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true);
×
29
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
×
30
    mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
×
31
    mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
×
32
    mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
×
33
    mapper.registerModule(new JavaTimeModule());
×
34
    // Custom ByteSerializer
35
    SimpleModule simpleModule = new SimpleModule();
×
36
    simpleModule.addSerializer(byte[].class, new ByteArraySerializer());
×
37
    simpleModule.addDeserializer(byte[].class, new ByteArrayDeserializer());
×
38
    mapper.registerModule(simpleModule);
×
39
  }
×
40

41
  /**
42
   * Set the date format for JSON (de)serialization with Date properties.
43
   * @param dateFormat Date format
44
   */
45
  public void setDateFormat(DateFormat dateFormat) {
46
    mapper.setDateFormat(dateFormat);
×
47
  }
×
48

49
  @Override
50
  public ObjectMapper getContext(Class<?> type) {
51
    return mapper;
×
52
  }
53

54
  /**
55
   * Get the object mapper
56
   *
57
   * @return object mapper
58
   */
59
  public static ObjectMapper getMapper() { return mapper; }
×
60

61
  /**
62
   * Returns the target model class that should be used to deserialize the input data.
63
   * The discriminator mappings are used to determine the target model class.
64
   *
65
   * @param node The input data.
66
   * @param modelClass The class that contains the discriminator mappings.
67
   */
68
  public static Class<?> getClassForElement(JsonNode node, Class<?> modelClass) {
69
    ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass);
×
70
    if (cdm != null) {
×
71
      return cdm.getClassForElement(node, new HashSet<Class<?>>());
×
72
    }
73
    return null;
×
74
  }
75

76
  /**
77
   * Helper class to register the discriminator mappings.
78
   */
79
  private static class ClassDiscriminatorMapping {
80
    // The model class name.
81
    Class<?> modelClass;
82
    // The name of the discriminator property.
83
    String discriminatorName;
84
    // The discriminator mappings for a model class.
85
    Map<String, Class<?>> discriminatorMappings;
86

87
    // Constructs a new class discriminator.
88
    ClassDiscriminatorMapping(Class<?> cls, String propertyName, Map<String, Class<?>> mappings) {
×
89
      modelClass = cls;
×
90
      discriminatorName = propertyName;
×
91
      discriminatorMappings = new HashMap<String, Class<?>>();
×
92
      if (mappings != null) {
×
93
        discriminatorMappings.putAll(mappings);
×
94
      }
95
    }
×
96

97
    // Return the name of the discriminator property for this model class.
98
    String getDiscriminatorPropertyName() {
99
      return discriminatorName;
×
100
    }
101

102
    // Return the discriminator value or null if the discriminator is not
103
    // present in the payload.
104
    String getDiscriminatorValue(JsonNode node) {
105
      // Determine the value of the discriminator property in the input data.
106
      if (discriminatorName != null) {
×
107
        // Get the value of the discriminator property, if present in the input payload.
108
        node = node.get(discriminatorName);
×
109
        if (node != null && node.isValueNode()) {
×
110
          String discrValue = node.asText();
×
111
          if (discrValue != null) {
×
112
            return discrValue;
×
113
          }
114
        }
115
      }
116
      return null;
×
117
    }
118

119
    /**
120
     * Returns the target model class that should be used to deserialize the input data.
121
     * This function can be invoked for anyOf/oneOf composed models with discriminator mappings.
122
     * The discriminator mappings are used to determine the target model class.
123
     *
124
     * @param node The input data.
125
     * @param visitedClasses The set of classes that have already been visited.
126
     */
127
    Class<?> getClassForElement(JsonNode node, Set<Class<?>> visitedClasses) {
128
      if (visitedClasses.contains(modelClass)) {
×
129
        // Class has already been visited.
130
        return null;
×
131
      }
132
      // Determine the value of the discriminator property in the input data.
133
      String discrValue = getDiscriminatorValue(node);
×
134
      if (discrValue == null) {
×
135
        return null;
×
136
      }
137
      Class<?> cls = discriminatorMappings.get(discrValue);
×
138
      // It may not be sufficient to return this cls directly because that target class
139
      // may itself be a composed schema, possibly with its own discriminator.
140
      visitedClasses.add(modelClass);
×
141
      for (Class<?> childClass : discriminatorMappings.values()) {
×
142
        ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass);
×
143
        if (childCdm == null) {
×
144
          continue;
×
145
        }
146
        if (!discriminatorName.equals(childCdm.discriminatorName)) {
×
147
          discrValue = getDiscriminatorValue(node);
×
148
          if (discrValue == null) {
×
149
            continue;
×
150
          }
151
        }
152
        if (childCdm != null) {
×
153
          // Recursively traverse the discriminator mappings.
154
          Class<?> childDiscr = childCdm.getClassForElement(node, visitedClasses);
×
155
          if (childDiscr != null) {
×
156
            return childDiscr;
×
157
          }
158
        }
159
      }
×
160
      return cls;
×
161
    }
162
  }
163

164
  /**
165
   * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy.
166
   *
167
   * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy,
168
   * so it's not possible to use the instanceof keyword.
169
   *
170
   * @param modelClass A OpenAPI model class.
171
   * @param inst The instance object.
172
   */
173
  public static boolean isInstanceOf(Class<?> modelClass, Object inst, Set<Class<?>> visitedClasses) {
174
    if (modelClass.isInstance(inst)) {
×
175
      // This handles the 'allOf' use case with single parent inheritance.
176
      return true;
×
177
    }
178
    if (visitedClasses.contains(modelClass)) {
×
179
      // This is to prevent infinite recursion when the composed schemas have
180
      // a circular dependency.
181
      return false;
×
182
    }
183
    visitedClasses.add(modelClass);
×
184

185
    // Traverse the oneOf/anyOf composed schemas.
186
    Map<String, GenericType> descendants = modelDescendants.get(modelClass);
×
187
    if (descendants != null) {
×
188
      for (GenericType childType : descendants.values()) {
×
189
        if (isInstanceOf(childType.getRawType(), inst, visitedClasses)) {
×
190
          return true;
×
191
        }
192
      }
×
193
    }
194
    return false;
×
195
  }
196

197
  /**
198
   * A map of discriminators for all model classes.
199
   */
200
  private static Map<Class<?>, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<Class<?>, ClassDiscriminatorMapping>();
×
201

202
  /**
203
   * A map of oneOf/anyOf descendants for each model class.
204
   */
205
  private static Map<Class<?>, Map<String, GenericType>> modelDescendants = new HashMap<Class<?>, Map<String, GenericType>>();
×
206

207
  /**
208
    * Register a model class discriminator.
209
    *
210
    * @param modelClass the model class
211
    * @param discriminatorPropertyName the name of the discriminator property
212
    * @param mappings a map with the discriminator mappings.
213
    */
214
  public static void registerDiscriminator(Class<?> modelClass, String discriminatorPropertyName, Map<String, Class<?>> mappings) {
215
    ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings);
×
216
    modelDiscriminators.put(modelClass, m);
×
217
  }
×
218

219
  /**
220
    * Register the oneOf/anyOf descendants of the modelClass.
221
    *
222
    * @param modelClass the model class
223
    * @param descendants a map of oneOf/anyOf descendants.
224
    */
225
  public static void registerDescendants(Class<?> modelClass, Map<String, GenericType> descendants) {
226
    modelDescendants.put(modelClass, descendants);
×
227
  }
×
228

229
  private static JSON json;
230

231
  static
232
  {
233
    json = new JSON();
×
234
  }
×
235

236
  /**
237
    * Get the default JSON instance.
238
    *
239
    * @return the default JSON instance
240
    */
241
  public static JSON getDefault() {
242
    return json;
×
243
  }
244

245
  /**
246
    * Set the default JSON instance.
247
    *
248
    * @param json JSON instance to be used
249
    */
250
  public static void setDefault(JSON json) {
251
    JSON.json = json;
×
252
  }
×
253
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc