Skip to content

Method: static {...}

1: /**
2: * Copyright (C) 2022 Czech Technical University in Prague
3: * <p>
4: * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5: * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6: * version.
7: * <p>
8: * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10: * details. You should have received a copy of the GNU General Public License along with this program. If not, see
11: * <http://www.gnu.org/licenses/>.
12: */
13: package cz.cvut.kbss.jsonld.deserialization.expanded;
14:
15: import cz.cvut.kbss.jsonld.JsonLd;
16: import cz.cvut.kbss.jsonld.deserialization.DeserializationContext;
17: import cz.cvut.kbss.jsonld.deserialization.InstanceBuilder;
18: import cz.cvut.kbss.jsonld.deserialization.util.DataTypeTransformer;
19: import cz.cvut.kbss.jsonld.deserialization.util.LangString;
20: import cz.cvut.kbss.jsonld.deserialization.util.XSDTypeCoercer;
21: import cz.cvut.kbss.jsonld.exception.MissingIdentifierException;
22:
23: import java.net.URI;
24: import java.util.List;
25: import java.util.Map;
26:
27: class CollectionDeserializer extends Deserializer<List<?>> {
28:
29: private final String property;
30:
31: CollectionDeserializer(InstanceBuilder instanceBuilder, DeserializerConfig config, String property) {
32: super(instanceBuilder, config);
33: this.property = property;
34: }
35:
36: @Override
37: void processValue(List<?> value) {
38: if (value.size() == 1 && value.get(0) instanceof Map) {
39: final Map<?, ?> map = (Map<?, ?>) value.get(0);
40: if (!instanceBuilder.isPlural(property)) {
41: resolvePropertyValue(map);
42: return;
43: }
44: if (map.size() == 1 && map.containsKey(JsonLd.LIST)) {
45: assert map.get(JsonLd.LIST) instanceof List;
46: processValue((List<?>) map.get(JsonLd.LIST));
47: return;
48: }
49: }
50: instanceBuilder.openCollection(property);
51: for (Object item : value) {
52: if (item instanceof Map) {
53: resolveValue((Map<?, ?>) item);
54: } else {
55: instanceBuilder.addValue(item);
56: }
57: }
58: instanceBuilder.closeCollection();
59: }
60:
61: private void resolveValue(Map<?, ?> value) {
62: final Class<?> targetType = instanceBuilder.getCurrentCollectionElementType();
63: if (config.getDeserializers().hasCustomDeserializer(targetType)) {
64: instanceBuilder.addValue(deserializeUsingCustomDeserializer(targetType, value));
65: } else if (value.size() == 1 && value.containsKey(JsonLd.VALUE)) {
66: instanceBuilder.addValue(value.get(JsonLd.VALUE));
67: } else if (value.size() == 1 && value.containsKey(JsonLd.ID)) {
68: handleReferenceNodeInCollection(value, targetType);
69: } else if (value.containsKey(JsonLd.LANGUAGE)) {
70: assert value.containsKey(JsonLd.VALUE);
71: instanceBuilder.addValue(
72: new LangString(value.get(JsonLd.VALUE).toString(), value.get(JsonLd.LANGUAGE).toString()));
73: } else if (instanceBuilder.isCurrentCollectionProperties()) {
74: // If we are deserializing an object into @Properties, just extract the identifier and put it into the map
75: if (!value.containsKey(JsonLd.ID)) {
76: throw new MissingIdentifierException(
77: "Cannot put an object without an identifier into @Properties. Object: " + value);
78: }
79: instanceBuilder.addValue(URI.create(value.get(JsonLd.ID).toString()));
80: } else {
81: final Class<?> elementType = instanceBuilder.getCurrentCollectionElementType();
82: new ObjectDeserializer(instanceBuilder, config, elementType).processValue(value);
83: }
84: }
85:
86: private void handleReferenceNodeInCollection(Map<?, ?> value, Class<?> targetType) {
87: assert value.size() == 1 && value.containsKey(JsonLd.ID);
88: final String identifier = value.get(JsonLd.ID).toString();
89: if (targetType.isEnum()) {
90: instanceBuilder.addValue(DataTypeTransformer.transformIndividualToEnumConstant(identifier,
91: (Class<? extends Enum>) targetType));
92: } else {
93: instanceBuilder.addNodeReference(identifier);
94: }
95: }
96:
97: private void resolvePropertyValue(Map<?, ?> value) {
98: final Class<?> targetType = instanceBuilder.getTargetType(property);
99: if (config.getDeserializers().hasCustomDeserializer(targetType)) {
100: instanceBuilder.addValue(property, deserializeUsingCustomDeserializer(targetType, value));
101: return;
102: }
103: if (value.containsKey(JsonLd.VALUE)) {
104: extractLiteralValue(value);
105: } else if (value.size() == 1 && value.containsKey(JsonLd.ID)) {
106: handleSingularReferenceNode(value, targetType);
107: } else {
108: new ObjectDeserializer(instanceBuilder, config, property).processValue(value);
109: }
110: }
111:
112: private <T> T deserializeUsingCustomDeserializer(Class<T> targetType, Map<?, ?> value) {
113: final DeserializationContext<T> ctx = new DeserializationContext<>(targetType, config.getTargetResolver());
114: assert config.getDeserializers().getDeserializer(ctx).isPresent();
115: return config.getDeserializers().getDeserializer(ctx).get().deserialize(value, ctx);
116: }
117:
118: private void extractLiteralValue(Map<?, ?> value) {
119: final Object val = value.get(JsonLd.VALUE);
120: if (value.containsKey(JsonLd.TYPE)) {
121: instanceBuilder
122: .addValue(property, XSDTypeCoercer.coerceType(val.toString(), value.get(JsonLd.TYPE).toString()));
123: } else if (value.containsKey(JsonLd.LANGUAGE)) {
124: instanceBuilder.addValue(property, new LangString(val.toString(), value.get(JsonLd.LANGUAGE).toString()));
125: } else {
126: instanceBuilder.addValue(property, val);
127: }
128: }
129:
130: private void handleSingularReferenceNode(Map<?, ?> value, Class<?> targetType) {
131: assert value.size() == 1 && value.containsKey(JsonLd.ID);
132: final String identifier = value.get(JsonLd.ID).toString();
133: if (targetType.isEnum()) {
134: instanceBuilder.addValue(property, DataTypeTransformer.transformIndividualToEnumConstant(identifier,
135: (Class<? extends Enum>) targetType));
136: } else {
137: instanceBuilder.addNodeReference(property, identifier);
138: }
139: }
140: }