From 1e8f734c6b529087ff5cbed64de7e8a9cc0412ad Mon Sep 17 00:00:00 2001 From: Hylke van der Schaaf Date: Fri, 15 Mar 2024 13:06:28 +0100 Subject: [PATCH] Refactored Property Types and how they are (de)serialised --- .../frostserver/model}/CollectionsHelper.java | 5 +- .../ilt/frostserver/model/ComplexValue.java | 68 +++++++++ .../frostserver/model/ComplexValueImpl.java | 87 +++++++++++ .../ilt/frostserver/model/ext/MapValue.java | 115 +++++++++++++++ .../frostserver/model/ext/TimeInterval.java | 95 ++++++++++-- .../ilt/frostserver/model/ext/TimeValue.java | 110 ++++++++++++-- .../model/ext/UnitOfMeasurement.java | 56 +++++++- .../property/EntityPropertyCustomSelect.java | 3 +- .../property/type/PropertyType.java | 38 +++-- .../property/type/TypeComplex.java | 136 ++++++++++++++---- .../frostserver/property/type/TypeEntity.java | 3 +- .../property/type/TypeEntitySet.java | 3 +- .../property/type/TypeEnumeration.java | 5 +- .../frostserver/property/type/TypeSimple.java | 24 +++- .../property/type/TypeSimpleCustom.java | 14 +- .../property/type/TypeSimplePrimitive.java | 5 + .../property/type/TypeSimpleSet.java | 5 +- .../custom/CustomEntityDeserializer.java | 133 ++++++----------- .../pgjooq/bindings/JsonValue.java | 17 +-- .../fieldwrapper/StaTimeIntervalWrapper.java | 4 +- .../utils/fieldmapper/FieldMapperJson.java | 2 +- .../frostserver/property/ComplexValue.java | 29 ---- .../format/csv/tools/CsvComplexProperty.java | 8 +- .../deserialize/TimeIntervalDeserializer.java | 8 +- .../deserialize/TimeValueDeserializer.java | 8 +- .../odata/metadata/CsdlItemComplexType.java | 10 +- .../odata/metadata/MxGraphGenerator.java | 11 +- .../serialize/TimeIntervalSerializer.java | 8 +- .../odata/serialize/TimeValueSerializer.java | 10 +- .../plugin/openapi/spec/OASchema.java | 6 +- 30 files changed, 763 insertions(+), 263 deletions(-) rename {FROST-Server.Util/src/main/java/de/fraunhofer/iosb/ilt/frostserver/util => FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model}/CollectionsHelper.java (96%) create mode 100644 FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ComplexValue.java create mode 100644 FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ComplexValueImpl.java create mode 100644 FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/MapValue.java delete mode 100644 FROST-Server.Util/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/ComplexValue.java diff --git a/FROST-Server.Util/src/main/java/de/fraunhofer/iosb/ilt/frostserver/util/CollectionsHelper.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/CollectionsHelper.java similarity index 96% rename from FROST-Server.Util/src/main/java/de/fraunhofer/iosb/ilt/frostserver/util/CollectionsHelper.java rename to FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/CollectionsHelper.java index f7f884742..aaf783a32 100644 --- a/FROST-Server.Util/src/main/java/de/fraunhofer/iosb/ilt/frostserver/util/CollectionsHelper.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/CollectionsHelper.java @@ -15,9 +15,8 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ -package de.fraunhofer.iosb.ilt.frostserver.util; +package de.fraunhofer.iosb.ilt.frostserver.model; -import de.fraunhofer.iosb.ilt.frostserver.property.ComplexValue; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -85,7 +84,7 @@ private static Object getFrom(final Object mapOrList, final List path) { if (currentEntry instanceof Map map) { currentEntry = map.get(key); } else if (currentEntry instanceof ComplexValue cv) { - currentEntry = cv.get(key); + currentEntry = cv.getProperty(key); } else if (currentEntry instanceof List list) { try { currentEntry = list.get(Integer.parseInt(key)); diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ComplexValue.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ComplexValue.java new file mode 100644 index 000000000..3aea3513d --- /dev/null +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ComplexValue.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 + * Karlsruhe, Germany. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package de.fraunhofer.iosb.ilt.frostserver.model; + +import de.fraunhofer.iosb.ilt.frostserver.property.Property; + +/** + * Interface that values of complex properties should implement to make it + * easier to access sub-properties. + * + * @param The type of the complex value (for fluent API) + */ +public interface ComplexValue> { + + /** + * Get the value of the given property. + * + * @param

The type of the property and value. + * @param property The property to get the value of. + * @return the value of the requested property. + */ + public

P getProperty(Property

property); + + /** + * Set the given property to the given value. + * + * @param

The type of the property. + * @param property The property to set. + * @param value The value to set the property to. + * @return this. + */ + public

S setProperty(Property

property, P value); + + /** + * Get the custom property with the given name. Only valid for ComplexTypes + * that are classed as openType, returns null for non-openTypes. + * + * @param name The name of the custom property to fetch. + * @return The value of the custom property. + */ + public Object getProperty(String name); + + /** + * Set the custom property with the given name to the given value. Only + * valid for ComplexTypes that are classed as openType. + * + * @param name The name of the custom property to set. + * @param value The value of the custom property to set. + * @return this. + */ + public S setProperty(String name, Object value); + +} diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ComplexValueImpl.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ComplexValueImpl.java new file mode 100644 index 000000000..697b8a09c --- /dev/null +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ComplexValueImpl.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 + * Karlsruhe, Germany. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package de.fraunhofer.iosb.ilt.frostserver.model; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.type.TypeReference; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; +import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +public class ComplexValueImpl implements ComplexValue { + + public static final TypeReference TYPE_REFERENCE = new TypeReference() { + // Empty by design. + }; + + private final TypeComplex type; + private final Map properties = new LinkedHashMap<>(); + + public ComplexValueImpl(TypeComplex type) { + this.type = type; + } + + @JsonIgnore + public TypeComplex getType() { + return type; + } + + @Override + public

P getProperty(Property

property) { + return (P) properties.get(property.getJsonName()); + } + + @Override + public

ComplexValueImpl setProperty(Property

property, P value) { + properties.put(property.getJsonName(), value); + return this; + } + + @JsonAnyGetter + public Map getAllProperties() { + return Collections.unmodifiableMap(properties); + } + + @JsonAnySetter + public void setAnyProperty(String name, Object value) { + properties.put(name, value); + } + + @Override + public Object getProperty(String name) { + return properties.get(name); + } + + @Override + public ComplexValueImpl setProperty(String name, Object value) { + if (!type.isOpenType()) { + throw new IllegalArgumentException("Can not set custom properties on non-openType " + type); + } + properties.put(name, value); + return this; + } + + public static TypeComplex.Instantiator createFor(TypeComplex type) { + return () -> new ComplexValueImpl(type); + } + +} diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/MapValue.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/MapValue.java new file mode 100644 index 000000000..1cf7642c0 --- /dev/null +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/MapValue.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 + * Karlsruhe, Germany. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package de.fraunhofer.iosb.ilt.frostserver.model.ext; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import de.fraunhofer.iosb.ilt.frostserver.model.ComplexValue; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * The complex value for an open type. + */ +public class MapValue implements ComplexValue { + + private final Map content; + + public MapValue() { + this.content = new LinkedHashMap<>(); + } + + public MapValue(Map content) { + this.content = content; + } + + @JsonIgnore + public boolean isEmpty() { + return content.isEmpty(); + } + + @JsonAnyGetter + public Map getContent() { + return content; + } + + public Set> entrySet() { + return content.entrySet(); + } + + @JsonIgnore + public Object get(String name) { + return content.get(name); + } + + public boolean containsKey(String name) { + return content.containsKey(name); + } + + @JsonAnySetter + public MapValue put(String name, Object value) { + content.put(name, value); + return this; + } + + @JsonIgnore + @Override + public

P getProperty(Property

property) { + return (P) content.get(property.getJsonName()); + } + + @JsonIgnore + @Override + public

MapValue setProperty(Property

property, P value) { + content.put(property.getJsonName(), value); + return this; + } + + @Override + public Object getProperty(String name) { + return content.get(name); + } + + @Override + public MapValue setProperty(String name, Object value) { + content.put(name, value); + return this; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof MapValue o) { + return content.equals(o.content); + } + return false; + } + + @Override + public int hashCode() { + int hash = 5; + return 79 * hash + Objects.hashCode(content); + } + +} diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/TimeInterval.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/TimeInterval.java index 9ac012e10..af6a478a1 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/TimeInterval.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/TimeInterval.java @@ -17,24 +17,33 @@ */ package de.fraunhofer.iosb.ilt.frostserver.model.ext; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_END; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_START; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_END; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_START; -import de.fraunhofer.iosb.ilt.frostserver.property.ComplexValue; +import de.fraunhofer.iosb.ilt.frostserver.model.ComplexValue; +import de.fraunhofer.iosb.ilt.frostserver.property.EntityPropertyMain; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; +import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex; import de.fraunhofer.iosb.ilt.frostserver.util.StringHelper; import java.text.ParseException; +import java.time.Instant; import java.util.Objects; import net.time4j.Moment; import net.time4j.range.MomentInterval; /** * Represent an ISO8601 time interval. - * - * @author jab */ -public class TimeInterval implements TimeObject, ComplexValue { +public class TimeInterval implements TimeObject, ComplexValue { + + public static EntityPropertyMain EP_START_TIME = TypeComplex.EP_START_TIME; + public static EntityPropertyMain EP_END_TIME = TypeComplex.EP_INTERVAL_END_TIME; - private final MomentInterval interval; + private MomentInterval interval; + + public TimeInterval() { + this.interval = MomentInterval.between(Moment.nowInSystemTime(), Moment.nowInSystemTime()); + } public TimeInterval(MomentInterval interval) { if (interval == null) { @@ -94,15 +103,75 @@ public String toString() { return asISO8601(); } + public Moment getStart() { + return interval.getStartAsMoment(); + } + + public Moment getEnd() { + return interval.getEndAsMoment(); + } + + @Override + public Object getProperty(String name) { + switch (name) { + case NAME_INTERVAL_START: + return interval.getStartAsMoment(); + + case NAME_INTERVAL_END: + return interval.getEndAsMoment(); + + default: + throw new IllegalArgumentException("Unknown sub-property: " + name); + } + } + @Override - public Object get(String name) { - return switch (name) { - case KEY_INTERVAL_START -> interval.getStartAsMoment(); + public TimeInterval setProperty(String name, Object value) { + switch (name) { + case NAME_INTERVAL_START: + return setProperty(EP_START_TIME, value); - case KEY_INTERVAL_END -> interval.getEndAsMoment(); + case NAME_INTERVAL_END: + return setProperty(EP_END_TIME, value); - default -> throw new IllegalArgumentException("Unknown sub-property: " + name); - }; + default: + throw new IllegalArgumentException("Unknown sub-property: " + name); + } + } + + @Override + public

P getProperty(Property

property) { + if (property == EP_START_TIME) { + return (P) interval.getStartAsMoment(); + } + if (property == EP_END_TIME) { + return (P) interval.getStartAsMoment(); + } + throw new IllegalArgumentException("Unknown sub-property: " + property); + } + + @Override + public TimeInterval setProperty(Property property, Object value) { + if (value == null) { + return this; + } + Moment moment; + if (value instanceof Moment m) { + moment = m; + } else if (value instanceof Instant i) { + moment = Moment.from(i); + } else { + throw new IllegalArgumentException("TimeInterval only accepts Moment or Instant, not " + value.getClass().getName()); + } + if (property == EP_START_TIME) { + interval = interval.withStart(moment); + return this; + } + if (property == EP_END_TIME) { + interval = interval.withEnd(moment).withOpenEnd(); + return this; + } + throw new IllegalArgumentException("Unknown sub-property: " + property); } } diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/TimeValue.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/TimeValue.java index d9c8a18d4..56adc332c 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/TimeValue.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/TimeValue.java @@ -17,22 +17,33 @@ */ package de.fraunhofer.iosb.ilt.frostserver.model.ext; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_START; - -import de.fraunhofer.iosb.ilt.frostserver.property.ComplexValue; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_END; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_START; + +import de.fraunhofer.iosb.ilt.frostserver.model.ComplexValue; +import de.fraunhofer.iosb.ilt.frostserver.property.EntityPropertyMain; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; +import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex; +import java.time.Instant; import java.util.Objects; import net.time4j.Moment; /** * Common interface for time values. Needed as STA sometimes does not specify * wether an instant or an interval will be passed. - * - * @author jab */ -public class TimeValue implements TimeObject, ComplexValue { +public class TimeValue implements TimeObject, ComplexValue { + + public static EntityPropertyMain EP_START_TIME = TypeComplex.EP_START_TIME; + public static EntityPropertyMain EP_END_TIME = TypeComplex.EP_INTERVAL_END_TIME; + + private TimeInstant instant; + private TimeInterval interval; - private final TimeInstant instant; - private final TimeInterval interval; + public TimeValue() { + this.instant = null; + this.interval = null; + } public TimeValue(TimeInstant timeInstant) { this.instant = timeInstant; @@ -111,14 +122,87 @@ public int hashCode() { } @Override - public Object get(String name) { + public

P getProperty(Property

property) { + if (property != EP_START_TIME && property != EP_END_TIME) { + throw new IllegalArgumentException("Unknown sub-property: " + property); + } if (isInterval()) { - return interval.get(name); + return interval.getProperty(property); } else { - if (KEY_INTERVAL_START.equals(name)) { - return instant; + return (P) instant; + } + } + + @Override + public TimeValue setProperty(Property property, Object value) { + Moment moment; + if (value == null) { + moment = null; + } else if (value instanceof Moment m) { + moment = m; + } else if (value instanceof Instant i) { + moment = Moment.from(i); + } else { + throw new IllegalArgumentException("TimeInterval only accepts Moment or Instant, not " + value.getClass().getName()); + } + if (property == EP_START_TIME) { + if (moment == null) { + return this; + } + if (instant != null) { + instant = new TimeInstant(moment); + } else { + interval.setProperty(property, moment); } - return null; + return this; + } + if (property == EP_END_TIME) { + if (instant != null) { + if (moment == null) { + return this; + } + // setting end on instant, convert to interval. + interval = TimeInterval.create(instant.getDateTime(), moment); + instant = null; + } else { + if (moment == null) { + // Removing end from interval, convert to instant + instant = TimeInstant.create(interval.getStart()); + interval = null; + } else { + interval.setProperty(property, moment); + } + } + } + throw new IllegalArgumentException("Unknown sub-property: " + property); + + } + + @Override + public Object getProperty(String name) { + switch (name) { + case NAME_INTERVAL_START: + return getProperty(EP_START_TIME); + + case NAME_INTERVAL_END: + return getProperty(EP_END_TIME); + + default: + throw new IllegalArgumentException("Unknown sub-property: " + name); + } + } + + @Override + public TimeValue setProperty(String name, Object value) { + switch (name) { + case NAME_INTERVAL_START: + return setProperty(EP_START_TIME, value); + + case NAME_INTERVAL_END: + return setProperty(EP_END_TIME, value); + + default: + throw new IllegalArgumentException("Unknown sub-property: " + name); } } diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/UnitOfMeasurement.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/UnitOfMeasurement.java index d0bc4d012..97b8a52fc 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/UnitOfMeasurement.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/model/ext/UnitOfMeasurement.java @@ -17,8 +17,12 @@ */ package de.fraunhofer.iosb.ilt.frostserver.model.ext; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeSimplePrimitive.EDM_STRING; + import com.fasterxml.jackson.core.JsonProcessingException; -import de.fraunhofer.iosb.ilt.frostserver.property.ComplexValue; +import de.fraunhofer.iosb.ilt.frostserver.model.ComplexValue; +import de.fraunhofer.iosb.ilt.frostserver.property.EntityPropertyMain; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; import de.fraunhofer.iosb.ilt.frostserver.util.SimpleJsonMapper; import java.util.Objects; @@ -27,7 +31,11 @@ * * @author jab */ -public class UnitOfMeasurement implements ComplexValue { +public class UnitOfMeasurement implements ComplexValue { + + public static final EntityPropertyMain EP_NAME = new EntityPropertyMain<>("name", EDM_STRING); + public static final EntityPropertyMain EP_DEFINITION = new EntityPropertyMain<>("definition", EDM_STRING); + public static final EntityPropertyMain EP_SYMBOL = new EntityPropertyMain<>("symbol", EDM_STRING); private String name; private String symbol; @@ -46,7 +54,7 @@ public UnitOfMeasurement( } @Override - public Object get(String name) { + public Object getProperty(String name) { switch (name) { case "name": return getName(); @@ -59,6 +67,48 @@ public Object get(String name) { } } + @Override + public UnitOfMeasurement setProperty(String name, Object value) { + switch (name) { + case "name": + return setName((String) value); + case "symbol": + return setSymbol((String) value); + case "definition": + return setDefinition((String) value); + default: + return this; + } + } + + @Override + public

P getProperty(Property

property) { + if (property == EP_NAME) { + return (P) name; + } + if (property == EP_DEFINITION) { + return (P) definition; + } + if (property == EP_SYMBOL) { + return (P) symbol; + } + throw new IllegalArgumentException("Unknown sub-property: " + property); + } + + @Override + public

UnitOfMeasurement setProperty(Property

property, P value) { + if (property == EP_NAME) { + return setName((String) value); + } + if (property == EP_DEFINITION) { + return setDefinition((String) value); + } + if (property == EP_SYMBOL) { + return setSymbol((String) value); + } + throw new IllegalArgumentException("Unknown sub-property: " + property); + } + /** * @return the name */ diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/EntityPropertyCustomSelect.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/EntityPropertyCustomSelect.java index f01d2d59b..01d366171 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/EntityPropertyCustomSelect.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/EntityPropertyCustomSelect.java @@ -17,9 +17,10 @@ */ package de.fraunhofer.iosb.ilt.frostserver.property; +import de.fraunhofer.iosb.ilt.frostserver.model.CollectionsHelper; +import de.fraunhofer.iosb.ilt.frostserver.model.ComplexValue; import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity; import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex; -import de.fraunhofer.iosb.ilt.frostserver.util.CollectionsHelper; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/PropertyType.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/PropertyType.java index b562b147d..7b58cfa71 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/PropertyType.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/PropertyType.java @@ -17,28 +17,34 @@ */ package de.fraunhofer.iosb.ilt.frostserver.property.type; -import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; import de.fraunhofer.iosb.ilt.frostserver.model.core.annotations.Annotatable; import de.fraunhofer.iosb.ilt.frostserver.model.core.annotations.Annotation; +import de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils; import java.util.ArrayList; import java.util.List; /** - * - * @author hylke + * Class for defining property types. */ public class PropertyType implements Annotatable { private final String name; private final String description; - private final TypeReference typeReference; - + private JsonDeserializer deserializer; + private JsonSerializer serializer; private final List annotations = new ArrayList<>(); - public PropertyType(String name, String description, TypeReference typeReference) { + public PropertyType(String name, String description, JsonDeserializer deserializer, JsonSerializer serializer) { this.name = name; this.description = description; - this.typeReference = typeReference; + this.deserializer = deserializer; + this.serializer = serializer; + } + + public PropertyType(String name, String description, JsonDeserializer deserializer) { + this(name, description, deserializer, ParserUtils.getDefaultSerializer()); } public String getName() { @@ -49,8 +55,22 @@ public String getDescription() { return description; } - public TypeReference getTypeReference() { - return typeReference; + public JsonDeserializer getDeserializer() { + return deserializer; + } + + public PropertyType setDeserializer(JsonDeserializer deserializer) { + this.deserializer = deserializer; + return this; + } + + public JsonSerializer getSerializer() { + return serializer; + } + + public PropertyType setSerializer(JsonSerializer serializer) { + this.serializer = serializer; + return this; } public Object parseFromUrl(String input) { diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeComplex.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeComplex.java index ad0c4f257..f846941d3 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeComplex.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeComplex.java @@ -17,13 +17,28 @@ */ package de.fraunhofer.iosb.ilt.frostserver.property.type; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeSimplePrimitive.EDM_DATETIMEOFFSET; + import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; +import de.fraunhofer.iosb.ilt.frostserver.model.ComplexValue; +import de.fraunhofer.iosb.ilt.frostserver.model.ComplexValueImpl; +import de.fraunhofer.iosb.ilt.frostserver.model.ext.MapValue; +import de.fraunhofer.iosb.ilt.frostserver.model.ext.TimeInstant; +import de.fraunhofer.iosb.ilt.frostserver.model.ext.TimeInterval; +import de.fraunhofer.iosb.ilt.frostserver.model.ext.TimeValue; import de.fraunhofer.iosb.ilt.frostserver.model.ext.TypeReferencesHelper; +import de.fraunhofer.iosb.ilt.frostserver.property.EntityPropertyMain; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; +import de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import org.apache.commons.lang3.reflect.FieldUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,19 +53,26 @@ public class TypeComplex extends PropertyType { public static final String STA_OBJECT_NAME = "ANY"; public static final String STA_TIMEINTERVAL_NAME = "TM_Period"; public static final String STA_TIMEVALUE_NAME = "TM_Object"; - public static final String KEY_INTERVAL_START = "start"; - public static final String KEY_INTERVAL_END = "end"; - - public static final TypeComplex STA_MAP = new TypeComplex(STA_MAP_NAME, "A free object that can contain anything", TypeReferencesHelper.TYPE_REFERENCE_MAP, true); - public static final TypeComplex STA_OBJECT = new TypeComplex(STA_OBJECT_NAME, "A free type, can be anything", TypeReferencesHelper.TYPE_REFERENCE_OBJECT, true); - public static final TypeComplex STA_OBJECT_UNTYPED = new TypeComplex(STA_OBJECT_NAME, "A free type, can be anything", null, true); - - public static final TypeComplex STA_TIMEINTERVAL = new TypeComplex(STA_TIMEINTERVAL_NAME, "An ISO time interval.", TypeReferencesHelper.TYPE_REFERENCE_TIMEINTERVAL) - .addProperty(KEY_INTERVAL_START, TypeSimplePrimitive.EDM_DATETIMEOFFSET, true) - .addProperty(KEY_INTERVAL_END, TypeSimplePrimitive.EDM_DATETIMEOFFSET, true); - public static final TypeComplex STA_TIMEVALUE = new TypeComplex(STA_TIMEVALUE_NAME, "An ISO time instant or time interval.", TypeReferencesHelper.TYPE_REFERENCE_TIMEVALUE) - .addProperty(KEY_INTERVAL_START, TypeSimplePrimitive.EDM_DATETIMEOFFSET, true) - .addProperty(KEY_INTERVAL_END, TypeSimplePrimitive.EDM_DATETIMEOFFSET, false); + public static final String NAME_INTERVAL_START = "start"; + public static final String NAME_INTERVAL_END = "end"; + + public static final EntityPropertyMain EP_START_TIME = new EntityPropertyMain(NAME_INTERVAL_START, EDM_DATETIMEOFFSET) + .setNullable(false); + public static final EntityPropertyMain EP_INTERVAL_END_TIME = new EntityPropertyMain(NAME_INTERVAL_END, EDM_DATETIMEOFFSET) + .setNullable(false); + public static final EntityPropertyMain EP_VALUE_END_TIME = new EntityPropertyMain(NAME_INTERVAL_END, EDM_DATETIMEOFFSET) + .setNullable(true); + + public static final TypeComplex STA_MAP = new TypeComplex(STA_MAP_NAME, "A free object that can contain anything", true, MapValue::new, TypeReferencesHelper.TYPE_REFERENCE_MAP); + public static final TypeComplex STA_OBJECT = new TypeComplex(STA_OBJECT_NAME, "A free type, can be anything", true, null, TypeReferencesHelper.TYPE_REFERENCE_OBJECT); + public static final TypeComplex STA_OBJECT_UNTYPED = new TypeComplex(STA_OBJECT_NAME, "A free type, can be anything", true, null, null, null); + + public static final TypeComplex STA_TIMEINTERVAL = new TypeComplex(STA_TIMEINTERVAL_NAME, "An ISO time interval.", false, TimeInterval::new, TypeReferencesHelper.TYPE_REFERENCE_TIMEINTERVAL) + .registerProperty(EP_START_TIME) + .registerProperty(EP_INTERVAL_END_TIME); + public static final TypeComplex STA_TIMEVALUE = new TypeComplex(STA_TIMEVALUE_NAME, "An ISO time instant or time interval.", false, TimeValue::new, TypeReferencesHelper.TYPE_REFERENCE_TIMEVALUE) + .registerProperty(EP_START_TIME) + .registerProperty(EP_VALUE_END_TIME); private static final Logger LOGGER = LoggerFactory.getLogger(TypeComplex.class.getName()); private static final Map TYPES = new HashMap<>(); @@ -79,37 +101,97 @@ public static TypeComplex getType(String name) { return TYPES.get(name); } + /** + * The Set of PROPERTIES that Elements of this type have. + */ + private final Set properties = new LinkedHashSet<>(); + + /** + * The Set of PROPERTIES that Entities of this type have, mapped by their + * name. + */ + private final Map propertiesByName = new LinkedHashMap<>(); private final boolean openType; - private final Map properties = new LinkedHashMap<>(); - private final Map propertiesRequired = new LinkedHashMap<>(); + private Instantiator instantiator; + + public TypeComplex(String name, String description, boolean openType) { + super(name, description, null, null); + this.openType = openType; + } - public TypeComplex(String name, String description, TypeReference typeReference) { - this(name, description, typeReference, false); + public TypeComplex(String name, String description, boolean openType, Instantiator instantiator, TypeReference tr) { + super(name, description, ParserUtils.getDefaultDeserializer(tr), null); + this.openType = openType; + this.instantiator = instantiator; } - public TypeComplex(String name, String description, TypeReference typeReference, boolean openType) { - super(name, description, typeReference); + public TypeComplex(String name, String description, boolean openType, Instantiator instantiator, JsonDeserializer jd, JsonSerializer js) { + super(name, description, jd, js); this.openType = openType; + this.instantiator = instantiator; } public boolean isOpenType() { return openType; } - public Map getProperties() { + public Set getProperties() { return properties; } - public boolean isRequired(String property) { - return propertiesRequired.getOrDefault(property, false); + public Property getProperty(String name) { + return propertiesByName.get(name); } - public TypeComplex addProperty(String name, PropertyType property, boolean required) { - properties.put(name, property); - if (required) { - propertiesRequired.put(name, required); - } + public Map getPropertiesByName() { + return propertiesByName; + } + + public TypeComplex registerProperty(Property property) { + properties.add(property); + propertiesByName.put(property.getName(), property); return this; } + @Override + public String toString() { + return "TypeComplex: " + getName(); + } + + @Override + public JsonSerializer getSerializer() { + JsonSerializer serializer = super.getSerializer(); + if (serializer == null) { + serializer = ParserUtils.getDefaultSerializer(); + setSerializer(serializer); + } + return serializer; + } + + @Override + public JsonDeserializer getDeserializer() { + JsonDeserializer deserializer = super.getDeserializer(); + if (deserializer == null) { + deserializer = ParserUtils.getComplexTypeDeserializer(this); + setDeserializer(deserializer); + } + return deserializer; + } + + public void setInstantiator(Instantiator instantiator) { + this.instantiator = instantiator; + } + + public ComplexValue instantiate() { + if (instantiator == null) { + this.instantiator = ComplexValueImpl.createFor(this); + } + return instantiator.instantiate(); + } + + public static interface Instantiator { + + public ComplexValue instantiate(); + } + } diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEntity.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEntity.java index d0530c8ed..b4865e092 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEntity.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEntity.java @@ -18,7 +18,6 @@ package de.fraunhofer.iosb.ilt.frostserver.property.type; import de.fraunhofer.iosb.ilt.frostserver.model.EntityType; -import de.fraunhofer.iosb.ilt.frostserver.model.ext.TypeReferencesHelper; /** * @@ -29,7 +28,7 @@ public class TypeEntity extends TypeComplex { private EntityType entityType; public TypeEntity(EntityType entityType) { - super(entityType.entityName, "Entity Type " + entityType.entityName, TypeReferencesHelper.TYPE_REFERENCE_ENTITY, false); + super(entityType.entityName, "Entity Type " + entityType.entityName, false, null, null, null); } public EntityType getEntityType() { diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEntitySet.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEntitySet.java index 5d553a08d..254237640 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEntitySet.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEntitySet.java @@ -18,7 +18,6 @@ package de.fraunhofer.iosb.ilt.frostserver.property.type; import de.fraunhofer.iosb.ilt.frostserver.model.EntityType; -import de.fraunhofer.iosb.ilt.frostserver.model.ext.TypeReferencesHelper; /** * @@ -29,7 +28,7 @@ public class TypeEntitySet extends TypeComplex { private EntityType entityType; public TypeEntitySet(EntityType entityType) { - super(entityType.entityName, "Collection of " + entityType.entityName, TypeReferencesHelper.TYPE_REFERENCE_ENTITYSET, false); + super(entityType.entityName, "Collection of " + entityType.entityName, false, null, null, null); } public EntityType getEntityType() { diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEnumeration.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEnumeration.java index e3821647d..77c9f481f 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEnumeration.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeEnumeration.java @@ -18,6 +18,7 @@ package de.fraunhofer.iosb.ilt.frostserver.property.type; import com.fasterxml.jackson.core.type.TypeReference; +import de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils; import java.util.LinkedHashMap; import java.util.Map; @@ -30,8 +31,8 @@ public class TypeEnumeration> extends PropertyType { private final Class enumClass; - public TypeEnumeration(String name, String description, Class enumClass, TypeReference typeReference) { - super(name, description, typeReference); + public TypeEnumeration(String name, String description, Class enumClass, TypeReference tr) { + super(name, description, ParserUtils.getDefaultDeserializer(tr), ParserUtils.getDefaultSerializer()); this.enumClass = enumClass; } diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimple.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimple.java index 586b40b1f..ac1bf3419 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimple.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimple.java @@ -18,6 +18,8 @@ package de.fraunhofer.iosb.ilt.frostserver.property.type; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonDeserializer; +import de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils; /** * @@ -32,8 +34,12 @@ protected TypeSimple(String name, String description, TypeReference typeReferenc this(name, description, typeReference, null); } - protected TypeSimple(String name, String description, TypeReference typeReference, Parser parser) { - super(name, description, typeReference); + protected TypeSimple(String name, String description, TypeReference tr, Parser parser) { + this(name, description, ParserUtils.getDefaultDeserializer(tr), parser); + } + + protected TypeSimple(String name, String description, JsonDeserializer deserializer, Parser parser) { + super(name, description, deserializer, ParserUtils.getDefaultSerializer()); if (this instanceof TypeSimplePrimitive typeSimplePrimitive) { this.underlyingType = typeSimplePrimitive; } else { @@ -42,12 +48,14 @@ protected TypeSimple(String name, String description, TypeReference typeReferenc this.parser = parser; } - protected TypeSimple(String name, String description, TypeSimplePrimitive underlyingType, TypeReference typeReference) { - this(name, description, underlyingType, typeReference, null); + protected TypeSimple(String name, String description, TypeSimplePrimitive ut) { + super(name, description, ut.getDeserializer(), ut.getSerializer()); + this.underlyingType = ut; + this.parser = ut.getParser(); } - protected TypeSimple(String name, String description, TypeSimplePrimitive underlyingType, TypeReference typeReference, Parser parser) { - super(name, description, typeReference); + protected TypeSimple(String name, String description, TypeSimplePrimitive underlyingType, TypeReference tr, Parser parser) { + super(name, description, ParserUtils.getDefaultDeserializer(tr), ParserUtils.getDefaultSerializer()); this.underlyingType = underlyingType; this.parser = parser; } @@ -56,6 +64,10 @@ public TypeSimplePrimitive getUnderlyingType() { return underlyingType; } + protected Parser getParser() { + return parser; + } + @Override public Object parseFromUrl(String input) { if (parser != null) { diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimpleCustom.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimpleCustom.java index dc2593a79..5214c422e 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimpleCustom.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimpleCustom.java @@ -17,11 +17,10 @@ */ package de.fraunhofer.iosb.ilt.frostserver.property.type; -import static de.fraunhofer.iosb.ilt.frostserver.model.ext.TypeReferencesHelper.TYPE_REFERENCE_TIMEINSTANT; import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeSimplePrimitive.EDM_DATETIMEOFFSET; import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeSimplePrimitive.EDM_GEOMETRY; -import com.fasterxml.jackson.core.type.TypeReference; +import de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; @@ -38,8 +37,9 @@ public class TypeSimpleCustom extends TypeSimple { public static final String STA_GEOJSON_NAME = "Geometry"; public static final String STA_TM_INSTANT_NAME = "TM_Instant"; - public static final TypeSimpleCustom STA_GEOJSON = new TypeSimpleCustom(STA_GEOJSON_NAME, "A GeoJSON Object", EDM_GEOMETRY, null); - public static final TypeSimpleCustom STA_TM_INSTANT = new TypeSimpleCustom(STA_TM_INSTANT_NAME, "A Time Instant", EDM_DATETIMEOFFSET, TYPE_REFERENCE_TIMEINSTANT); + public static final PropertyType STA_LOCATION = new TypeSimpleCustom(STA_GEOJSON_NAME, "A Free Location object", EDM_GEOMETRY) + .setDeserializer(ParserUtils.getLocationDeserializer()); + public static final PropertyType STA_TM_INSTANT = new TypeSimpleCustom(STA_TM_INSTANT_NAME, "A Time Instant", EDM_DATETIMEOFFSET); private static final Logger LOGGER = LoggerFactory.getLogger(TypeSimpleCustom.class.getName()); private static final Map TYPES = new HashMap<>(); @@ -69,11 +69,7 @@ public static TypeSimpleCustom getType(String name) { } public TypeSimpleCustom(String name, String description, TypeSimplePrimitive underlyingType) { - super(name, description, underlyingType, underlyingType.getTypeReference()); - } - - public TypeSimpleCustom(String name, String description, TypeSimplePrimitive underlyingType, TypeReference typeReference) { - super(name, description, underlyingType, typeReference); + super(name, description, underlyingType); } } diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimplePrimitive.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimplePrimitive.java index 4c357c0bb..eaf980c31 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimplePrimitive.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimplePrimitive.java @@ -18,6 +18,7 @@ package de.fraunhofer.iosb.ilt.frostserver.property.type; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonDeserializer; import de.fraunhofer.iosb.ilt.frostserver.model.ext.TypeReferencesHelper; import de.fraunhofer.iosb.ilt.frostserver.util.Constants; import java.lang.reflect.Field; @@ -148,4 +149,8 @@ private TypeSimplePrimitive(String name, String description, TypeReference typeR super(name, description, typeReference, parser); } + private TypeSimplePrimitive(String name, String description, JsonDeserializer deserializer, Parser parser) { + super(name, description, deserializer, parser); + } + } diff --git a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimpleSet.java b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimpleSet.java index fec33c753..0a1c9cb9c 100644 --- a/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimpleSet.java +++ b/FROST-Server.Core.Model/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/type/TypeSimpleSet.java @@ -18,6 +18,7 @@ package de.fraunhofer.iosb.ilt.frostserver.property.type; import com.fasterxml.jackson.core.type.TypeReference; +import de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils; /** * @@ -28,12 +29,12 @@ public class TypeSimpleSet extends PropertyType { private final PropertyType containtedType; public TypeSimpleSet(TypeSimple containedType, TypeReference typeReference) { - super(containedType.getName(), "Collection of " + containedType.getName(), typeReference); + super(containedType.getName(), "Collection of " + containedType.getName(), ParserUtils.getDefaultDeserializer(typeReference)); this.containtedType = containedType; } public TypeSimpleSet(TypeComplex containedType, TypeReference typeReference) { - super(containedType.getName(), "Collection of " + containedType.getName(), typeReference); + super(containedType.getName(), "Collection of " + containedType.getName(), ParserUtils.getDefaultDeserializer(typeReference)); this.containtedType = containedType; } diff --git a/FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/json/deserialize/custom/CustomEntityDeserializer.java b/FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/json/deserialize/custom/CustomEntityDeserializer.java index cbf5d087c..c4903c6d4 100644 --- a/FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/json/deserialize/custom/CustomEntityDeserializer.java +++ b/FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/json/deserialize/custom/CustomEntityDeserializer.java @@ -19,8 +19,6 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonDeserializer; @@ -33,14 +31,14 @@ import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySet; import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySetImpl; import de.fraunhofer.iosb.ilt.frostserver.property.EntityPropertyMain; -import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain; +import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntity; import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntitySet; import de.fraunhofer.iosb.ilt.frostserver.property.Property; -import de.fraunhofer.iosb.ilt.frostserver.util.ParserUtils; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -48,6 +46,7 @@ */ public class CustomEntityDeserializer extends JsonDeserializer { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomEntityDeserializer.class.getName()); private static final String BUT_FOUND = " but found: "; private static final Map> instancePerModelAndType = new HashMap<>(); @@ -64,34 +63,10 @@ public static CustomEntityDeserializer getInstance(final ModelRegistry modelRegi private final EntityType entityType; private final ModelRegistry modelRegistry; - private final Map propertyByName = new HashMap<>(); public CustomEntityDeserializer(ModelRegistry modelRegistry, EntityType entityType) { this.modelRegistry = modelRegistry; this.entityType = entityType; - final Set propertySet; - propertySet = entityType.getPropertySet(); - - for (Property property : propertySet) { - if (property instanceof EntityPropertyMain epm) { - final PropertyData propertyData = new PropertyData( - property, - property.getType().getTypeReference(), - false, - null); - for (String alias : epm.getAliases()) { - propertyByName.put(alias, propertyData); - } - } else if (property instanceof NavigationPropertyMain npm) { - propertyByName.put( - property.getJsonName(), - new PropertyData( - property, - null, - npm.isEntitySet(), - npm.getEntityType())); - } - } } /** @@ -111,84 +86,54 @@ public Entity deserializeFull(JsonParser parser, DeserializationContext ctxt) th @Override public Entity deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException { - Entity result = new DefaultEntity(entityType); + Entity target = new DefaultEntity(entityType); boolean failOnUnknown = ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); JsonToken currentToken = parser.nextToken(); while (currentToken == JsonToken.FIELD_NAME) { String fieldName = parser.getCurrentName(); - PropertyData propertyData = propertyByName.get(fieldName); - if (propertyData == null) { + Property property = entityType.getProperty(fieldName); + if (property == null) { if (failOnUnknown) { - final String message = "Unknown field: " + fieldName + " on " + entityType.entityName + " expected one of: " + propertyByName.keySet(); + final String message = "Unknown field: " + fieldName + " on " + entityType.entityName + " expected one of: " + entityType.getPropertySet(); throw new UnrecognizedPropertyException(parser, message, parser.getCurrentLocation(), DefaultEntity.class, fieldName, null); } else { parser.nextValue(); parser.readValueAsTree(); } } else { - deserializeProperty(parser, ctxt, result, propertyData); + deserializeProperty(parser, ctxt, property, target); } currentToken = parser.nextToken(); } - return result; - } - - private void deserializeProperty(JsonParser parser, DeserializationContext ctxt, Entity result, PropertyData propertyData) throws IOException { - if (propertyData.property instanceof EntityPropertyMain) { - deserializeEntityProperty(parser, propertyData, result); - } else if (propertyData.property instanceof NavigationPropertyMain) { - deserializeNavigationProperty(propertyData, result, parser, ctxt); - } + return target; } - private void deserializeNavigationProperty(PropertyData propertyData, Entity result, JsonParser parser, DeserializationContext ctxt) throws IOException { - NavigationPropertyMain navPropertyMain = (NavigationPropertyMain) propertyData.property; - if (propertyData.isEntitySet) { - deserialiseEntitySet(parser, ctxt, (NavigationPropertyEntitySet) navPropertyMain, result); - } else { - final EntityType targetEntityType = navPropertyMain.getEntityType(); - JsonToken nextToken = parser.nextToken(); - if (nextToken != JsonToken.START_OBJECT) { - final String message = "Expected start of object for: " + propertyData.property.getName() + " on " + entityType.entityName + BUT_FOUND + nextToken; - throw MismatchedInputException.from(parser, DefaultEntity.class, message); - } - Object value = getInstance(modelRegistry, targetEntityType) - .deserialize(parser, ctxt); - navPropertyMain.setOn(result, value); + private void deserializeProperty(JsonParser parser, DeserializationContext ctxt, Property property, Entity target) throws IOException { + if (property instanceof EntityPropertyMain epm) { + deserializeEntityProperty(parser, ctxt, epm, target); + } else if (property instanceof NavigationPropertyEntity npe) { + deserializeNavigationProperty(parser, ctxt, npe, target); + } else if (property instanceof NavigationPropertyEntitySet npes) { + deserializeNavigationProperty(parser, ctxt, npes, target); } } - private void deserializeEntityProperty(JsonParser parser, PropertyData propertyData, Entity result) throws IOException { - parser.nextValue(); - EntityPropertyMain entityPropertyMain = (EntityPropertyMain) propertyData.property; - if (propertyData.valueTypeRef == null) { - TreeNode value = parser.readValueAsTree(); - entityPropertyMain.setOn(result, value); - } else if (propertyData.property == entityType.getPrimaryKey()) { - Object value = parser.readValueAs(propertyData.valueTypeRef); - entityPropertyMain.setOn(result, ParserUtils.idFromObject(value)); - } else { - Object value = parser.readValueAs(propertyData.valueTypeRef); - entityPropertyMain.setOn(result, value); - } - } - - private void deserialiseEntitySet(JsonParser parser, DeserializationContext ctxt, NavigationPropertyEntitySet navPropertyMain, Entity result) throws IOException { - final EntityType setType = navPropertyMain.getEntityType(); - EntitySet entitySet = new EntitySetImpl(navPropertyMain); + private void deserializeNavigationProperty(JsonParser parser, DeserializationContext ctxt, NavigationPropertyEntitySet npes, Entity result) throws IOException { + final EntityType setType = npes.getEntityType(); + EntitySet entitySet = new EntitySetImpl(npes); CustomEntityDeserializer setEntityDeser = getInstance(modelRegistry, setType); - result.setProperty(navPropertyMain, entitySet); + result.setProperty(npes, entitySet); JsonToken curToken = parser.nextToken(); if (curToken != JsonToken.START_ARRAY) { - final String message = "Expected start of array for: " + navPropertyMain.getName() + " on " + entityType.entityName + BUT_FOUND + curToken; + final String message = "Expected start of array for: " + npes.getName() + " on " + entityType.entityName + BUT_FOUND + curToken; throw MismatchedInputException.from(parser, DefaultEntity.class, message); } curToken = parser.nextToken(); if (curToken != JsonToken.START_OBJECT && curToken != JsonToken.END_ARRAY) { - final String message = "Expected object in array for: " + navPropertyMain.getName() + " on " + entityType.entityName + BUT_FOUND + curToken; + final String message = "Expected object in array for: " + npes.getName() + " on " + entityType.entityName + BUT_FOUND + curToken; throw MismatchedInputException.from(parser, DefaultEntity.class, message); } while (curToken != null && curToken != JsonToken.END_ARRAY) { @@ -197,19 +142,27 @@ private void deserialiseEntitySet(JsonParser parser, DeserializationContext ctxt } } - private static class PropertyData { - - final Property property; - final TypeReference valueTypeRef; - final boolean isEntitySet; - final EntityType setType; - - public PropertyData(Property property, TypeReference valueTypeRef, boolean isEntitySet, EntityType setType) { - this.property = property; - this.valueTypeRef = valueTypeRef; - this.isEntitySet = isEntitySet; - this.setType = setType; + private void deserializeNavigationProperty(JsonParser parser, DeserializationContext ctxt, NavigationPropertyEntity npe, Entity target) throws IOException { + final EntityType targetEntityType = npe.getEntityType(); + JsonToken nextToken = parser.nextToken(); + if (nextToken != JsonToken.START_OBJECT) { + final String message = "Expected start of object for: " + npe.getName() + " on " + entityType.entityName + BUT_FOUND + nextToken; + throw MismatchedInputException.from(parser, DefaultEntity.class, message); } + Entity value = getInstance(modelRegistry, targetEntityType) + .deserialize(parser, ctxt); + npe.setOn(target, value); + } + private void deserializeEntityProperty(JsonParser parser, DeserializationContext ctxt, EntityPropertyMain epm, Entity target) throws IOException { + parser.nextValue(); + final JsonDeserializer deserializer = epm.getType().getDeserializer(); + if (deserializer == null) { + LOGGER.error("Missing deserialiser for {}/{}", entityType, epm); + return; + } + Object value = deserializer.deserialize(parser, ctxt); + epm.setOn(target, value); } + } diff --git a/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/bindings/JsonValue.java b/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/bindings/JsonValue.java index 9a327d002..568be5fc1 100644 --- a/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/bindings/JsonValue.java +++ b/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/bindings/JsonValue.java @@ -21,8 +21,6 @@ import com.fasterxml.jackson.databind.JsonNode; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.Utils; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * @@ -30,10 +28,7 @@ */ public class JsonValue { - private static final Logger LOGGER = LoggerFactory.getLogger(JsonValue.class.getName()); - private Object value; - private TypeReference type; private String stringValue; private int stringLength = 0; @@ -64,19 +59,11 @@ public Object getValue() { } public Map getMapValue() { - return getValue(Utils.TYPE_SORTED_MAP_STRING_OBJECT); + return Utils.jsonToObject(stringValue, Utils.TYPE_SORTED_MAP_STRING_OBJECT); } public T getValue(TypeReference typeReference) { - if (type != null && !type.equals(typeReference)) { - LOGGER.warn("Type Switch, from {} to {}", type, typeReference); - type = null; - } - if (type == null) { - type = typeReference; - value = Utils.jsonToObject(stringValue, typeReference); - } - return (T) value; + return Utils.jsonToObject(stringValue, typeReference); } public int getStringLength() { diff --git a/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/fieldwrapper/StaTimeIntervalWrapper.java b/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/fieldwrapper/StaTimeIntervalWrapper.java index aaededaa2..b34e6d3ef 100644 --- a/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/fieldwrapper/StaTimeIntervalWrapper.java +++ b/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/fieldwrapper/StaTimeIntervalWrapper.java @@ -37,8 +37,8 @@ public class StaTimeIntervalWrapper implements TimeFieldWrapper { private static final Logger LOGGER = LoggerFactory.getLogger(StaTimeIntervalWrapper.class.getName()); - public static final String KEY_TIME_INTERVAL_START = TypeComplex.KEY_INTERVAL_START; - public static final String KEY_TIME_INTERVAL_END = TypeComplex.KEY_INTERVAL_END; + public static final String KEY_TIME_INTERVAL_START = TypeComplex.NAME_INTERVAL_START; + public static final String KEY_TIME_INTERVAL_END = TypeComplex.NAME_INTERVAL_END; private static final String INCOMPATIBLE_OP = "Incompatible operator: Interval '"; /** * Flag indicating that the original time given was in UTC. diff --git a/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/utils/fieldmapper/FieldMapperJson.java b/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/utils/fieldmapper/FieldMapperJson.java index ec9a8f3b3..c86183653 100644 --- a/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/utils/fieldmapper/FieldMapperJson.java +++ b/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/utils/fieldmapper/FieldMapperJson.java @@ -77,7 +77,7 @@ public > void registerMapping(JooqPersistenceManager p (T t, Record tuple, Entity entity, DataSize dataSize) -> { final JsonValue fieldJsonValue = Utils.getFieldJsonValue(tuple, (Field) t.field(idx)); dataSize.increase(fieldJsonValue.getStringLength()); - entity.setProperty(entityProperty, fieldJsonValue.getValue(entityProperty.getType().getTypeReference())); + entity.setProperty(entityProperty, fieldJsonValue.getValue()); }, (t, entity, insertFields) -> insertFields.put(t.field(idx), new JsonValue(entity.getProperty(entityProperty))), (t, entity, updateFields, message) -> { diff --git a/FROST-Server.Util/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/ComplexValue.java b/FROST-Server.Util/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/ComplexValue.java deleted file mode 100644 index 10bc86994..000000000 --- a/FROST-Server.Util/src/main/java/de/fraunhofer/iosb/ilt/frostserver/property/ComplexValue.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 - * Karlsruhe, Germany. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ -package de.fraunhofer.iosb.ilt.frostserver.property; - -/** - * Interface that values of complex properties should implement to make it - * easier to access sub-properties. - * - * @author scf - */ -public interface ComplexValue { - - public Object get(String name); -} diff --git a/Plugins/FormatCsv/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/format/csv/tools/CsvComplexProperty.java b/Plugins/FormatCsv/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/format/csv/tools/CsvComplexProperty.java index 61624f6b8..9258ff204 100644 --- a/Plugins/FormatCsv/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/format/csv/tools/CsvComplexProperty.java +++ b/Plugins/FormatCsv/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/format/csv/tools/CsvComplexProperty.java @@ -17,10 +17,10 @@ */ package de.fraunhofer.iosb.ilt.frostserver.plugin.format.csv.tools; +import de.fraunhofer.iosb.ilt.frostserver.model.ComplexValue; import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity; -import de.fraunhofer.iosb.ilt.frostserver.property.ComplexValue; import de.fraunhofer.iosb.ilt.frostserver.property.EntityProperty; -import de.fraunhofer.iosb.ilt.frostserver.property.type.PropertyType; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex; import java.util.Map; import java.util.TreeMap; @@ -44,7 +44,7 @@ public CsvComplexProperty(String headerPrefix, EntityProperty property) { public void writeHeader(CsvRowCollector collector) { final String baseName = property.getJsonName(); final TypeComplex type = (TypeComplex) property.getType(); - for (Map.Entry subProperty : type.getProperties().entrySet()) { + for (Map.Entry subProperty : type.getPropertiesByName().entrySet()) { String subName = subProperty.getKey(); int idx = collector.registerHeader(headerPrefix + baseName + "/" + subName); subProperties.put(idx, subName); @@ -56,7 +56,7 @@ public void writeData(CsvRowCollector collector, Entity source) { Object value = source.getProperty(property); if (value instanceof ComplexValue complexValue) { for (Map.Entry entry : subProperties.entrySet()) { - collector.collectEntry(entry.getKey(), complexValue.get(entry.getValue())); + collector.collectEntry(entry.getKey(), complexValue.getProperty(entry.getValue())); } } else if (value instanceof Map mapValue) { for (Map.Entry entry : subProperties.entrySet()) { diff --git a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/deserialize/TimeIntervalDeserializer.java b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/deserialize/TimeIntervalDeserializer.java index f5c8281db..4d5bc3954 100644 --- a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/deserialize/TimeIntervalDeserializer.java +++ b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/deserialize/TimeIntervalDeserializer.java @@ -17,8 +17,8 @@ */ package de.fraunhofer.iosb.ilt.frostserver.plugin.odata.deserialize; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_END; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_START; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_END; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_START; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -48,11 +48,11 @@ public TimeInterval deserialize(JsonParser parser, DeserializationContext dc) th while (currentToken == JsonToken.FIELD_NAME) { String fieldName = parser.getCurrentName(); switch (fieldName) { - case KEY_INTERVAL_START: + case NAME_INTERVAL_START: start = TimeValueDeserializer.parseTime(parser); break; - case KEY_INTERVAL_END: + case NAME_INTERVAL_END: end = TimeValueDeserializer.parseTime(parser); break; diff --git a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/deserialize/TimeValueDeserializer.java b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/deserialize/TimeValueDeserializer.java index d7c226b3b..e422a3d08 100644 --- a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/deserialize/TimeValueDeserializer.java +++ b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/deserialize/TimeValueDeserializer.java @@ -17,8 +17,8 @@ */ package de.fraunhofer.iosb.ilt.frostserver.plugin.odata.deserialize; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_END; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_START; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_END; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_START; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -52,11 +52,11 @@ public TimeValue deserialize(JsonParser parser, DeserializationContext dc) throw while (currentToken == JsonToken.FIELD_NAME) { String fieldName = parser.getCurrentName(); switch (fieldName) { - case KEY_INTERVAL_START: + case NAME_INTERVAL_START: start = TimeValueDeserializer.parseTime(parser); break; - case KEY_INTERVAL_END: + case NAME_INTERVAL_END: end = TimeValueDeserializer.parseTime(parser); break; diff --git a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/metadata/CsdlItemComplexType.java b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/metadata/CsdlItemComplexType.java index fdf0abf18..435b6dcbe 100644 --- a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/metadata/CsdlItemComplexType.java +++ b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/metadata/CsdlItemComplexType.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import de.fraunhofer.iosb.ilt.frostserver.property.type.PropertyType; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex; import java.io.IOException; import java.io.Writer; @@ -48,11 +48,11 @@ public class CsdlItemComplexType implements CsdlSchemaItem { public CsdlItemComplexType generateFrom(CsdlDocument doc, String nameSpace, TypeComplex tc) { description = tc.getDescription(); openType = tc.isOpenType(); - for (Entry entry : tc.getProperties().entrySet()) { + for (Entry entry : tc.getPropertiesByName().entrySet()) { final String name = entry.getKey(); - final PropertyType type = entry.getValue(); - final boolean nullable = !tc.isRequired(name); - properties.put(name, new CsdlPropertyEntity().generateFrom(doc, nameSpace, type, nullable)); + final Property prop = entry.getValue(); + final boolean nullable = prop.isNullable(); + properties.put(name, new CsdlPropertyEntity().generateFrom(doc, nameSpace, prop.getType(), nullable)); } return this; } diff --git a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/metadata/MxGraphGenerator.java b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/metadata/MxGraphGenerator.java index f5c0299a1..e49b1443d 100644 --- a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/metadata/MxGraphGenerator.java +++ b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/metadata/MxGraphGenerator.java @@ -32,6 +32,7 @@ import de.fraunhofer.iosb.ilt.frostserver.model.ModelRegistry; import de.fraunhofer.iosb.ilt.frostserver.property.EntityPropertyMain; import de.fraunhofer.iosb.ilt.frostserver.property.NavigationProperty; +import de.fraunhofer.iosb.ilt.frostserver.property.Property; import de.fraunhofer.iosb.ilt.frostserver.property.type.PropertyType; import de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex; import java.io.IOException; @@ -174,7 +175,7 @@ private void addComplexPropertyType(TypeComplex tc, MxCell cellOne, Root root) { globalY += rowHeight + DISTANCE; rowHeight = DISTANCE; } - Map properties = tc.getProperties(); + Map properties = tc.getPropertiesByName(); int boxHeight = BOX_HEIGHT_BASE + properties.size() * BOX_HEIGHT_ITEM; if (boxHeight > rowHeight) { rowHeight = boxHeight; @@ -194,10 +195,10 @@ private void addComplexPropertyType(TypeComplex tc, MxCell cellOne, Root root) { root.addMxCell(typeCell); int listItemY = BOX_HEIGHT_BASE; - for (Map.Entry prop : properties.entrySet()) { - final String name = prop.getKey(); - final PropertyType type = prop.getValue(); - addTypeProperty(listItemY, typeCell, tc, name, type, tc.isRequired(name), root); + for (Map.Entry entry : properties.entrySet()) { + final String name = entry.getKey(); + final Property prop = entry.getValue(); + addTypeProperty(listItemY, typeCell, tc, name, prop.getType(), !prop.isNullable(), root); listItemY += BOX_HEIGHT_ITEM; } } diff --git a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/serialize/TimeIntervalSerializer.java b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/serialize/TimeIntervalSerializer.java index 34aa67f34..3c60602d0 100644 --- a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/serialize/TimeIntervalSerializer.java +++ b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/serialize/TimeIntervalSerializer.java @@ -17,8 +17,8 @@ */ package de.fraunhofer.iosb.ilt.frostserver.plugin.odata.serialize; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_END; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_START; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_END; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_START; import static de.fraunhofer.iosb.ilt.frostserver.util.StringHelper.FORMAT_MOMENT; import com.fasterxml.jackson.core.JsonGenerator; @@ -45,9 +45,9 @@ public void serialize(TimeInterval value, JsonGenerator gen, SerializerProvider final MomentInterval interval = value.getInterval(); final Moment start = interval.getStartAsMoment(); final Moment end = interval.getEndAsMoment(); - gen.writeObjectField(KEY_INTERVAL_START, FORMAT_MOMENT.print(start)); + gen.writeObjectField(NAME_INTERVAL_START, FORMAT_MOMENT.print(start)); if (!start.equals(end)) { - gen.writeObjectField(KEY_INTERVAL_END, FORMAT_MOMENT.print(end)); + gen.writeObjectField(NAME_INTERVAL_END, FORMAT_MOMENT.print(end)); } gen.writeEndObject(); } diff --git a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/serialize/TimeValueSerializer.java b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/serialize/TimeValueSerializer.java index 07e2c0e19..eab6b2a4b 100644 --- a/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/serialize/TimeValueSerializer.java +++ b/Plugins/OData/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/odata/serialize/TimeValueSerializer.java @@ -17,8 +17,8 @@ */ package de.fraunhofer.iosb.ilt.frostserver.plugin.odata.serialize; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_END; -import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.KEY_INTERVAL_START; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_END; +import static de.fraunhofer.iosb.ilt.frostserver.property.type.TypeComplex.NAME_INTERVAL_START; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; @@ -43,14 +43,14 @@ public void serialize(TimeValue value, JsonGenerator gen, SerializerProvider ser } else { gen.writeStartObject(); if (value.isInstant()) { - gen.writeObjectField(KEY_INTERVAL_START, value.asISO8601()); + gen.writeObjectField(NAME_INTERVAL_START, value.asISO8601()); } else { final MomentInterval interval = value.getInterval().getInterval(); final Moment start = interval.getStartAsMoment(); final Moment end = interval.getEndAsMoment(); - gen.writeObjectField(KEY_INTERVAL_START, StringHelper.FORMAT_MOMENT.print(start)); + gen.writeObjectField(NAME_INTERVAL_START, StringHelper.FORMAT_MOMENT.print(start)); if (!start.equals(end)) { - gen.writeObjectField(KEY_INTERVAL_END, StringHelper.FORMAT_MOMENT.print(end)); + gen.writeObjectField(NAME_INTERVAL_END, StringHelper.FORMAT_MOMENT.print(end)); } } gen.writeEndObject(); diff --git a/Plugins/OpenApi/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/openapi/spec/OASchema.java b/Plugins/OpenApi/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/openapi/spec/OASchema.java index 889a2b8b2..e1606bf96 100644 --- a/Plugins/OpenApi/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/openapi/spec/OASchema.java +++ b/Plugins/OpenApi/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/openapi/spec/OASchema.java @@ -206,10 +206,10 @@ public OASchema(Version version, PropertyType propertyType) { } private void addSubtypeComplex(Version version, TypeComplex typeComplex) { - for (var subPropEntry : typeComplex.getProperties().entrySet()) { + for (var subPropEntry : typeComplex.getPropertiesByName().entrySet()) { var subPropName = subPropEntry.getKey(); - var subPropType = subPropEntry.getValue(); - addProperty(subPropName, new OASchema(version, subPropType)); + var subProp = subPropEntry.getValue(); + addProperty(subPropName, new OASchema(version, subProp.getType())); } }