Skip to contentMethod: lambda$getPropertyOrder$1(String, Field)
1: /*
2: * JB4JSON-LD
3: * Copyright (C) 2024 Czech Technical University in Prague
4: *
5: * This library is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public
7: * License as published by the Free Software Foundation; either
8: * version 3.0 of the License, or (at your option) any later version.
9: *
10: * This library is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: * Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this library.
17: */
18: package cz.cvut.kbss.jsonld.deserialization.expanded;
19:
20: import cz.cvut.kbss.jsonld.ConfigParam;
21: import cz.cvut.kbss.jsonld.JsonLd;
22: import cz.cvut.kbss.jsonld.common.BeanAnnotationProcessor;
23: import cz.cvut.kbss.jsonld.common.IdentifierUtil;
24: import cz.cvut.kbss.jsonld.deserialization.InstanceBuilder;
25: import cz.cvut.kbss.jsonld.deserialization.util.ValueUtils;
26: import cz.cvut.kbss.jsonld.exception.JsonLdDeserializationException;
27: import cz.cvut.kbss.jsonld.exception.UnknownPropertyException;
28: import jakarta.json.JsonObject;
29: import jakarta.json.JsonValue;
30:
31: import java.lang.reflect.Field;
32: import java.util.ArrayList;
33: import java.util.Collections;
34: import java.util.HashSet;
35: import java.util.List;
36: import java.util.Optional;
37: import java.util.Set;
38:
39: class ObjectDeserializer extends Deserializer<JsonObject> {
40:
41: private final String property;
42: private final Class<?> targetClass;
43:
44: ObjectDeserializer(InstanceBuilder instanceBuilder, DeserializerConfig config, String property) {
45: super(instanceBuilder, config);
46: assert property != null;
47: this.property = property;
48: this.targetClass = null;
49: }
50:
51: ObjectDeserializer(InstanceBuilder instanceBuilder, DeserializerConfig config, Class<?> targetClass) {
52: super(instanceBuilder, config);
53: assert targetClass != null;
54: this.targetClass = targetClass;
55: this.property = null;
56: }
57:
58: @Override
59: void processValue(JsonObject value) {
60: openObject(value);
61: final List<String> orderedProps = orderAttributesForProcessing(value);
62: for (String property : orderedProps) {
63: final boolean shouldSkip = shouldSkipProperty(property);
64: if (shouldSkip) {
65: continue;
66: }
67: assert value.get(property).getValueType() == JsonValue.ValueType.ARRAY;
68: new CollectionDeserializer(instanceBuilder, config, property).processValue(value.getJsonArray(property));
69: }
70: instanceBuilder.closeObject();
71: }
72:
73: private void openObject(JsonObject value) {
74: try {
75: if (property != null) {
76: instanceBuilder.openObject(getId(value), property, getObjectTypes(value));
77: } else {
78: assert targetClass != null;
79: final Class<?> cls = resolveTargetClass(value, targetClass);
80: assert targetClass.isAssignableFrom(cls);
81: instanceBuilder.openObject(getId(value), cls);
82: }
83: } catch (UnknownPropertyException e) {
84: if (!configuration().is(ConfigParam.IGNORE_UNKNOWN_PROPERTIES)) {
85: throw e;
86: }
87: }
88: }
89:
90: private String getId(JsonObject object) {
91: return object.containsKey(JsonLd.ID) ? ValueUtils.stringValue(object.get(JsonLd.ID)) : IdentifierUtil.generateBlankNodeId();
92: }
93:
94: private List<String> orderAttributesForProcessing(JsonObject value) {
95: final List<String> propertyOrder = getPropertyOrder();
96: final Set<String> ordered = new HashSet<>(propertyOrder);
97: final List<String> result = new ArrayList<>();
98: propertyOrder.stream().filter(value::containsKey).forEach(result::add);
99:
100: value.keySet().stream().filter(p -> !ordered.contains(p)).forEach(result::add);
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.isEmpty()) {
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: }