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

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

16 Oct 2023 09:08AM CUT coverage: 12.568%. First build
#2703

push

web-flow
Merge 5bb3765b7 into fe719ccb3

6014 of 6014 new or added lines in 86 files covered. (100.0%)

11852 of 94302 relevant lines covered (12.57%)

0.13 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.fasterxml.jackson.annotation.*;
5
import com.fasterxml.jackson.databind.*;
6
import com.fasterxml.jackson.databind.json.JsonMapper;
7
import com.fasterxml.jackson.databind.module.SimpleModule;
8
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
9
import com.adyen.model.acswebhooks.*;
10

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

227
  private static JSON json;
228

229
  static
230
  {
231
    json = new JSON();
×
232
  }
×
233

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

243
  /**
244
    * Set the default JSON instance.
245
    *
246
    * @param json JSON instance to be used
247
    */
248
  public static void setDefault(JSON json) {
249
    JSON.json = json;
×
250
  }
×
251
}
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