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

wistefan / ngsi-ld-java-mapping / #215

30 Oct 2024 11:56AM UTC coverage: 79.327% (+0.07%) from 79.26%
#215

push

web-flow
Merge pull request #63 from wistefan/handle-emptylists

handle empty property lists

2 of 2 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

495 of 624 relevant lines covered (79.33%)

0.79 hits per line

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

75.68
/src/main/java/io/github/wistefan/mapping/AdditionalPropertyDeserializer.java
1
package io.github.wistefan.mapping;
2

3
import com.fasterxml.jackson.core.JsonParser;
4
import com.fasterxml.jackson.core.JsonToken;
5
import com.fasterxml.jackson.core.type.TypeReference;
6
import com.fasterxml.jackson.databind.DeserializationContext;
7
import com.fasterxml.jackson.databind.JavaType;
8
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
9
import com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer;
10
import com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer;
11
import com.fasterxml.jackson.databind.type.TypeFactory;
12
import org.fiware.ngsi.model.*;
13

14
import java.io.IOException;
15
import java.util.ArrayList;
16
import java.util.List;
17

18
/**
19
 * Custom deserializer for the {@link org.fiware.ngsi.model.AdditionalPropertyVO}
20
 * It can differentiate between list and object type properties and handle them with the fitting serializer.
21
 */
22
public class AdditionalPropertyDeserializer extends AsArrayTypeDeserializer {
23

24
        /**
25
         * Default property-type deserializer can be used for the individual objects.
26
         */
27
        private final AsPropertyTypeDeserializer additionalPropertyObjectDeser;
28

29
        public AdditionalPropertyDeserializer(JavaType bt, TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible, JavaType defaultImpl) {
30
                super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);
1✔
31
                additionalPropertyObjectDeser = new AsPropertyTypeDeserializer(
1✔
32
                                TypeFactory.defaultInstance().constructType(new TypeReference<AdditionalPropertyObjectVO>() {}),
1✔
33
                                idRes,
34
                                AdditionalPropertyTypeResolver.NGSI_LD_TYPE_PROPERTY_NAME,
35
                                false,
36
                                defaultImpl);
37

38
        }
1✔
39

40
        @Override
41
        protected Object _deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
42

43
                // default behaviour
44
                if (p.canReadTypeId()) {
1✔
45
                        Object typeId = p.getTypeId();
×
46
                        if (typeId != null) {
×
47
                                return _deserializeWithNativeTypeId(p, ctxt, typeId);
×
48
                        }
49
                }
50
                // if no type id is present we need the next token to decide if its an object or an array
51
                JsonToken t = p.nextToken();
1✔
52
                // case FIELD_NAME:
53
                // If the token is of type FIELD_NAME, no START_ARRAY was present, thus we can take the
54
                // object and directly serialize it with the standard deserializer
55
                if (t == JsonToken.FIELD_NAME) {
1✔
56
                        return additionalPropertyObjectDeser.deserializeTypedFromObject(p, ctxt);
1✔
57
                }
58
                // case START_OBJECT
59
                // If a start-object(e.g. '{') token is present, a START_ARRAY was present and we have at least one
60
                // one object to be deserialized. The parser is handed over to the specialized method.
61
                if (t == JsonToken.START_OBJECT) {
1✔
62
                        return deserializeArray(p, ctxt);
1✔
63
                } else if (t == JsonToken.END_ARRAY) {
1✔
64
                        // we received an empty list
65
                        return new PropertyListVO();
1✔
66
                }
67

UNCOV
68
                return super._deserialize(p, ctxt);
×
69
        }
70

71
        /**
72
         * Deserializes an array of NGSI-LD properties(e.g. Property, GeoProperty or Relationship) to there concrete
73
         * list types(e.g. PropertyList, GeoPropertyList, RelationshipList)
74
         * @param p the current parser
75
         * @param ctxt the desrialization context to use
76
         * @return object of the deserialized list, will be a PropertyList, GeoPropertyList or RelationshipList type
77
         * @throws IOException
78
         */
79
        private Object deserializeArray(JsonParser p, DeserializationContext ctxt) throws IOException {
80
                List<Object> deserializedObjects = new ArrayList<>();
1✔
81
                JsonToken next;
82
                do {
83
                        next = p.nextToken();
1✔
84
                        if (next == JsonToken.FIELD_NAME) {
1✔
85
                                deserializedObjects.add(additionalPropertyObjectDeser.deserializeTypedFromObject(p, ctxt));
1✔
86
                        }
87
                } while (next != JsonToken.END_ARRAY);
1✔
88

89
                if (deserializedObjects.isEmpty()) {
1✔
90
                        // any empty list is sufficient
91
                        return new PropertyListVO();
×
92
                }
93
                // get type of first object to decide the list type
94
                Object firstObject = deserializedObjects.get(0);
1✔
95
                if (firstObject instanceof PropertyVO) {
1✔
96
                        PropertyListVO propertyVOS = new PropertyListVO();
1✔
97
                        deserializedObjects.stream().map(PropertyVO.class::cast).forEach(propertyVOS::add);
1✔
98
                        return propertyVOS;
1✔
99
                } else if (firstObject instanceof GeoPropertyVO) {
1✔
100
                        GeoPropertyListVO geoPropertyVOS = new GeoPropertyListVO();
×
101
                        deserializedObjects.stream().map(GeoPropertyVO.class::cast).forEach(geoPropertyVOS::add);
×
102
                        return geoPropertyVOS;
×
103
                } else if (firstObject instanceof RelationshipVO) {
1✔
104
                        RelationshipListVO relationshipVOS = new RelationshipListVO();
1✔
105
                        deserializedObjects.stream().map(RelationshipVO.class::cast).forEach(relationshipVOS::add);
1✔
106
                        return relationshipVOS;
1✔
107
                }
108
                throw new MappingException("Was not able to deserialize the array.");
×
109
        }
110

111
}
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