Skip to contentMethod: getId(Map)
1: /**
2: * Copyright (C) 2022 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jsonld.deserialization.expanded;
16:
17: import cz.cvut.kbss.jsonld.ConfigParam;
18: import cz.cvut.kbss.jsonld.JsonLd;
19: import cz.cvut.kbss.jsonld.common.BeanAnnotationProcessor;
20: import cz.cvut.kbss.jsonld.common.IdentifierUtil;
21: import cz.cvut.kbss.jsonld.deserialization.InstanceBuilder;
22: import cz.cvut.kbss.jsonld.exception.JsonLdDeserializationException;
23: import cz.cvut.kbss.jsonld.exception.UnknownPropertyException;
24:
25: import java.lang.reflect.Field;
26: import java.util.*;
27:
28: class ObjectDeserializer extends Deserializer<Map<?, ?>> {
29:
30: private final String property;
31: private final Class<?> targetClass;
32:
33: ObjectDeserializer(InstanceBuilder instanceBuilder, DeserializerConfig config, String property) {
34: super(instanceBuilder, config);
35: assert property != null;
36: this.property = property;
37: this.targetClass = null;
38: }
39:
40: ObjectDeserializer(InstanceBuilder instanceBuilder, DeserializerConfig config, Class<?> targetClass) {
41: super(instanceBuilder, config);
42: assert targetClass != null;
43: this.targetClass = targetClass;
44: this.property = null;
45: }
46:
47: @Override
48: void processValue(Map<?, ?> value) {
49: openObject(value);
50: for (Map.Entry<?, ?> e : orderAttributesForProcessing(value).entrySet()) {
51: final String property = e.getKey().toString();
52: final boolean shouldSkip = shouldSkipProperty(property);
53: if (shouldSkip) {
54: continue;
55: }
56: assert e.getValue() instanceof List;
57: new CollectionDeserializer(instanceBuilder, config, property).processValue((List<?>) e.getValue());
58: }
59: instanceBuilder.closeObject();
60: }
61:
62: private void openObject(Map<?, ?> value) {
63: try {
64: if (property != null) {
65: instanceBuilder.openObject(getId(value), property, getObjectTypes(value));
66: } else {
67: assert targetClass != null;
68: final Class<?> cls = resolveTargetClass(value, targetClass);
69: assert targetClass.isAssignableFrom(cls);
70: instanceBuilder.openObject(getId(value), cls);
71: }
72: } catch (UnknownPropertyException e) {
73: if (!configuration().is(ConfigParam.IGNORE_UNKNOWN_PROPERTIES)) {
74: throw e;
75: }
76: }
77: }
78:
79: private String getId(Map<?, ?> object) {
80:• return object.containsKey(JsonLd.ID) ? object.get(JsonLd.ID).toString() : IdentifierUtil.generateBlankNodeId();
81: }
82:
83: private Map<?, ?> orderAttributesForProcessing(Map<?, ?> value) {
84: final List<String> propertyOrder = getPropertyOrder();
85: if (propertyOrder.isEmpty()) {
86: return value;
87: }
88: final Map result = new LinkedHashMap<>(value.size());
89: for (String property : propertyOrder) {
90: final Iterator<? extends Map.Entry<?, ?>> it = value.entrySet().iterator();
91: while (it.hasNext()) {
92: final Map.Entry<?, ?> e = it.next();
93: if (property.equals(e.getKey())) {
94: result.put(e.getKey(), e.getValue());
95: it.remove();
96: break;
97: }
98: }
99: }
100: result.putAll(value);
101: return result;
102: }
103:
104: private List<String> getPropertyOrder() {
105: final Class<?> cls = instanceBuilder.getCurrentContextType();
106: if (cls == null) {
107: return Collections.emptyList();
108: }
109: final String[] attributeOrder = BeanAnnotationProcessor.getAttributeOrder(cls);
110: if (attributeOrder.length == 0) {
111: return Collections.emptyList();
112: }
113: final List<Field> fields = BeanAnnotationProcessor
114: .getMarshallableFields(instanceBuilder.getCurrentContextType());
115: final List<String> propertyOrder = new ArrayList<>(attributeOrder.length);
116: for (String name : attributeOrder) {
117: final Optional<Field> field = fields.stream().filter(f -> f.getName().equals(name)).findFirst();
118: if (!field.isPresent()) {
119: throw new JsonLdDeserializationException(
120: "Field called " + name + " declared in JsonLdAttributeOrder annotation not found in class " +
121: cls + ".");
122: }
123: propertyOrder.add(BeanAnnotationProcessor.getAttributeIdentifier(field.get()));
124: }
125: return propertyOrder;
126: }
127:
128: private boolean shouldSkipProperty(String property) {
129: if (JsonLd.ID.equals(property)) {
130: return true;
131: }
132: if (!instanceBuilder.isPropertyDeserializable(property)) {
133: throwUnknownPropertyIfNotIgnored(property);
134: return true;
135: }
136: return false;
137: }
138:
139: private void throwUnknownPropertyIfNotIgnored(String property) {
140: if (!instanceBuilder.isPropertyMapped(property) && !configuration().is(ConfigParam.IGNORE_UNKNOWN_PROPERTIES)) {
141: throw UnknownPropertyException.create(property, instanceBuilder.getCurrentContextType());
142: }
143: }
144: }