diff --git a/pom.xml b/pom.xml index 5c42300..f1675b2 100644 --- a/pom.xml +++ b/pom.xml @@ -14,8 +14,8 @@ UTF-8 - 11 - 11 + 17 + 17 de.fraunhofer.iosb.ilt.sensorthingsmanager.MainApp 3.11.0 @@ -32,7 +32,7 @@ 0.34 1.4.6 19.0.2.1 - 0.44 + 2.2-SNAPSHOT @@ -200,7 +200,7 @@ ${project.groupId} - FROST-Client + FROST-Client-Dynamic ${FROST-Client.version} diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/MainApp.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/MainApp.java index e978601..2b1eba5 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/MainApp.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/MainApp.java @@ -17,7 +17,7 @@ */ package de.fraunhofer.iosb.ilt.sensorthingsmanager; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; +import de.fraunhofer.iosb.ilt.frostclient.exception.ServiceFailureException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URISyntaxException; diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregateCombo.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregateCombo.java index 2f8f09c..9365acf 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregateCombo.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregateCombo.java @@ -16,29 +16,35 @@ */ package de.fraunhofer.iosb.ilt.sensorthingsmanager.aggregation; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.dao.BaseDao; -import de.fraunhofer.iosb.ilt.sta.model.Datastream; -import de.fraunhofer.iosb.ilt.sta.model.EntityType; -import de.fraunhofer.iosb.ilt.sta.model.Id; -import de.fraunhofer.iosb.ilt.sta.model.MultiDatastream; -import de.fraunhofer.iosb.ilt.sta.model.Observation; -import de.fraunhofer.iosb.ilt.sta.model.Thing; -import de.fraunhofer.iosb.ilt.sta.model.TimeObject; -import de.fraunhofer.iosb.ilt.sta.model.ext.EntityList; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.dao.Dao; +import de.fraunhofer.iosb.ilt.frostclient.exception.ServiceFailureException; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.EntitySet; +import de.fraunhofer.iosb.ilt.frostclient.model.EntityType; +import de.fraunhofer.iosb.ilt.frostclient.model.ext.TimeInterval; +import de.fraunhofer.iosb.ilt.frostclient.model.ext.TimeValue; +import de.fraunhofer.iosb.ilt.frostclient.model.property.NavigationPropertyEntitySet; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11; +import de.fraunhofer.iosb.ilt.frostclient.models.ext.MapValue; +import static de.fraunhofer.iosb.ilt.frostclient.utils.ParserUtils.formatKeyValuesForUrl; import java.time.DateTimeException; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; -import java.util.Iterator; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; +import net.time4j.ClockUnit; +import net.time4j.Moment; +import net.time4j.ZonalDateTime; +import net.time4j.tz.TZID; +import net.time4j.tz.Timezone; import org.apache.commons.lang3.builder.CompareToBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.threeten.extra.Interval; /** * @@ -51,10 +57,11 @@ public class AggregateCombo implements Comparable { */ private static final Logger LOGGER = LoggerFactory.getLogger(AggregateCombo.class); - public final Thing targetThing; - public final MultiDatastream target; - public Datastream sourceDs; - public MultiDatastream sourceMds; + private final SensorThingsService service; + public final Entity targetThing; + public final Entity targetMds; + public Entity sourceDs; + public Entity sourceMds; public boolean sourceIsAggregate; /** * Indicates that observations in the source contain a list of values. @@ -62,12 +69,13 @@ public class AggregateCombo implements Comparable { public boolean sourceIsCollection = false; public AggregationLevel level; public String baseName; - private ZoneId zoneId; - private Interval currentInterval; + private TZID zoneId; + private TimeInterval currentInterval; - public AggregateCombo(Thing targetThing, MultiDatastream target) { + public AggregateCombo(SensorThingsService service, Entity targetThing, Entity target) { + this.service = service; this.targetThing = targetThing; - this.target = target; + this.targetMds = target; } public boolean hasSource() { @@ -76,44 +84,50 @@ public boolean hasSource() { public EntityType getSourceType() { if (sourceDs != null) { - return EntityType.DATASTREAM; + return sourceDs.getEntityType(); } if (sourceMds != null) { - return EntityType.MULTIDATASTREAM; + return sourceMds.getEntityType(); } return null; } - public Id getSourceId() { + public Object[] getSourceId() { if (sourceDs != null) { - return sourceDs.getId(); + return sourceDs.getPrimaryKeyValues(); } if (sourceMds != null) { - return sourceMds.getId(); + return sourceMds.getPrimaryKeyValues(); } return null; } - public BaseDao getObsDaoForSource() { + public Dao getObsDaoForSource() { + final EntityType sourceType = getSourceType(); + if (sourceType == null) { + return null; + } + NavigationPropertyEntitySet npes = sourceType.getNavigationPropertySet("Observations"); if (sourceDs != null) { - return sourceDs.observations(); + return sourceDs.dao(npes); } if (sourceMds != null) { - return sourceMds.observations(); + return sourceMds.dao(npes); } return null; } - public Observation getLastForTarget() { + public Entity getLastForTarget() { try { - return target.observations().query().select("id", "phenomenonTime").orderBy("phenomenonTime desc").first(); + NavigationPropertyEntitySet npObs = targetMds.getEntityType().getNavigationPropertySet("Observations"); + return targetMds.query(npObs).select("id", "phenomenonTime").orderBy("phenomenonTime desc").first(); } catch (ServiceFailureException ex) { LOGGER.error("Error fetching last observation.", ex); return null; } } - public Observation getFirstForSource() { + public Entity getFirstForSource() { try { if (hasSource()) { return getObsDaoForSource().query().select("id", "phenomenonTime").orderBy("phenomenonTime asc").first(); @@ -125,7 +139,7 @@ public Observation getFirstForSource() { } } - public Observation getLastForSource() { + public Entity getLastForSource() { try { if (hasSource()) { return getObsDaoForSource().query().select("id", "phenomenonTime").orderBy("phenomenonTime desc").first(); @@ -137,15 +151,14 @@ public Observation getLastForSource() { } } - public List getObservationsForSource(Instant start, Instant end) { - List result = new ArrayList<>(); + public List getObservationsForSource(Instant start, Instant end) { + List result = new ArrayList<>(); if (hasSource()) { try { StringBuilder filter = new StringBuilder(); filter.append("overlaps(phenomenonTime,").append(start.toString()).append("/").append(end.toString()).append(")"); - EntityList entityList = getObsDaoForSource().query().filter(filter.toString()).orderBy("phenomenonTime asc").top(1000).list(); - for (Iterator it = entityList.fullIterator(); it.hasNext();) { - Observation entity = it.next(); + EntitySet entityList = getObsDaoForSource().query().filter(filter.toString()).orderBy("phenomenonTime asc").top(1000).list(); + for (Entity entity : entityList) { result.add(entity); } } catch (ServiceFailureException ex) { @@ -155,15 +168,15 @@ public List getObservationsForSource(Instant start, Instant end) { return result; } - public void resolveZoneId(ZoneId dflt) { + public void resolveZoneId(TZID dflt) { if (zoneId == null) { - Map properties = targetThing.getProperties(); + MapValue properties = targetThing.getProperty(SensorThingsSensingV11.EP_PROPERTIES); Object zoneName = properties.get("timeZone"); if (zoneName == null || zoneName.toString().isEmpty()) { zoneId = dflt; } else { try { - zoneId = ZoneId.of(zoneName.toString()); + zoneId = Timezone.normalize(zoneName.toString()); } catch (DateTimeException ex) { LOGGER.warn("Invalid zone: " + zoneName, ex); zoneId = dflt; @@ -172,32 +185,32 @@ public void resolveZoneId(ZoneId dflt) { } } - public ZoneId getZoneId() { + public TZID getZoneId() { return zoneId; } public String getSourceObsMqttPath() { if (sourceDs != null) { - return "v1.0/Datastreams(" + sourceDs.getId() + ")/Observations?$select=id,phenomenonTime"; + return "v1.0/Datastreams(" + formatKeyValuesForUrl(sourceDs) + ")/Observations?$select=id,phenomenonTime"; } if (sourceMds != null) { - return "v1.0/MultiDatastreams(" + sourceMds.getId() + ")/Observations?$select=id,phenomenonTime"; + return "v1.0/MultiDatastreams(" + formatKeyValuesForUrl(sourceMds) + ")/Observations?$select=id,phenomenonTime"; } return ""; } - public List calculateIntervalsForTime(TimeObject phenTime) { - List retval = new ArrayList<>(); - Instant phenTimeStart = Utils.getPhenTimeStart(phenTime); - Instant phenTimeEnd = Utils.getPhenTimeEnd(phenTime); - ZonedDateTime atZone = phenTimeStart.atZone(getZoneId()); - ZonedDateTime intStart = level.toIntervalStart(atZone); - ZonedDateTime intEnd = intStart.plus(level.amount, level.unit); - retval.add(Interval.of(intStart.toInstant(), intEnd.toInstant())); - while (intEnd.toInstant().isBefore(phenTimeEnd)) { + public List calculateIntervalsForTime(TimeValue phenTime) { + List retval = new ArrayList<>(); + Moment phenTimeStart = Utils.getPhenTimeStart(phenTime); + Moment phenTimeEnd = Utils.getPhenTimeEnd(phenTime); + ZonalDateTime atZone = phenTimeStart.inZonalView(getZoneId()); + Moment intStart = ZonalDateTime.from(level.toIntervalStart(atZone.toTemporalAccessor())).toMoment(); + Moment intEnd = Moment.from(intStart.toTemporalAccessor().plus(level.amount, level.unit)); + retval.add(TimeInterval.create(intStart, intEnd)); + while (intEnd.isBefore(phenTimeEnd)) { intStart = intEnd; - intEnd = intStart.plus(level.amount, level.unit); - retval.add(Interval.of(intStart.toInstant(), intEnd.toInstant())); + intEnd = Moment.from(intStart.toTemporalAccessor().plus(level.amount, level.unit)); + retval.add(TimeInterval.create(intStart, intEnd)); } return retval; } @@ -211,7 +224,7 @@ public List calculateIntervalsForTime(TimeObject phenTime) { * @return null if the given interval is the same as the current interval, * otherwise the current interval. */ - public Interval replaceIfNotCurrent(Interval other) { + public TimeInterval replaceIfNotCurrent(TimeInterval other) { if (currentInterval == null) { // There is no interval yet. This happens the first time at startup. currentInterval = other; @@ -222,7 +235,7 @@ public Interval replaceIfNotCurrent(Interval other) { return null; } else { // The interval changed. Recalculate the old interval. - Interval old = currentInterval; + TimeInterval old = currentInterval; currentInterval = other; return old; } @@ -236,7 +249,7 @@ public Interval replaceIfNotCurrent(Interval other) { * @param other The interval to check against the current interval. * @return null if the given interval is the same as the current interval. */ - public Interval unsetCurrent(Interval other) { + public TimeInterval unsetCurrent(TimeInterval other) { if (currentInterval == null) { // There is no interval. return null; @@ -247,7 +260,7 @@ public Interval unsetCurrent(Interval other) { return null; } else { // The interval is different. Recalculate the old interval. - Interval old = currentInterval; + TimeInterval old = currentInterval; currentInterval = null; return old; } @@ -268,12 +281,12 @@ public boolean equals(Object obj) { if (!baseName.equals(otherCombo.baseName)) { return false; } - return target.getId().equals(otherCombo.target.getId()); + return Arrays.equals(targetMds.getPrimaryKeyValues(), otherCombo.targetMds.getPrimaryKeyValues()); } @Override public int hashCode() { - return Objects.hash(target, level, baseName); + return Objects.hash(targetMds, level, baseName); } @Override @@ -287,12 +300,12 @@ public int compareTo(AggregateCombo o) { @Override public String toString() { if (sourceDs != null) { - return baseName + " " + level + ". (d " + sourceDs.getId() + " -> md " + target.getId() + ")"; + return baseName + " " + level + ". (d " + Arrays.toString(sourceDs.getPrimaryKeyValues()) + " -> md " + Arrays.toString(targetMds.getPrimaryKeyValues()) + ")"; } if (sourceMds != null) { - return baseName + " " + level + ". (md " + sourceMds.getId() + " -> md " + target.getId() + ")"; + return baseName + " " + level + ". (md " + Arrays.toString(sourceMds.getPrimaryKeyValues()) + " -> md " + Arrays.toString(targetMds.getPrimaryKeyValues()) + ")"; } - return baseName + " " + level + ". (? -> md " + target.getId() + ")"; + return baseName + " " + level + ". (? -> md " + Arrays.toString(targetMds.getPrimaryKeyValues()) + ")"; } public String getBaseName() { diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregationBase.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregationBase.java index 9f263a2..1e3c975 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregationBase.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregationBase.java @@ -16,8 +16,7 @@ */ package de.fraunhofer.iosb.ilt.sensorthingsmanager.aggregation; -import de.fraunhofer.iosb.ilt.sta.model.Datastream; -import de.fraunhofer.iosb.ilt.sta.model.MultiDatastream; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -37,8 +36,8 @@ public class AggregationBase { private static final Logger LOGGER = LoggerFactory.getLogger(AggregationBase.class); private final String baseName; - private Datastream baseDatastream; - private MultiDatastream baseMultiDatastream; + private Entity baseDatastream; + private Entity baseMultiDatastream; private final Set combos = new TreeSet<>(); private final Map combosByLevel = new HashMap<>(); @@ -50,7 +49,7 @@ public AggregationBase(String baseName) { this.baseName = baseName; } - public AggregationBase(String baseName, Datastream baseDatastream, MultiDatastream baseMultiDatastream) { + public AggregationBase(String baseName, Entity baseDatastream, Entity baseMultiDatastream) { this.baseName = baseName; this.baseDatastream = baseDatastream; this.baseMultiDatastream = baseMultiDatastream; @@ -103,19 +102,19 @@ public Map getWantedLevels() { return wantedLevels; } - public Datastream getBaseDatastream() { + public Entity getBaseDatastream() { return baseDatastream; } - public void setBaseDatastream(Datastream baseDatastream) { + public void setBaseDatastream(Entity baseDatastream) { this.baseDatastream = baseDatastream; } - public MultiDatastream getBaseMultiDatastream() { + public Entity getBaseMultiDatastream() { return baseMultiDatastream; } - public void setBaseMultiDatastream(MultiDatastream baseMultiDatastream) { + public void setBaseMultiDatastream(Entity baseMultiDatastream) { this.baseMultiDatastream = baseMultiDatastream; } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregationData.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregationData.java index 132a87a..2ea0da9 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregationData.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/AggregationData.java @@ -16,25 +16,30 @@ */ package de.fraunhofer.iosb.ilt.sensorthingsmanager.aggregation; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.exception.ServiceFailureException; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.EntitySet; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsMultiDatastreamV11; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsMultiDatastreamV11.EP_MULTIOBSERVATIONDATATYPES; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsMultiDatastreamV11.EP_UNITOFMEASUREMENTS; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_NAME; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_PROPERTIES; +import de.fraunhofer.iosb.ilt.frostclient.models.ext.MapValue; +import de.fraunhofer.iosb.ilt.frostclient.query.Query; +import static de.fraunhofer.iosb.ilt.frostclient.utils.ParserUtils.formatKeyValuesForUrl; import static de.fraunhofer.iosb.ilt.sensorthingsmanager.aggregation.Utils.KEY_AGGREGATE_SOURCE_D; import static de.fraunhofer.iosb.ilt.sensorthingsmanager.aggregation.Utils.KEY_AGGREGATE_SOURCE_MD; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.model.Datastream; -import de.fraunhofer.iosb.ilt.sta.model.MultiDatastream; -import de.fraunhofer.iosb.ilt.sta.model.Thing; -import de.fraunhofer.iosb.ilt.sta.model.ext.EntityList; -import de.fraunhofer.iosb.ilt.sta.query.Query; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; -import java.time.ZoneId; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Matcher; +import net.time4j.tz.TZID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,18 +62,22 @@ public static interface ProgressListener { private final List aggregationBases = new ArrayList<>(); private final Map aggregationBasesByName = new HashMap<>(); private Map> combosBySource; - private ZoneId zoneId; + private TZID zoneId; private final boolean fixReferences; private final boolean addEmptyBases; private final boolean sourceEqualsTarget = true; private double progressBase = 0; private double progressTarget = 1; private final List progressListeners = new CopyOnWriteArrayList<>(); + private final SensorThingsSensingV11 sMdl; + private final SensorThingsMultiDatastreamV11 mMdl; public AggregationData(SensorThingsService service, boolean fixReferences, boolean addEmptyBases) { this.service = service; this.fixReferences = fixReferences; this.addEmptyBases = addEmptyBases; + sMdl = service.getModel(SensorThingsSensingV11.class); + mMdl = service.getModel(SensorThingsMultiDatastreamV11.class); } public AggregationData(SensorThingsService service, boolean fixReferences) { @@ -89,22 +98,19 @@ private AggregationBase getAggregationBase(String baseName) { private void findAllBases() { try { - Query query = service.datastreams() - .query() + Query query = service.query(sMdl.etDatastream) .select("id", "name", "description", "properties", "unitOfMeasurement") .top(1000) .orderBy("id asc"); if (hasListeners()) { query.count(); } - EntityList dsList = query.list(); + EntitySet dsList = query.list(); long count = dsList.getCount(); double pPart = (progressTarget - progressBase) / count; int nr = 0; - Iterator datastreams = dsList.fullIterator(); - while (datastreams.hasNext()) { - Datastream datastream = datastreams.next(); - String name = datastream.getName(); + for (Entity datastream : dsList) { + String name = datastream.getProperty(EP_NAME); String base = baseNameFromName(name); AggregationBase aggregationBase = getAggregationBase(base); aggregationBase.setBaseDatastream(datastream); @@ -119,8 +125,7 @@ private void findAllBases() { private void findTargetMultiDatastreams() { try { - Query query = service.things() - .query() + Query query = service.query(sMdl.etThing) .top(1000) .select("id,name,properties") .orderBy("id asc") @@ -128,23 +133,20 @@ private void findTargetMultiDatastreams() { if (hasListeners()) { query.count(); } - EntityList thingList = query.list(); + EntitySet thingList = query.list(); long count = thingList.getCount(); double pPart = (progressTarget - progressBase) / count; int nr = 0; - Iterator thingIt = thingList.fullIterator(); - while (thingIt.hasNext()) { - Thing thing = thingIt.next(); - EntityList dsList = thing.getMultiDatastreams(); - for (Iterator it = dsList.fullIterator(); it.hasNext();) { - MultiDatastream mds = it.next(); - String name = mds.getName(); + for (Entity thing : thingList) { + EntitySet dsList = thing.getProperty(mMdl.npThingMultidatastreams); + for (Entity mds : dsList) { + String name = mds.getProperty(EP_NAME); Matcher matcher = Utils.POSTFIX_PATTERN.matcher(name); if (!matcher.matches()) { LOGGER.debug("MultiDatastream {} is not an aggregate."); continue; } - AggregateCombo combo = new AggregateCombo(thing, mds); + AggregateCombo combo = new AggregateCombo(service, thing, mds); combo.baseName = matcher.group(1).trim(); String postfix = matcher.group(2); combo.level = AggregationLevel.of(postfix); @@ -153,7 +155,7 @@ private void findTargetMultiDatastreams() { continue; } combo.resolveZoneId(zoneId); - LOGGER.debug("Found: {} from {}, timeZone {}", combo.level, combo.target.getName(), combo.getZoneId()); + LOGGER.debug("Found: {} from {}, timeZone {}", combo.level, combo.targetMds.getProperty(EP_NAME), combo.getZoneId()); AggregationBase aggBase = getAggregationBase(combo.baseName); aggBase.addCombo(combo); } @@ -171,14 +173,13 @@ private void findSourceDatastreams(AggregateCombo target) { if (base != null && base.getBaseDatastream() != null) { target.sourceDs = base.getBaseDatastream(); target.sourceIsAggregate = false; - checkReference(target.sourceDs, target.target, target.level); + checkReferenceFromDs(target.sourceDs, target.targetMds, target.level); return; } String nameQuoted = "'" + target.baseName.replaceAll("'", "''") + "'"; { - List list = service.multiDatastreams() - .query() + List list = service.query(mMdl.etMultiDatastream) .filter("name eq " + nameQuoted) .top(1000) .orderBy("id asc") @@ -187,24 +188,22 @@ private void findSourceDatastreams(AggregateCombo target) { if (list.size() > 1) { LOGGER.warn("Multiple ({}) sources found for '{}'.", list.size(), target.baseName); } - if (list.size() > 0) { + if (!list.isEmpty()) { target.sourceMds = list.get(0); target.sourceIsAggregate = false; - checkReference(target.sourceMds, target.target, target.level); + checkReferenceFromDs(target.sourceMds, target.targetMds, target.level); return; } } { - List list = service.datastreams() - .query() + List list = service.query(sMdl.etDatastream) .filter("name eq " + nameQuoted) .top(1000) .orderBy("id asc") .list() .toList(); if (list.isEmpty()) { - list = service.datastreams() - .query() + list = service.query(sMdl.etDatastream) .filter("startswith(name," + nameQuoted + ")") .top(1000) .orderBy("id asc") @@ -214,15 +213,15 @@ private void findSourceDatastreams(AggregateCombo target) { if (list.size() > 1) { LOGGER.warn("Multiple ({}) sources found for '{}'.", list.size(), target.baseName); } - for (Datastream source : list) { - String postfix = source.getName().substring(target.baseName.length()); + for (Entity sourceDs : list) { + String postfix = sourceDs.getProperty(EP_NAME).substring(target.baseName.length()); if (!AggregationLevel.isPostfix(postfix)) { continue; } - target.sourceDs = source; + target.sourceDs = sourceDs; target.sourceIsAggregate = false; target.sourceIsCollection = true; - checkReference(target.sourceDs, target.target, target.level); + checkReferenceFromDs(target.sourceDs, target.targetMds, target.level); return; } } @@ -248,10 +247,10 @@ private void findSourceDatastreams(AggregationBase base) { long larger = target.level.duration.getSeconds(); if (larger % smaller == 0) { LOGGER.debug("{}: {} ~ {} ({})", target.baseName, target.level, test.level, (larger / smaller)); - target.sourceMds = test.target; + target.sourceMds = test.targetMds; target.sourceIsAggregate = true; found = true; - checkReference(target.sourceMds, target.target, target.level); + checkReferenceFromDs(target.sourceMds, target.targetMds, target.level); } } if (!found) { @@ -354,35 +353,35 @@ public Map> getComboBySource(boolean recalculate) { return combosBySource; } - private void checkReference(Datastream source, MultiDatastream aggregate, AggregationLevel level) { + private void checkReferenceFromDs(Entity sourceDs, Entity aggregateMds, AggregationLevel level) { String expectedAggFor; String aggKey = null; Object aggId = null; if (sourceEqualsTarget) { - expectedAggFor = "/Datastreams(" + source.getId().getUrl() + ")"; + expectedAggFor = "/Datastreams(" + formatKeyValuesForUrl(sourceDs.getPrimaryKeyValues()) + ")"; aggKey = KEY_AGGREGATE_SOURCE_D; - aggId = source.getId().getValue(); + aggId = formatKeyValuesForUrl(sourceDs.getPrimaryKeyValues()); } else { - expectedAggFor = source.getSelfLink().toString(); + expectedAggFor = sourceDs.getSelfLink(); } - checkReference(aggregate, expectedAggFor, level, aggKey, aggId); + checkReference(aggregateMds, expectedAggFor, level, aggKey, aggId); } - private void checkReference(MultiDatastream source, MultiDatastream aggregate, AggregationLevel level) { + private void checkReferenceFromMds(Entity sourceMds, Entity aggregateMds, AggregationLevel level) { String expectedAggFor; String aggKey = null; Object aggId = null; if (sourceEqualsTarget) { - expectedAggFor = "/MultiDatastreams(" + source.getId().getUrl() + ")"; + expectedAggFor = "/MultiDatastreams(" + formatKeyValuesForUrl(sourceMds.getPrimaryKeyValues()) + ")"; aggKey = KEY_AGGREGATE_SOURCE_MD; - aggId = source.getId().getValue(); + aggId = formatKeyValuesForUrl(sourceMds.getPrimaryKeyValues()); } else { - expectedAggFor = source.getSelfLink().toString(); + expectedAggFor = sourceMds.getSelfLink(); } - checkReference(aggregate, expectedAggFor, level, aggKey, aggId); + checkReference(aggregateMds, expectedAggFor, level, aggKey, aggId); } - private boolean checkProperty(Map properties, String property, Object value) { + private boolean checkProperty(MapValue properties, String property, Object value) { Object checkValue = value; boolean changed = false; Object oldValue = properties.get(property); @@ -401,11 +400,11 @@ private boolean checkProperty(Map properties, String property, O return changed; } - private void checkReference(MultiDatastream aggregate, String expectedAggFor, AggregationLevel level, String aggSourceKey, Object aggSourceId) { - Map properties = aggregate.getProperties(); + private void checkReference(Entity aggregateMds, String expectedAggFor, AggregationLevel level, String aggSourceKey, Object aggSourceId) { + MapValue properties = aggregateMds.getProperty(EP_PROPERTIES); if (properties == null) { - properties = new HashMap<>(); - aggregate.setProperties(properties); + properties = new MapValue(); + aggregateMds.setProperty(EP_PROPERTIES, properties); } boolean changed = false; changed = changed | checkProperty(properties, Utils.KEY_AGGREGATE_AMOUNT, level.amount); @@ -417,27 +416,27 @@ private void checkReference(MultiDatastream aggregate, String expectedAggFor, Ag String aggFor = Objects.toString(properties.get(Utils.KEY_AGGREGATE_FOR)); if (!expectedAggFor.equals(aggFor)) { if (fixReferences) { - LOGGER.info("Setting source reference for {} to {}.", aggregate.getName(), expectedAggFor); + LOGGER.info("Setting source reference for {} to {}.", aggregateMds.getProperty(EP_NAME), expectedAggFor); properties.put(Utils.KEY_AGGREGATE_FOR, expectedAggFor); changed = true; } else { - LOGGER.info("Source reference for {} not correct. Should be {}.", aggregate.getName(), expectedAggFor); + LOGGER.info("Source reference for {} not correct. Should be {}.", aggregateMds.getProperty(EP_NAME), expectedAggFor); } } if (changed && fixReferences) { try { - MultiDatastream copy = aggregate.withOnlyId(); - copy.setProperties(aggregate.getProperties()); - copy.setMultiObservationDataTypes(null); - copy.setUnitOfMeasurements(null); - service.update(copy); + Entity copyMds = aggregateMds.withOnlyPk(); + copyMds.setProperty(EP_PROPERTIES, aggregateMds.getProperty(EP_PROPERTIES)); + copyMds.setProperty(EP_MULTIOBSERVATIONDATATYPES, null); + copyMds.setProperty(EP_UNITOFMEASUREMENTS, null); + service.update(copyMds); } catch (ServiceFailureException ex) { LOGGER.error("Failed to update reference.", ex); } } } - public void setZoneId(ZoneId zoneId) { + public void setZoneId(TZID zoneId) { this.zoneId = zoneId; } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/ControllerAggManager.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/ControllerAggManager.java index e6de41c..da24986 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/ControllerAggManager.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/ControllerAggManager.java @@ -18,17 +18,22 @@ import de.fraunhofer.iosb.ilt.configurable.ConfigurationException; import de.fraunhofer.iosb.ilt.configurable.editor.EditorMap; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.exception.ServiceFailureException; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.ext.TimeValue; +import de.fraunhofer.iosb.ilt.frostclient.model.ext.UnitOfMeasurement; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsMultiDatastreamV11; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_DESCRIPTION; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_PHENOMENONTIME; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_UNITOFMEASUREMENT; +import de.fraunhofer.iosb.ilt.frostclient.models.ext.MapValue; +import de.fraunhofer.iosb.ilt.frostclient.utils.CollectionsHelper; +import de.fraunhofer.iosb.ilt.frostclient.utils.ParserUtils; import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.ButtonTableCell; import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.DateTimePicker; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.model.Datastream; -import de.fraunhofer.iosb.ilt.sta.model.Observation; -import de.fraunhofer.iosb.ilt.sta.model.ObservedProperty; -import de.fraunhofer.iosb.ilt.sta.model.TimeObject; -import de.fraunhofer.iosb.ilt.sta.model.ext.UnitOfMeasurement; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; import java.net.URL; -import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.HashMap; @@ -64,9 +69,9 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.text.Text; +import net.time4j.Moment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.threeten.extra.Interval; /** * @@ -105,6 +110,8 @@ public Void getValue() { private ProgressBar progressBar; private SensorThingsService service; + private SensorThingsSensingV11 sMdl; + private SensorThingsMultiDatastreamV11 mMdl; private AggregationData data; @@ -113,8 +120,8 @@ public Void getValue() { private Map> columnsByLevel = new HashMap<>(); private EditorMap levelEditor; private SensorThingsUtils utils = new SensorThingsUtils(); - private Instant lastPickedStart; - private Instant lastPickedEnd; + private Moment lastPickedStart; + private Moment lastPickedEnd; @Override public void initialize(URL location, ResourceBundle resources) { @@ -129,6 +136,8 @@ public void initialize(URL location, ResourceBundle resources) { public void setService(SensorThingsService service) { this.service = service; buttonReload.setDisable(false); + sMdl = service.getModel(SensorThingsSensingV11.class); + mMdl = service.getModel(SensorThingsMultiDatastreamV11.class); } private void addMenuToColumn(final TableColumn column, final AggregationLevel level) { @@ -183,17 +192,17 @@ private TableColumn getColumnForLevel(final Aggregatio return column; } - private void reCalculateBase(AggregationBase base, Instant start, Instant end) { + private void reCalculateBase(AggregationBase base, Moment start, Moment end) { try { - Datastream baseDs = base.getBaseDatastream(); + Entity baseDs = base.getBaseDatastream(); if (baseDs == null) { LOGGER.error("No base Datastream for {}", base.getBaseName()); } - Observation dummy = new Observation("Dummy", baseDs); - dummy.setPhenomenonTime(new TimeObject(Interval.of(start, end))); + Entity dummyObs = sMdl.newObservation("Dummy", baseDs); + dummyObs.setProperty(EP_PHENOMENONTIME, TimeValue.create(start, end)); - service.create(dummy); - service.delete(dummy); + service.create(dummyObs); + service.delete(dummyObs); } catch (ServiceFailureException ex) { LOGGER.error("Failed to create or delete dummy observation!", ex); } @@ -221,9 +230,9 @@ private void reCalculateBase(AggregationBase base) { dialog.getDialogPane().setExpandableContent(new Text("This will create a new Observation in the given Datastream, and directly delete it again.")); Optional confirmation = dialog.showAndWait(); - Instant startDateTime = startTime.getValue().toInstant(); + Moment startDateTime = Moment.from(startTime.getValue().toInstant()); lastPickedStart = startDateTime; - Instant endDateTime = endTime.getValue().toInstant(); + Moment endDateTime = Moment.from(endTime.getValue().toInstant()); lastPickedEnd = endDateTime; if (confirmation.isPresent() && confirmation.get() == ButtonType.APPLY) { @@ -362,27 +371,31 @@ protected Void call() throws Exception { private void createAggregate(AggregationBase base, AggregationLevel level) throws ServiceFailureException { LOGGER.info("Creating {} for {}.", level, base.getBaseName()); - Datastream baseDs = base.getBaseDatastream(); - ObservedProperty op = baseDs.getObservedProperty(); - UnitOfMeasurement uom = baseDs.getUnitOfMeasurement(); + Entity baseDs = base.getBaseDatastream(); + Entity op = baseDs.getProperty(sMdl.npDatastreamObservedproperty); + UnitOfMeasurement uom = baseDs.getProperty(EP_UNITOFMEASUREMENT); utils.findOrCreateAggregateOps(service, op); - List ops = new ArrayList<>(); + List ops = new ArrayList<>(); ops.add(op); ops.addAll(utils.aggregateProperties.get(op)); List uoms = new ArrayList<>(); - for (ObservedProperty op1 : ops) { + for (Entity op1 : ops) { uoms.add(uom); } - Map aggProps = new HashMap<>(); - aggProps.put(Utils.KEY_AGGREGATE_SOURCE_D, baseDs.getId().getValue()); - aggProps.put(Utils.KEY_AGGREGATE_FOR, "/Datastreams(" + baseDs.getId().getUrl() + ")"); - aggProps.put(Utils.KEY_AGGREGATE_AMOUNT, level.amount); - aggProps.put(Utils.KEY_AGGREGATE_UNIT, level.unit.toString()); + MapValue aggProps = CollectionsHelper.propertiesBuilder() + .addItem(Utils.KEY_AGGREGATE_SOURCE_D, ParserUtils.formatKeyValuesForUrl(baseDs.getPrimaryKeyValues())) + .addItem(Utils.KEY_AGGREGATE_FOR, "/Datastreams(" + ParserUtils.formatKeyValuesForUrl(baseDs.getPrimaryKeyValues()) + ")") + .addItem(Utils.KEY_AGGREGATE_AMOUNT, level.amount) + .addItem(Utils.KEY_AGGREGATE_UNIT, level.unit.toString()) + .build(); String mdsName = base.getBaseName() + " " + level.toPostFix(); - String mdsDesc = baseDs.getDescription() + " aggregated per " + level.amount + " " + level.unit; - utils.findOrCreateMultiDatastream(service, mdsName, mdsDesc, uoms, baseDs.getThing(), ops, baseDs.getSensor(), aggProps); + String mdsDesc = baseDs.getProperty(EP_DESCRIPTION) + " aggregated per " + level.amount + " " + level.unit; + utils.findOrCreateMultiDatastream( + service, mdsName, mdsDesc, uoms, + baseDs.getProperty(sMdl.npDatastreamThing), ops, + baseDs.getProperty(sMdl.npDatastreamSensor), aggProps); } private void deleteAggregate(AggregationBase base, AggregationLevel level) { @@ -393,9 +406,9 @@ private void deleteAggregate(AggregationBase base, AggregationLevel level) { } LOGGER.error("Deleting {} for {}", level, base.getBaseName()); try { - service.delete(combo.target); + service.delete(combo.targetMds); } catch (ServiceFailureException ex) { - LOGGER.error("Failed to delete {}", combo.target); + LOGGER.error("Failed to delete {}", combo.targetMds); LOGGER.error("Failed to delete:", ex); } } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/SensorThingsUtils.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/SensorThingsUtils.java index 4c5b929..b0c2d44 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/SensorThingsUtils.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/SensorThingsUtils.java @@ -16,16 +16,20 @@ */ package de.fraunhofer.iosb.ilt.sensorthingsmanager.aggregation; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.Utils; -import de.fraunhofer.iosb.ilt.sta.model.MultiDatastream; -import de.fraunhofer.iosb.ilt.sta.model.ObservedProperty; -import de.fraunhofer.iosb.ilt.sta.model.Sensor; -import de.fraunhofer.iosb.ilt.sta.model.Thing; -import de.fraunhofer.iosb.ilt.sta.model.ext.EntityList; -import de.fraunhofer.iosb.ilt.sta.model.ext.UnitOfMeasurement; -import de.fraunhofer.iosb.ilt.sta.query.Query; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.exception.ServiceFailureException; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.EntitySet; +import de.fraunhofer.iosb.ilt.frostclient.model.ext.UnitOfMeasurement; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsMultiDatastreamV11; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_DEFINITION; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_DESCRIPTION; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_NAME; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_PROPERTIES; +import de.fraunhofer.iosb.ilt.frostclient.models.ext.MapValue; +import de.fraunhofer.iosb.ilt.frostclient.query.Query; +import de.fraunhofer.iosb.ilt.frostclient.utils.StringHelper; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -44,32 +48,31 @@ public class SensorThingsUtils { */ private static final Logger LOGGER = LoggerFactory.getLogger(SensorThingsUtils.class); - public final Map> aggregateProperties = new HashMap<>(); + public final Map> aggregateProperties = new HashMap<>(); public SensorThingsUtils() { } - public ObservedProperty findOrCreateOp(SensorThingsService service, String name, String def, String description, Map properties, String filter, boolean aggregates) throws ServiceFailureException { - Query query = service.observedProperties().query(); - if (Utils.isNullOrEmpty(filter)) { - query.filter("name eq '" + Utils.escapeForStringConstant(name) + "'"); + public Entity findOrCreateOp(SensorThingsService service, String name, String def, String description, MapValue properties, String filter, boolean aggregates) throws ServiceFailureException { + SensorThingsSensingV11 sMdl = service.getModel(SensorThingsSensingV11.class); + SensorThingsMultiDatastreamV11 mMdl = service.getModel(SensorThingsMultiDatastreamV11.class); + Query query = service.query(sMdl.etObservedProperty); + if (StringHelper.isNullOrEmpty(filter)) { + query.filter("name eq " + StringHelper.quoteForUrl(name) + ""); } else { query.filter(filter); } - EntityList opList = query.list(); + EntitySet opList = query.list(); if (opList.size() > 1) { throw new IllegalStateException("More than one observedProperty with name " + name); } - ObservedProperty op; + Entity op; if (opList.size() == 1) { op = opList.iterator().next(); } else { LOGGER.info("Creating ObservedProperty {}.", name); - op = new ObservedProperty(); - op.setName(name); - op.setDefinition(def); - op.setDescription(description); - op.setProperties(properties); + op = sMdl.newObservedProperty(name, def, description) + .setProperty(EP_PROPERTIES, properties); service.create(op); } if (aggregates) { @@ -78,61 +81,57 @@ public ObservedProperty findOrCreateOp(SensorThingsService service, String name, return op; } - public void findOrCreateAggregateOps(SensorThingsService service, ObservedProperty op) throws ServiceFailureException { - List agList = aggregateProperties.get(op); + public void findOrCreateAggregateOps(SensorThingsService service, Entity op) throws ServiceFailureException { + List agList = aggregateProperties.get(op); if (agList != null && agList.size() == 3) { return; } agList = new ArrayList<>(); aggregateProperties.put(op, agList); - String opName = op.getName(); - String opDef = op.getDefinition(); - String opDesc = op.getDescription(); - String def = op.getDefinition(); + String opName = op.getProperty(EP_NAME); + String opDef = op.getProperty(EP_DEFINITION); + String opDesc = op.getProperty(EP_DESCRIPTION); + String def = op.getProperty(EP_DEFINITION); { String agOpName = opName + " Min"; String agOpDesc = opDesc + " Minimum"; - ObservedProperty agOp = findOrCreateOp(service, agOpName, def, agOpDesc, null, "", false); + Entity agOp = findOrCreateOp(service, agOpName, def, agOpDesc, null, "", false); agList.add(agOp); } { String agOpName = opName + " Max"; String agOpDesc = opDesc + " Maximum"; - ObservedProperty agOp = findOrCreateOp(service, agOpName, def, agOpDesc, null, "", false); + Entity agOp = findOrCreateOp(service, agOpName, def, agOpDesc, null, "", false); agList.add(agOp); } { String agOpName = opName + " Dev"; String agOpDesc = opDesc + " Standard deviation"; - ObservedProperty agOp = findOrCreateOp(service, agOpName, def, agOpDesc, null, "", false); + Entity agOp = findOrCreateOp(service, agOpName, def, agOpDesc, null, "", false); agList.add(agOp); } } - public MultiDatastream findOrCreateMultiDatastream(SensorThingsService service, String name, String desc, List uoms, Thing t, List ops, Sensor s, Map props) throws ServiceFailureException { - EntityList mdsList = service.multiDatastreams().query().filter("name eq '" + Utils.escapeForStringConstant(name) + "'").list(); + public Entity findOrCreateMultiDatastream(SensorThingsService service, String name, String desc, List uoms, Entity thing, List ops, Entity sensor, MapValue props) throws ServiceFailureException { + SensorThingsMultiDatastreamV11 mMdl = service.getModel(SensorThingsMultiDatastreamV11.class); + + EntitySet mdsList = service.query(mMdl.etMultiDatastream) + .filter("name eq " + StringHelper.quoteForUrl(name) + "") + .list(); if (mdsList.size() > 1) { throw new IllegalStateException("More than one multidatastream with name " + name); } - MultiDatastream mds; + Entity mds; if (mdsList.size() == 1) { mds = mdsList.iterator().next(); } else { LOGGER.info("Creating multiDatastream {}.", name); - List dataTypes = new ArrayList<>(); - for (ObservedProperty op : ops) { - dataTypes.add("http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement"); - } - mds = new MultiDatastream( - name, - desc, - dataTypes, - uoms); - mds.setProperties(props); - mds.setThing(t); - mds.setSensor(s); - mds.getObservedProperties().addAll(ops); + mds = mMdl.newMultiDatastream(name, desc, uoms) + .setProperty(EP_PROPERTIES, props) + .setProperty(mMdl.npMultidatastreamThing, thing) + .setProperty(mMdl.npMultidatastreamSensor, sensor) + .addNavigationEntity(mMdl.npMultidatastreamObservedproperties, ops); service.create(mds); } return mds; diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/Utils.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/Utils.java index 7fa0573..a427bdd 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/Utils.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/aggregation/Utils.java @@ -16,12 +16,13 @@ */ package de.fraunhofer.iosb.ilt.sensorthingsmanager.aggregation; -import de.fraunhofer.iosb.ilt.sta.model.Observation; -import de.fraunhofer.iosb.ilt.sta.model.TimeObject; -import de.fraunhofer.iosb.ilt.sta.model.ext.UnitOfMeasurement; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.ext.TimeValue; +import de.fraunhofer.iosb.ilt.frostclient.model.ext.UnitOfMeasurement; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11; import java.nio.charset.Charset; -import java.time.Instant; import java.util.regex.Pattern; +import net.time4j.Moment; /** * @@ -59,27 +60,27 @@ private Utils() { // Not to be instantiated. } - public static Instant getPhenTimeStart(Observation obs) { - TimeObject phenTime = obs.getPhenomenonTime(); + public static Moment getPhenTimeStart(Entity obs) { + TimeValue phenTime = obs.getProperty(SensorThingsSensingV11.EP_PHENOMENONTIME); return getPhenTimeStart(phenTime); } - public static Instant getPhenTimeStart(TimeObject phenTime) { + public static Moment getPhenTimeStart(TimeValue phenTime) { if (phenTime.isInterval()) { - return phenTime.getAsInterval().getStart(); + return phenTime.getInterval().getStart(); } - return phenTime.getAsDateTime().toInstant(); + return phenTime.getInstant().getDateTime(); } - public static Instant getPhenTimeEnd(Observation obs) { - TimeObject phenTime = obs.getPhenomenonTime(); + public static Moment getPhenTimeEnd(Entity obs) { + TimeValue phenTime = obs.getProperty(SensorThingsSensingV11.EP_PHENOMENONTIME); return getPhenTimeEnd(phenTime); } - public static Instant getPhenTimeEnd(TimeObject phenTime) { + public static Moment getPhenTimeEnd(TimeValue phenTime) { if (phenTime.isInterval()) { - return phenTime.getAsInterval().getEnd(); + return phenTime.getInterval().getEnd(); } - return phenTime.getAsDateTime().toInstant(); + return phenTime.getInstant().getDateTime(); } } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthBasic.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthBasic.java index 1d3d917..3648e76 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthBasic.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthBasic.java @@ -21,7 +21,7 @@ import de.fraunhofer.iosb.ilt.configurable.editor.EditorBoolean; import de.fraunhofer.iosb.ilt.configurable.editor.EditorPassword; import de.fraunhofer.iosb.ilt.configurable.editor.EditorString; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; import java.net.URL; import java.security.KeyManagementException; import java.security.KeyStoreException; @@ -37,8 +37,7 @@ import org.slf4j.LoggerFactory; /** - * - * @author scf + * Authentication using HTTP Basic Auth. */ public class AuthBasic implements AnnotatedConfigurable, AuthMethod { diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthHeader.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthHeader.java index 1c29726..f9f8d37 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthHeader.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthHeader.java @@ -19,14 +19,13 @@ import de.fraunhofer.iosb.ilt.configurable.AnnotatedConfigurable; import de.fraunhofer.iosb.ilt.configurable.annotations.ConfigurableField; import de.fraunhofer.iosb.ilt.configurable.editor.EditorString; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; -import de.fraunhofer.iosb.ilt.sta.service.TokenManager; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.utils.TokenManager; import org.apache.http.HttpRequest; import org.apache.http.impl.client.CloseableHttpClient; /** - * - * @author scf + * Authentication using custom Headers added to each request. */ public class AuthHeader implements AnnotatedConfigurable, AuthMethod { diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthMethod.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthMethod.java index 3886dc7..8069bde 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthMethod.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthMethod.java @@ -17,11 +17,10 @@ package de.fraunhofer.iosb.ilt.sensorthingsmanager.auth; import de.fraunhofer.iosb.ilt.configurable.Configurable; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; /** - * - * @author scf + * A method for authenticating users to a service. */ public interface AuthMethod extends Configurable { diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthNone.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthNone.java index 2c8b3b3..41fed69 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthNone.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthNone.java @@ -22,7 +22,7 @@ import de.fraunhofer.iosb.ilt.configurable.annotations.ConfigurableField; import de.fraunhofer.iosb.ilt.configurable.editor.EditorBoolean; import de.fraunhofer.iosb.ilt.configurable.editor.EditorNull; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -39,8 +39,6 @@ * Authentication type for no authentication. Does add the option to ignore SSL * certificate errors, for when using self-signed certificates for testing * purposes. - * - * @author scf */ public class AuthNone implements AnnotatedConfigurable, AuthMethod { @@ -68,8 +66,7 @@ public ConfigEditor getConfigEditor(Void context, Void edtCtx) { @Override public void setAuth(SensorThingsService service) { try { - HttpClientBuilder clientBuilder = HttpClients.custom() - .useSystemProperties(); + HttpClientBuilder clientBuilder = service.getClientBuilder(); if (ignoreSslErrors) { SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( @@ -80,9 +77,7 @@ public void setAuth(SensorThingsService service) { clientBuilder.setSSLSocketFactory(sslsf); } - CloseableHttpClient httpclient = clientBuilder.build(); - - service.setHttpClient(httpclient); + service.rebuildHttpClient(); } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException ex) { LOGGER.error("Failed to initialise basic auth.", ex); } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthPostCookie.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthPostCookie.java index e3ec3b0..993c1e7 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthPostCookie.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/auth/AuthPostCookie.java @@ -18,18 +18,16 @@ import de.fraunhofer.iosb.ilt.configurable.AnnotatedConfigurable; import de.fraunhofer.iosb.ilt.configurable.annotations.ConfigurableField; -import de.fraunhofer.iosb.ilt.configurable.editor.EditorBoolean; import de.fraunhofer.iosb.ilt.configurable.editor.EditorPassword; import de.fraunhofer.iosb.ilt.configurable.editor.EditorString; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; import java.io.IOException; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.slf4j.LoggerFactory; /** - * - * @author scf + * Authentication using Cookies. */ public class AuthPostCookie implements AnnotatedConfigurable, AuthMethod { diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerCleaner.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerCleaner.java deleted file mode 100644 index 9e17ff5..0000000 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerCleaner.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (C) 2019 Fraunhofer IOSB - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package de.fraunhofer.iosb.ilt.sensorthingsmanager.controller; - -import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.ChangingStatusLogger; -import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.Utils; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.model.Datastream; -import de.fraunhofer.iosb.ilt.sta.model.FeatureOfInterest; -import de.fraunhofer.iosb.ilt.sta.model.Location; -import de.fraunhofer.iosb.ilt.sta.model.MultiDatastream; -import de.fraunhofer.iosb.ilt.sta.model.Observation; -import de.fraunhofer.iosb.ilt.sta.model.ObservedProperty; -import de.fraunhofer.iosb.ilt.sta.model.Sensor; -import de.fraunhofer.iosb.ilt.sta.model.Thing; -import de.fraunhofer.iosb.ilt.sta.model.TimeObject; -import de.fraunhofer.iosb.ilt.sta.model.ext.EntityList; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; -import java.net.URL; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.ResourceBundle; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.fxml.Initializable; -import javafx.scene.control.CheckBox; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author scf - */ -public class ControllerCleaner implements Initializable { - - /** - * The logger for this class. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(ControllerCleaner.class); - - private static class LogStatusCleaner extends ChangingStatusLogger.ChangingStatusDefault { - - public LogStatusCleaner() { - super("Cleaning... {} T, {} L, {} S, {} Op, {} Ds, {} MDs, {} F, {} O. To Delete: {} ", 9); - setAllTo(Long.valueOf(0)); - } - - public void setThings(Long value) { - setObjectAt(0, value); - } - - public void setLocations(Long value) { - setObjectAt(1, value); - } - - public void setSensors(Long value) { - setObjectAt(2, value); - } - - public void setObsProps(Long value) { - setObjectAt(3, value); - } - - public void setDatastreams(Long value) { - setObjectAt(4, value); - } - - public void setMultiDatastreams(Long value) { - setObjectAt(5, value); - } - - public void setFeatures(Long value) { - setObjectAt(6, value); - } - - public void setObservations(Long value) { - setObjectAt(7, value); - } - - public void setToDelete(Long value) { - setObjectAt(8, value); - } - } - - @FXML - private CheckBox cleanThings; - @FXML - private CheckBox cleanDatastreams; - @FXML - private CheckBox cleanMultiDatastreams; - @FXML - private CheckBox cleanSensors; - @FXML - private CheckBox cleanObservedProperties; - @FXML - private CheckBox cleanFeatures; - @FXML - private CheckBox cleanLocations; - @FXML - private CheckBox cleanDuplicateObsPhentime; - @FXML - private CheckBox deleteThings; - @FXML - private CheckBox deleteSensors; - @FXML - private CheckBox deleteObservedProperties; - @FXML - private CheckBox deleteFeatures; - @FXML - private CheckBox deleteLocations; - @FXML - private CheckBox deleteDatastreams; - @FXML - private CheckBox deleteMultiDatastreams; - @FXML - private CheckBox deleteObservations; - - private SensorThingsService service; - private final LogStatusCleaner logStatusCleaner = new LogStatusCleaner(); - private final ChangingStatusLogger statusLogger = new ChangingStatusLogger(LOGGER) - .addLogStatus(logStatusCleaner) - .setLogIntervalMs(2000); - - @FXML - private void actionClean(ActionEvent event) { - statusLogger.start(); - try { - if (cleanThings.isSelected()) { - cleanThings(); - } - if (cleanSensors.isSelected()) { - cleanSensors(); - } - if (cleanObservedProperties.isSelected()) { - cleanObservedProperties(); - } - if (cleanFeatures.isSelected()) { - cleanFeatures(); - } - if (cleanDatastreams.isSelected()) { - cleanDatastreams(); - } - if (cleanMultiDatastreams.isSelected()) { - cleanMultiDatastreams(); - } - if (cleanLocations.isSelected()) { - cleanLocations(); - } - if (cleanDuplicateObsPhentime.isSelected()) { - cleanObservationsDuplicatePhentime(); - } - } catch (ServiceFailureException ex) { - LOGGER.error("Failed to clean.", ex); - } - statusLogger.stop(); - } - - private void cleanThings() throws ServiceFailureException { - EntityList list = service.things() - .query() - .select("name", "id") - .expand("Datastreams($select=id;$top=1),MultiDatastreams($select=id;$top=1)") - .orderBy("id asc") - .list(); - List toDelete = new ArrayList<>(); - Iterator it; - long count = 0; - long toDel = 0; - for (it = list.fullIterator(); it.hasNext();) { - Thing next = it.next(); - logStatusCleaner.setThings(++count); - if (next.getDatastreams().isEmpty() && next.getMultiDatastreams().isEmpty()) { - toDelete.add(next); - logStatusCleaner.setToDelete(++toDel); - } - } - LOGGER.info("Deleting {} Things", toDelete.size()); - for (Thing item : toDelete) { - logStatusCleaner.setToDelete(--toDel); - service.delete(item.withOnlyId()); - } - } - - private void cleanSensors() throws ServiceFailureException { - EntityList list = service.sensors() - .query() - .select("name", "id") - .expand("Datastreams($select=id;$top=1),MultiDatastreams($select=id;$top=1)") - .orderBy("id asc") - .list(); - List toDelete = new ArrayList<>(); - Iterator it; - long count = 0; - long toDel = 0; - for (it = list.fullIterator(); it.hasNext();) { - Sensor next = it.next(); - count++; - logStatusCleaner.setSensors(count); - if (next.getDatastreams().isEmpty() && next.getMultiDatastreams().isEmpty()) { - toDelete.add(next); - logStatusCleaner.setToDelete(++toDel); - } - } - LOGGER.info("Deleting {} Sensors", toDelete.size()); - for (Sensor item : toDelete) { - logStatusCleaner.setToDelete(--toDel); - service.delete(item.withOnlyId()); - } - } - - private void cleanObservedProperties() throws ServiceFailureException { - EntityList list = service.observedProperties() - .query() - .select("name", "id") - .expand("Datastreams($select=id;$top=1),MultiDatastreams($select=id;$top=1)") - .orderBy("id asc") - .list(); - List toDelete = new ArrayList<>(); - Iterator it; - long count = 0; - long toDel = 0; - for (it = list.fullIterator(); it.hasNext();) { - ObservedProperty next = it.next(); - count++; - logStatusCleaner.setObsProps(count); - if (next.getDatastreams().isEmpty() && next.getMultiDatastreams().isEmpty()) { - toDelete.add(next); - logStatusCleaner.setToDelete(++toDel); - } - } - LOGGER.info("Deleting {} ObservedProperties", toDelete.size()); - for (ObservedProperty item : toDelete) { - logStatusCleaner.setToDelete(--toDel); - service.delete(item.withOnlyId()); - } - } - - private void cleanDatastreams() throws ServiceFailureException { - LOGGER.info("Cleaning Datastreams"); - EntityList list = service.datastreams() - .query() - .select("name", "id") - .expand("Observations($select=id;$top=1)") - .orderBy("id asc") - .list(); - List toDelete = new ArrayList<>(); - Iterator it; - long count = 0; - long toDel = 0; - for (it = list.fullIterator(); it.hasNext();) { - Datastream next = it.next(); - count++; - logStatusCleaner.setDatastreams(count); - if (next.getObservations().isEmpty()) { - toDelete.add(next); - logStatusCleaner.setToDelete(++toDel); - } - } - LOGGER.info("Deleting {} Datastreams", toDelete.size()); - for (Datastream item : toDelete) { - logStatusCleaner.setToDelete(--toDel); - service.delete(item.withOnlyId()); - } - } - - private void cleanMultiDatastreams() throws ServiceFailureException { - LOGGER.info("Cleaning MultiDatastreams"); - EntityList list = service.multiDatastreams() - .query() - .select("name", "id") - .expand("Observations($select=id;$top=1)") - .orderBy("id asc") - .list(); - List toDelete = new ArrayList<>(); - Iterator it; - long count = 0; - long toDel = 0; - for (it = list.fullIterator(); it.hasNext();) { - MultiDatastream next = it.next(); - count++; - logStatusCleaner.setMultiDatastreams(count); - if (next.getObservations().isEmpty()) { - toDelete.add(next); - logStatusCleaner.setToDelete(++toDel); - } - } - LOGGER.info("Deleting {} MultiDatastream", toDelete.size()); - for (MultiDatastream item : toDelete) { - logStatusCleaner.setToDelete(--toDel); - service.delete(item.withOnlyId()); - } - } - - private void cleanFeatures() throws ServiceFailureException { - LOGGER.info("Cleaning Features"); - EntityList list = service.featuresOfInterest() - .query() - .select("name", "id") - .expand("Observations($select=id;$top=1)") - .orderBy("id asc") - .list(); - long count = 0; - long toDel = 0; - List toDelete = new ArrayList<>(); - Iterator it; - for (it = list.fullIterator(); it.hasNext();) { - FeatureOfInterest next = it.next(); - count++; - logStatusCleaner.setFeatures(count); - if (next.getObservations().isEmpty()) { - toDelete.add(next); - logStatusCleaner.setToDelete(++toDel); - } - } - LOGGER.info("Deleting {} FeaturesOfInterest", toDelete.size()); - for (FeatureOfInterest item : toDelete) { - logStatusCleaner.setToDelete(--toDel); - service.delete(item.withOnlyId()); - } - } - - private void cleanLocations() throws ServiceFailureException { - EntityList list = service.locations() - .query() - .select("name", "id") - .expand("Things($select=id;$top=1),HistoricalLocations($select=id;$top=1)") - .orderBy("id asc") - .list(); - List toDelete = new ArrayList<>(); - Iterator it; - long count = 0; - long toDel = 0; - for (it = list.fullIterator(); it.hasNext();) { - Location next = it.next(); - count++; - logStatusCleaner.setLocations(count); - if (next.getThings().isEmpty() && next.getHistoricalLocations().isEmpty()) { - toDelete.add(next); - logStatusCleaner.setToDelete(++toDel); - } - } - LOGGER.info("Deleting {} Locations", toDelete.size()); - for (Location item : toDelete) { - logStatusCleaner.setToDelete(--toDel); - service.delete(item.withOnlyId()); - } - } - - private void cleanObservationsDuplicatePhentime() throws ServiceFailureException { - EntityList list = service.datastreams() - .query() - .select("name", "id") - .orderBy("id asc") - .expand("Observations($select=id;$top=1)") - .filter("id ge 3699") - .list(); - Iterator it; - long count = 0; - for (it = list.fullIterator(); it.hasNext();) { - Datastream next = it.next(); - count++; - logStatusCleaner.setDatastreams(count); - cleanObsForDatastream(next); - } - } - - private void cleanObsForDatastream(Datastream ds) throws ServiceFailureException { - List toDelete = new ArrayList<>(); - EntityList list = ds.observations().query() - .orderBy("phenomenonTime asc,id asc") - .select("id,phenomenonTime") - .top(100000) - .list(); - Iterator it = list.fullIterator(); - long count = 0; - long toDel = 0; - TimeObject last = null; - while (it.hasNext()) { - Observation next = it.next(); - count++; - logStatusCleaner.setObservations(count); - TimeObject cur = next.getPhenomenonTime(); - if (last == null) { - last = cur; - } else { - if (last.equals(cur)) { - toDelete.add(next); - logStatusCleaner.setToDelete(++toDel); - } - last = cur; - } - } - if (toDelete.isEmpty()) { - return; - } - LOGGER.info("Deleting {} obs for Datastream {}", toDelete.size(), ds); - for (Observation obs : toDelete) { - logStatusCleaner.setToDelete(--toDel); - service.delete(obs); - } - } - - @FXML - private void actionDelete(ActionEvent event) { - try { - if (deleteThings.isSelected()) { - Utils.deleteAll(service.things()); - } - if (deleteSensors.isSelected()) { - Utils.deleteAll(service.sensors()); - } - if (deleteObservedProperties.isSelected()) { - Utils.deleteAll(service.observedProperties()); - } - if (deleteFeatures.isSelected()) { - Utils.deleteAll(service.featuresOfInterest()); - } - if (deleteLocations.isSelected()) { - Utils.deleteAll(service.locations()); - } - if (deleteDatastreams.isSelected()) { - Utils.deleteAll(service.datastreams()); - } - if (deleteMultiDatastreams.isSelected()) { - Utils.deleteAll(service.multiDatastreams()); - } - if (deleteObservations.isSelected()) { - Utils.deleteAll(service.observations()); - } - - } catch (ServiceFailureException ex) { - LOGGER.error("Exception deleting.", ex); - } - } - - public void setService(SensorThingsService service) { - this.service = service; - } - - @Override - public void initialize(URL url, ResourceBundle rb) { - - } - -} diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerCollection.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerCollection.java index c1dd653..dbd5974 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerCollection.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerCollection.java @@ -1,17 +1,24 @@ package de.fraunhofer.iosb.ilt.sensorthingsmanager.controller; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.exception.ServiceFailureException; +import de.fraunhofer.iosb.ilt.frostclient.exception.StatusCodeException; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.EntitySet; +import de.fraunhofer.iosb.ilt.frostclient.model.EntityType; +import de.fraunhofer.iosb.ilt.frostclient.model.PrimaryKey; +import de.fraunhofer.iosb.ilt.frostclient.model.property.EntityPropertyMain; +import de.fraunhofer.iosb.ilt.frostclient.model.property.type.TypePrimitive; +import static de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11.EP_NAME; +import de.fraunhofer.iosb.ilt.frostclient.query.Query; +import de.fraunhofer.iosb.ilt.frostclient.utils.ParserUtils; +import de.fraunhofer.iosb.ilt.frostclient.utils.StringHelper; import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.Utils; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.StatusCodeException; -import de.fraunhofer.iosb.ilt.sta.model.Entity; -import de.fraunhofer.iosb.ilt.sta.model.Id; -import de.fraunhofer.iosb.ilt.sta.model.ext.EntityList; -import de.fraunhofer.iosb.ilt.sta.query.Query; import java.io.IOException; import java.net.URL; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.ResourceBundle; import javafx.beans.property.ReadOnlyObjectWrapper; @@ -37,14 +44,9 @@ /** * * @author scf - * @param The entity type of the collection. */ -public class ControllerCollection> implements Initializable { +public class ControllerCollection implements Initializable { - public static interface EntityFactory> { - - public T createEntity(); - } /** * The logger for this class. */ @@ -78,16 +80,19 @@ public static interface EntityFactory> { private BorderPane paneSelected; @FXML - private TableView> entityTable; + private TableView entityTable; @FXML - private TableColumn, String> columnName; - private TableColumn, ?> columnId; + private TableColumn columnName; + private TableColumn columnId; - private final ObservableList> entities = FXCollections.observableArrayList(); - private EntityList currentQueryList; + private final ObservableList entities = FXCollections.observableArrayList(); + private EntitySet currentQueryList; + + private SensorThingsService service; + private Query query; + private EntityType entityType; - private Query query; /** * Can new entities be created. */ @@ -105,9 +110,9 @@ public static interface EntityFactory> { * The setter used to link newly selected items to the owner of the * collection. */ - private EntityGuiController.ChildSetter childSetter; + private EntityGuiController.ChildSetter childSetter; private boolean canMultiSelect = false; - private EntityFactory entityFactory; + /** * Should navigation properties of the selected Entity be shown, or just * entityProperties. @@ -147,6 +152,13 @@ private void actionButtonNext(ActionEvent event) { "Failed to fetch", "Fetching the next set of entities failed for url: " + ex.getUrl(), ex); + } catch (ServiceFailureException ex) { + LOGGER.error("Failed to fetch entity list.", ex); + Utils.showAlert( + Alert.AlertType.ERROR, + "Failed to fetch", + "Fetching the set of all entities failed.", + ex); } loadEntities(); } @@ -227,27 +239,27 @@ private void actionDelete(ActionEvent event) { if (!canDelete) { return; } - ObservableList> selectedItems = entityTable.getSelectionModel().getSelectedItems(); - List> toDelete = new ArrayList<>(); - for (EntityListEntry selectedItem : selectedItems) { + ObservableList selectedItems = entityTable.getSelectionModel().getSelectedItems(); + List toDelete = new ArrayList<>(); + for (EntityListEntry selectedItem : selectedItems) { toDelete.add(selectedItem); } - String what = selectedItems.size() == 1 ? "Item " + selectedItems.get(0).getEntity().getId().toString() : "all " + selectedItems.size() + " items"; + String what = selectedItems.size() == 1 ? "Item " + ParserUtils.formatKeyValuesForUrl(selectedItems.get(0).getEntity()) : "all " + selectedItems.size() + " items"; Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "Delete " + what + " ?", ButtonType.YES, ButtonType.NO); alert.showAndWait(); if (alert.getResult() == ButtonType.YES) { try { // ToDo: Add progress dialog. - for (EntityListEntry selectedItem : toDelete) { + for (EntityListEntry selectedItem : toDelete) { Entity entity = selectedItem.getEntity(); - if (entity.getId() == null) { - // entity doesn't exist yet. - entities.remove(selectedItem); - } else { + if (entity.primaryKeyFullySet()) { LOGGER.info("Deleting " + entity); entity.getService().delete(entity); entities.remove(selectedItem); + } else { + // entity doesn't exist yet. + entities.remove(selectedItem); } } } catch (ServiceFailureException ex) { @@ -266,7 +278,7 @@ private void actionNew(ActionEvent event) { if (!canCreate) { return; } - EntityListEntry newItem = new EntityListEntry().setEntity(entityFactory.createEntity()); + EntityListEntry newItem = new EntityListEntry().setEntity(new Entity(entityType)); entities.add(newItem); entityTable.getSelectionModel().select(newItem); } @@ -277,11 +289,10 @@ private void actionAdd(ActionEvent event) { new Alert(Alert.AlertType.ERROR, "No childSetter defined.", ButtonType.CLOSE).showAndWait(); return; } - Class entityClass = query.getEntityClass(); - Query allQuery = new Query<>(query.getService(), entityClass); - Optional> result = EntityGuiController.entitySearchDialog(allQuery, true, orderby); + Query allQuery = service.query(entityType); + Optional> result = EntityGuiController.entitySearchDialog(allQuery, true, orderby); if (result.isPresent() && !result.get().isEmpty()) { - List newChildren = result.get(); + List newChildren = result.get(); childSetter.setChildren(newChildren); } } @@ -308,8 +319,8 @@ public void setOrderby(String orderby) { private void loadEntities() { entities.clear(); - for (T entity : currentQueryList) { - entities.add(new EntityListEntry().setEntity(entity)); + for (Entity entity : currentQueryList.toList()) { + entities.add(new EntityListEntry().setEntity(entity)); } createIdColumn(); buttonNext.setDisable(!currentQueryList.hasNextLink()); @@ -320,9 +331,8 @@ private void loadEntities() { private void loadAllEntities() { int i = 0; entities.clear(); - for (Iterator it = currentQueryList.fullIterator(); it.hasNext();) { - T entity = it.next(); - entities.add(new EntityListEntry().setEntity(entity)); + for (Entity entity : currentQueryList) { + entities.add(new EntityListEntry().setEntity(entity)); i++; if (i >= 500) { LOGGER.warn("Warning after {}. Total: {}.", i, entities.size()); @@ -339,14 +349,14 @@ private void loadAllEntities() { entityTable.sort(); } - private void entitySelected(EntityListEntry newValue) { + private void entitySelected(EntityListEntry newValue) { if (newValue == null) { buttonDelete.setDisable(true); return; } try { - T entity = newValue.getEntity(); - Node pane = FactoryEntityPanel.getPane(query.getService(), entity.getType(), entity, showNavigationProperties); + Entity entity = newValue.getEntity(); + Node pane = FactoryEntityPanel.getPane(service, entityType, entity, showNavigationProperties); paneSelected.setCenter(pane); buttonDelete.setDisable(false); } catch (IOException ex) { @@ -356,20 +366,26 @@ private void entitySelected(EntityListEntry newValue) { @Override public void initialize(URL location, ResourceBundle resources) { - columnName.setCellValueFactory( - (TableColumn.CellDataFeatures, String> param) -> { - T entity = param.getValue().getEntity(); - Id id = entity.getId(); - String entityString = entity.toString(); - if (id != null && entityString.startsWith(id.toString())) { - entityString = entityString.substring(id.toString().length()).trim(); - } - return new ReadOnlyObjectWrapper<>(entityString); - }); + columnName.setCellValueFactory((TableColumn.CellDataFeatures param) -> { + Entity entity = param.getValue().getEntity(); + if (entityType.hasProperty(EP_NAME)) { + String name = entity.getProperty(EP_NAME); + if (!StringHelper.isNullOrEmpty(name)) { + return new ReadOnlyObjectWrapper<>(name); + } + } + for (EntityPropertyMain prop : entity.getEntityType().getEntityProperties()) { + if (prop.getType() == TypePrimitive.EDM_STRING) { + Object propValue = entity.getProperty(prop); + return new ReadOnlyObjectWrapper<>(Objects.toString(propValue)); + } + } + return new ReadOnlyObjectWrapper<>(entity.getEntityType().entityName); + }); entityTable.setItems(entities); entityTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); entityTable.getSelectionModel().selectedItemProperty().addListener( - (ObservableValue> observable, EntityListEntry oldValue, EntityListEntry newValue) -> { + (ObservableValue observable, EntityListEntry oldValue, EntityListEntry newValue) -> { entitySelected(newValue); }); } @@ -378,28 +394,45 @@ private void createIdColumn() { if (entities.isEmpty() || columnId != null) { return; } - Id id = entities.get(0).getEntity().getId(); - if (id == null) { + final Entity entity = entities.get(0).getEntity(); + if (!entity.primaryKeyFullySet()) { return; } - if (id.getValue() instanceof Number) { - TableColumn, Number> column = new TableColumn<>("ID"); - column.setCellValueFactory((TableColumn.CellDataFeatures, Number> param) -> { - if (param.getValue().getEntity().getId() == null) { + final PrimaryKey pk = entity.getPrimaryKey(); + final List keyProps = pk.getKeyProperties(); + final EntityPropertyMain keyProp0 = keyProps.get(0); + boolean pkIsNumeric = false; + + if (keyProps.size() == 1 && keyProp0.getType().getName().equals(TypePrimitive.EDM_UNTYPED_NAME)) { + final Object pkVal = entity.getPrimaryKeyValues()[0]; + if (pkVal instanceof Number n) { + pkIsNumeric = true; + } + } else if (keyProps.size() == 1 && keyProp0.getType().getName().startsWith("EDM.Int")) { + pkIsNumeric = true; + } + if (pkIsNumeric) { + TableColumn column = new TableColumn<>("ID"); + columnId = column; + column.setCellValueFactory((TableColumn.CellDataFeatures param) -> { + final Object pkValue = param.getValue().getEntity().getPrimaryKeyValues()[0]; + if (pkValue == null) { return new ReadOnlyObjectWrapper<>(-1); } - return new ReadOnlyObjectWrapper<>((Number) param.getValue().getEntity().getId().getValue()); + return new ReadOnlyObjectWrapper<>((Number) pkValue); }); - columnId = column; + } else { - TableColumn, String> column = new TableColumn<>("ID"); - column.setCellValueFactory((TableColumn.CellDataFeatures, String> param) -> { - if (param.getValue().getEntity().getId() == null) { + TableColumn column = new TableColumn<>("ID"); + column.setCellValueFactory((TableColumn.CellDataFeatures param) -> { + final Entity cellEntity = param.getValue().getEntity(); + if (!cellEntity.primaryKeyFullySet()) { return new ReadOnlyObjectWrapper<>(""); } - return new ReadOnlyObjectWrapper<>(param.getValue().getEntity().getId().toString()); + String keyValue = ParserUtils.formatKeyValuesForUrl(cellEntity); + return new ReadOnlyObjectWrapper<>(keyValue); }); - columnId = column; + } entityTable.getColumns().add(0, columnId); } @@ -412,17 +445,18 @@ public Query getQuery() { } /** - * @param query the query to set. - * @param entityFactory The factory to use to generate new entities. + * @param query the query to use to fetch entities. This includes the + * service and the EntityType. * @param orderBy The ordering to use. * @return this ControllerCollection. */ - public ControllerCollection setQuery(Query query, EntityFactory entityFactory, String orderBy) { + public ControllerCollection setQuery(Query query, String orderBy) { this.query = query; + this.service = query.getService(); + this.entityType = query.getEntityType(); this.canCreate = true; this.canDelete = true; this.orderby = orderBy; - this.entityFactory = entityFactory; buttonDelete.setVisible(canDelete); buttonNew.setVisible(canCreate); buttonAdd.setVisible(canLinkNew); @@ -441,6 +475,8 @@ public ControllerCollection setQuery(Query query, EntityFactory entityFactory */ public ControllerCollection setQuery(Query query, boolean showNavigationProperties, boolean canDelete, boolean canLinkNew, boolean multiSelect, String orderBy) { this.query = query; + this.service = query.getService(); + this.entityType = query.getEntityType(); this.canCreate = false; this.canLinkNew = canLinkNew; this.canDelete = canDelete; @@ -454,7 +490,7 @@ public ControllerCollection setQuery(Query query, boolean showNavigationProperti return this; } - public void setChildSetter(EntityGuiController.ChildSetter childSetter) { + public void setChildSetter(EntityGuiController.ChildSetter childSetter) { this.childSetter = childSetter; } @@ -462,8 +498,8 @@ public void setChildSetter(EntityGuiController.ChildSetter childSetter) { * @return the currently selected entity for single-select mode, or the last * selected entity for multi select mode. */ - public T getSelectedEntity() { - EntityListEntry item = entityTable.getSelectionModel().getSelectedItem(); + public Entity getSelectedEntity() { + EntityListEntry item = entityTable.getSelectionModel().getSelectedItem(); if (item == null) { return null; } @@ -474,15 +510,13 @@ public T getSelectedEntity() { * @return the currently selected entity for single-select mode, or the last * selected entity for multi select mode. */ - public List getSelectedEntities() { - ObservableList> items = entityTable.getSelectionModel().getSelectedItems(); + public List getSelectedEntities() { + ObservableList items = entityTable.getSelectionModel().getSelectedItems(); if (items == null) { return null; } - List values = new ArrayList<>(); - for (EntityListEntry item : items) { - values.add(item.getEntity()); - } + List values = new ArrayList<>(); + items.stream().forEach(i -> values.add(i.getEntity())); return values; } } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerEntity.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerEntity.java index 5df2ba1..b086d65 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerEntity.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerEntity.java @@ -1,9 +1,9 @@ package de.fraunhofer.iosb.ilt.sensorthingsmanager.controller; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.exception.ServiceFailureException; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.Utils; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.model.Entity; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; import java.net.URL; import java.util.ResourceBundle; import javafx.event.ActionEvent; @@ -19,11 +19,9 @@ import org.slf4j.LoggerFactory; /** - * - * @author scf - * @param The entity type this controller controls. + * Controller for showing one entity. */ -public class ControllerEntity> implements Initializable { +public class ControllerEntity implements Initializable { /** * The logger for this class. @@ -41,15 +39,15 @@ public class ControllerEntity> implements Initializable { private SplitPane splitPaneMain; @FXML private Button buttonSave; - private T entity; - private EntityGuiController controller; + private Entity entity; + private EntityGuiController controller; private SensorThingsService service; @FXML private void actionSave(ActionEvent event) { controller.saveFields(); try { - if (entity.getId() == null) { + if (!entity.primaryKeyFullySet()) { service.create(entity); controller.loadFields(); } else { @@ -73,7 +71,7 @@ public void initialize(URL location, ResourceBundle resources) { /** * @return the entity */ - public T getEntity() { + public Entity getEntity() { return entity; } @@ -85,11 +83,11 @@ public T getEntity() { * selected Entity be shown, or just entityProperties. * @return this Controller. */ - public ControllerEntity setEntity(SensorThingsService service, T entity, EntityGuiController controller, boolean showNavigationProperties) { + public ControllerEntity setEntity(SensorThingsService service, Entity entity, EntityGuiController controller, boolean showNavigationProperties) { this.service = service; this.entity = entity; this.controller = controller; - labelType.setText(controller.getType().getName()); + labelType.setText(entity.getEntityType().getEntityName()); if (entity != null && showNavigationProperties) { controller.init(service, entity, gridProperties, accordionLinks, labelId, true); } else { @@ -101,7 +99,7 @@ public ControllerEntity setEntity(SensorThingsService service, T entity, EntityG return this; } - public EntityGuiController getController() { + public EntityGuiController getController() { return controller; } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerServer.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerServer.java index 2fb358a..c26ee96 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerServer.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/ControllerServer.java @@ -16,20 +16,12 @@ */ package de.fraunhofer.iosb.ilt.sensorthingsmanager.controller; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.model.EntityType; +import de.fraunhofer.iosb.ilt.frostclient.models.SensorThingsSensingV11; +import de.fraunhofer.iosb.ilt.frostclient.query.Query; import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.Server; import de.fraunhofer.iosb.ilt.sensorthingsmanager.aggregation.ControllerAggManager; -import de.fraunhofer.iosb.ilt.sta.model.Datastream; -import de.fraunhofer.iosb.ilt.sta.model.Entity; -import de.fraunhofer.iosb.ilt.sta.model.FeatureOfInterest; -import de.fraunhofer.iosb.ilt.sta.model.HistoricalLocation; -import de.fraunhofer.iosb.ilt.sta.model.Location; -import de.fraunhofer.iosb.ilt.sta.model.MultiDatastream; -import de.fraunhofer.iosb.ilt.sta.model.Observation; -import de.fraunhofer.iosb.ilt.sta.model.ObservedProperty; -import de.fraunhofer.iosb.ilt.sta.model.Sensor; -import de.fraunhofer.iosb.ilt.sta.model.Thing; -import de.fraunhofer.iosb.ilt.sta.query.Query; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -70,68 +62,33 @@ public void initialize(URL location, ResourceBundle resources) { public void setServerEntry(Server entry) { this.entry = entry; serverTitle.setText(entry.getName() + " @ " + entry.getUrl()); + try { - service = new SensorThingsService(new URL(entry.getUrl())); + service = new SensorThingsService(new URL(entry.getUrl()), entry.getDataModels()); if (entry.getAuthMethod() != null) { entry.getAuthMethod().setAuth(service); } - addTabFor("Things", "name asc", service.things().query(), () -> { - Thing entity = new Thing(); - entity.setName("New Thing"); - return entity; - }); - addTabFor("Sensors", "name asc", service.sensors().query(), () -> { - Sensor entity = new Sensor(); - entity.setName("New Sensor"); - return entity; - }); - addTabFor("Datastreams", "name asc", service.datastreams().query(), () -> { - Datastream entity = new Datastream(); - entity.setName("New Datastream"); - return entity; - }); - addTabFor("MultiDtstrms", "name asc", service.multiDatastreams().query(), () -> { - MultiDatastream entity = new MultiDatastream(); - entity.setName("New MultiDatastream"); - return entity; - }); - addTabFor("ObsrvdProps", "name asc", service.observedProperties().query(), () -> { - ObservedProperty entity = new ObservedProperty(); - entity.setName("New ObservedProperty"); - return entity; - }); - addTabFor("Locations", "name asc", service.locations().query(), () -> { - Location entity = new Location(); - entity.setName("New Location"); - return entity; - }); - addTabFor("HistLctns", "time desc", service.historicalLocations().query(), () -> { - HistoricalLocation entity = new HistoricalLocation(); - return entity; - }); - addTabFor("Observations", "phenomenonTime asc", service.observations().query(), () -> { - Observation entity = new Observation(); - return entity; - }); - addTabFor("FoIs", "name asc", service.featuresOfInterest().query(), () -> { - FeatureOfInterest entity = new FeatureOfInterest(); - entity.setName("New FeatureOfInterest"); - return entity; - }); - addCleanerTab(); + for (EntityType et : service.getModelRegistry().getEntityTypes()) { + String orderBy = ""; + if (et.getProperty(SensorThingsSensingV11.NAME_NAME) != null) { + orderBy = "name asc"; + } + addTabFor(et.plural, orderBy, service.query(et)); + } + addAggregationTab(); } catch (MalformedURLException ex) { LOGGER.error("Failed to create service url.", ex); } } - private > void addTabFor(String title, String orderBy, Query query, ControllerCollection.EntityFactory factory) { + private void addTabFor(String title, String orderBy, Query query) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Collection.fxml")); AnchorPane content = (AnchorPane) loader.load(); ControllerCollection controller = loader.getController(); - controller.setQuery(query, factory, orderBy); + controller.setQuery(query, orderBy); Tab tab = new Tab(title); tab.setContent(content); @@ -141,21 +98,20 @@ private > void addTabFor(String title, String orderBy, Query } } - private void addCleanerTab() { - try { - FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Cleaner.fxml")); - BorderPane content = (BorderPane) loader.load(); - ControllerCleaner controller = loader.getController(); - controller.setService(service); - - Tab tab = new Tab("Cleaner"); - tab.setContent(content); - collectionTabs.getTabs().add(tab); - } catch (IOException ex) { - LOGGER.error("Failed to load Tab.", ex); - } - } - +// private void addCleanerTab() { +// try { +// FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Cleaner.fxml")); +// BorderPane content = (BorderPane) loader.load(); +// ControllerCleaner controller = loader.getController(); +// controller.setService(service); +// +// Tab tab = new Tab("Cleaner"); +// tab.setContent(content); +// collectionTabs.getTabs().add(tab); +// } catch (IOException ex) { +// LOGGER.error("Failed to load Tab.", ex); +// } +// } private void addAggregationTab() { try { FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/AggregationManager.fxml")); diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/EntityGuiController.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/EntityGuiController.java index 461f01d..8dc1a4e 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/EntityGuiController.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/EntityGuiController.java @@ -1,35 +1,33 @@ package de.fraunhofer.iosb.ilt.sensorthingsmanager.controller; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.EntityType; +import de.fraunhofer.iosb.ilt.frostclient.model.PropertyType; +import de.fraunhofer.iosb.ilt.frostclient.model.property.EntityPropertyMain; +import de.fraunhofer.iosb.ilt.frostclient.model.property.NavigationProperty; +import de.fraunhofer.iosb.ilt.frostclient.model.property.NavigationPropertyEntitySet; +import de.fraunhofer.iosb.ilt.frostclient.model.ComplexValue; +import de.fraunhofer.iosb.ilt.frostclient.model.property.EntityProperty; +import de.fraunhofer.iosb.ilt.frostclient.model.property.type.TypeComplex; +import de.fraunhofer.iosb.ilt.frostclient.model.property.type.TypePrimitive; +import static de.fraunhofer.iosb.ilt.frostclient.model.property.type.TypePrimitive.EDM_STRING_NAME; +import de.fraunhofer.iosb.ilt.frostclient.models.ext.MapValue; +import de.fraunhofer.iosb.ilt.frostclient.query.Query; +import static de.fraunhofer.iosb.ilt.frostclient.utils.ParserUtils.formatKeyValuesForUrl; import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.ObjectMapperFactory; import de.fraunhofer.iosb.ilt.sensorthingsmanager.utils.Utils; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.jackson.LocationDeserializer; -import de.fraunhofer.iosb.ilt.sta.model.Datastream; -import de.fraunhofer.iosb.ilt.sta.model.Entity; -import de.fraunhofer.iosb.ilt.sta.model.EntityType; -import de.fraunhofer.iosb.ilt.sta.model.FeatureOfInterest; -import de.fraunhofer.iosb.ilt.sta.model.HistoricalLocation; -import de.fraunhofer.iosb.ilt.sta.model.Location; -import de.fraunhofer.iosb.ilt.sta.model.MultiDatastream; -import de.fraunhofer.iosb.ilt.sta.model.Observation; -import de.fraunhofer.iosb.ilt.sta.model.ObservedProperty; -import de.fraunhofer.iosb.ilt.sta.model.Sensor; -import de.fraunhofer.iosb.ilt.sta.model.Thing; -import de.fraunhofer.iosb.ilt.sta.model.TimeObject; -import de.fraunhofer.iosb.ilt.sta.model.ext.EntityList; -import de.fraunhofer.iosb.ilt.sta.model.ext.UnitOfMeasurement; -import de.fraunhofer.iosb.ilt.sta.query.Query; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; import java.io.IOException; -import java.time.ZonedDateTime; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import javafx.event.ActionEvent; import javafx.fxml.FXMLLoader; import javafx.geometry.VPos; @@ -44,31 +42,19 @@ import javafx.scene.control.TextField; import javafx.scene.control.TextInputControl; import javafx.scene.control.TitledPane; -import javafx.scene.control.Alert; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.scene.layout.Priority; import javafx.scene.layout.Region; import javafx.scene.layout.RowConstraints; -import org.geojson.GeoJsonObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.threeten.extra.Interval; /** * - * @author scf - * @param The exact entity type this controller controls. */ -public interface EntityGuiController> { - - public static TypeReference> TYPE_MAP_STRING_OBJECT = new TypeReference>() { - // Empty on purpose. - }; - public static TypeReference> TYPE_LIST_UOM = new TypeReference>() { - // Empty on purpose. - }; +public interface EntityGuiController { /** * Load the fields from the entity into the gui. @@ -91,127 +77,70 @@ public interface EntityGuiController> { * @param labelId The label that shows the entity id. * @param editable is the entity editable. */ - public void init(SensorThingsService service, T entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable); + public void init(SensorThingsService service, Entity entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable); - public static class GuiControllerDatastream implements EntityGuiController { + public static class GuiControllerDefault implements EntityGuiController { /** * The logger for this class. */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); + private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerDefault.class); private Label labelId; - private Datastream entity; - private TextField textName; - private TextArea textDescription; - private TextField textObservationType; - private TextField textUomName; - private TextField textUomSymbol; - private TextField textUomDefinition; - private TextField textObservedArea; - private TextField textPhenomenonTime; - private TextField textResultTime; - private TextArea textProperties; + private final EntityType entityType; + private Entity entity; + private final List controls = new ArrayList<>(); + private final AtomicInteger itemCount = new AtomicInteger(); + + public GuiControllerDefault(EntityType entityType) { + this.entityType = entityType; + } @Override public void loadFields() { if (entity == null) { return; } - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - textName.setText(entity.getName()); - textDescription.setText(entity.getDescription()); - textObservationType.setText(entity.getObservationType()); - UnitOfMeasurement uom = entity.getUnitOfMeasurement(); - if (uom == null) { - uom = new UnitOfMeasurement(); - entity.setUnitOfMeasurement(uom); + if (entity.primaryKeyFullySet()) { + labelId.setText(formatKeyValuesForUrl(entity)); } - textUomName.setText(uom.getName()); - textUomSymbol.setText(uom.getSymbol()); - textUomDefinition.setText(uom.getDefinition()); - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - GeoJsonObject oa = entity.getObservedArea(); - textObservedArea.setText(mapper.writeValueAsString(oa)); - } catch (IOException ex) { - LOGGER.error("Failed to load fields.", ex); - } - if (entity.getPhenomenonTime() != null) { - textPhenomenonTime.setText(entity.getPhenomenonTime().toString()); - } - if (entity.getResultTime() != null) { - textResultTime.setText(entity.getResultTime().toString()); - } - try { - if (entity.getProperties() != null) { - String props = mapper.writeValueAsString(entity.getProperties()); - textProperties.setText(props); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); + for (PropertyGuiGlue control : controls) { + control.entityToGui(); } } @Override public void saveFields() { - if (!Utils.isNullOrEmpty(textName.getText())) { - entity.setName(textName.getText()); - } - if (!Utils.isNullOrEmpty(textDescription.getText())) { - entity.setDescription(textDescription.getText()); - } - if (!Utils.isNullOrEmpty(textObservationType.getText())) { - entity.setObservationType(textObservationType.getText()); - } - if (!Utils.isNullOrEmpty(textUomName.getText()) - || !Utils.isNullOrEmpty(textUomSymbol.getText()) - || !Utils.isNullOrEmpty(textUomDefinition.getText())) { - UnitOfMeasurement uom = entity.getUnitOfMeasurement(); - uom.setName(textUomName.getText()); - uom.setSymbol(textUomSymbol.getText()); - uom.setDefinition(textUomDefinition.getText()); - } - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - if (!Utils.isNullOrEmpty(textProperties.getText())) { - Map properties = mapper.readValue(textProperties.getText(), TYPE_MAP_STRING_OBJECT); - entity.setProperties(properties); - } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); + for (PropertyGuiGlue control : controls) { + control.guiToEntity(); } } @Override public EntityType getType() { - return EntityType.DATASTREAM; + return entity.getEntityType(); } @Override - public void init(SensorThingsService service, Datastream entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { + public void init(SensorThingsService service, Entity entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { this.labelId = labelId; this.entity = entity; - int i = 0; - textName = addFieldTo(gridProperties, i, "Name", new TextField(), false, editable); - textDescription = addFieldTo(gridProperties, ++i, "Description", new TextArea(), true, editable); - textObservationType = addFieldTo(gridProperties, ++i, "ObservationType", new TextField(), false, editable); - textUomName = addFieldTo(gridProperties, ++i, "UoM: Name", new TextField(), false, editable); - textUomSymbol = addFieldTo(gridProperties, ++i, "UoM: Symbol", new TextField(), false, editable); - textUomDefinition = addFieldTo(gridProperties, ++i, "UoM: Definition", new TextField(), false, editable); - textObservedArea = addFieldTo(gridProperties, ++i, "ObservedArea", new TextField(), false, false); - textPhenomenonTime = addFieldTo(gridProperties, ++i, "PhenomenonTime", new TextField(), false, false); - textResultTime = addFieldTo(gridProperties, ++i, "ResultTime", new TextField(), false, false); - textProperties = addFieldTo(gridProperties, ++i, "Properties", new TextArea(), true, editable); + EntityType entityType = entity.getEntityType(); + Set entityProperties = entityType.getEntityProperties(); + for (EntityPropertyMain ep : entityProperties) { + addGuiElement(ep.getJsonName(), ep, editable, gridProperties); + } if (accordionLinks != null) { try { - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getThing(), service.things().query(), "name asc", entity::setThing)); - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getSensor(), service.sensors().query(), "name asc", entity::setSensor)); - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getObservedProperty(), service.observedProperties().query(), "name asc", entity::setObservedProperty)); - accordionLinks.getPanes().add(new TitledPane("Observations", createCollectionPaneFor(entity.observations().query(), "phenomenonTime asc"))); - } catch (IOException | ServiceFailureException ex) { + for (NavigationProperty npe : entityType.getNavigationEntities()) { + TitledPane tp = createEditableEntityPane(entity, entity.getProperty(npe), service.query(npe.getEntityType()), "name asc", child -> entity.setProperty(npe, child)); + accordionLinks.getPanes().add(tp); + } + for (NavigationPropertyEntitySet nps : entityType.getNavigationSets()) { + Pane pane = createCollectionPaneFor(entity.query(nps), ""); + accordionLinks.getPanes().add(new TitledPane(nps.getName(), pane)); + } + } catch (IOException ex) { LOGGER.error("Failed to create panel.", ex); } catch (NullPointerException e) { // Happens when entity is new. @@ -219,852 +148,220 @@ public void init(SensorThingsService service, Datastream entity, GridPane gridPr } } } - } - public static class GuiControllerMultiDatastream implements EntityGuiController { - - /** - * The logger for this class. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); - private Label labelId; - private MultiDatastream entity; - private TextField textName; - private TextArea textDescription; - private TextField textObservationType; - private TextArea textUoms; - private TextField textObservedArea; - private TextField textPhenomenonTime; - private TextField textResultTime; - private TextArea textProperties; - - @Override - public void loadFields() { - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - textName.setText(entity.getName()); - textDescription.setText(entity.getDescription()); - textObservationType.setText(entity.getObservationType()); - - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - List uoms = entity.getUnitOfMeasurements(); - if (uoms != null && !uoms.isEmpty()) { - textUoms.setText(mapper.writeValueAsString(uoms)); - } - } catch (IOException ex) { - LOGGER.error("Failed to load fields.", ex); - } - try { - GeoJsonObject oa = entity.getObservedArea(); - if (oa != null) { - textObservedArea.setText(mapper.writeValueAsString(oa)); - } - } catch (IOException ex) { - LOGGER.error("Failed to load fields.", ex); - } - if (entity.getPhenomenonTime() != null) { - textPhenomenonTime.setText(entity.getPhenomenonTime().toString()); - } - if (entity.getResultTime() != null) { - textResultTime.setText(entity.getResultTime().toString()); - } - try { - if (entity.getProperties() != null) { - String props = mapper.writeValueAsString(entity.getProperties()); - textProperties.setText(props); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } - } - - @Override - public void saveFields() { - if (!Utils.isNullOrEmpty(textName.getText())) { - entity.setName(textName.getText()); - } - if (!Utils.isNullOrEmpty(textDescription.getText())) { - entity.setDescription(textDescription.getText()); - } - if (!Utils.isNullOrEmpty(textObservationType.getText())) { - entity.setObservationType(textObservationType.getText()); - } - - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - List properties = mapper.readValue(textUoms.getText(), TYPE_LIST_UOM); - entity.setUnitOfMeasurements(properties); - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); - } - try { - if (!Utils.isNullOrEmpty(textProperties.getText())) { - Map properties = mapper.readValue(textProperties.getText(), TYPE_MAP_STRING_OBJECT); - entity.setProperties(properties); - } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); - } - } - - @Override - public EntityType getType() { - return EntityType.MULTIDATASTREAM; - } - - @Override - public void init(SensorThingsService service, MultiDatastream entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { - this.labelId = labelId; - this.entity = entity; - int i = 0; - textName = addFieldTo(gridProperties, i, "Name", new TextField(), false, editable); - textDescription = addFieldTo(gridProperties, ++i, "Description", new TextArea(), true, editable); - textObservationType = addFieldTo(gridProperties, ++i, "ObservationType", new TextField(), false, editable); - textUoms = addFieldTo(gridProperties, ++i, "UoMs", new TextArea(), false, editable); - textObservedArea = addFieldTo(gridProperties, ++i, "ObservedArea", new TextField(), false, false); - textPhenomenonTime = addFieldTo(gridProperties, ++i, "PhenomenonTime", new TextField(), false, false); - textResultTime = addFieldTo(gridProperties, ++i, "ResultTime", new TextField(), false, false); - textProperties = addFieldTo(gridProperties, ++i, "Properties", new TextArea(), true, editable); - - if (accordionLinks != null) { - try { - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getThing(), service.things().query(), "name asc", entity::setThing)); - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getSensor(), service.sensors().query(), "name asc", entity::setSensor)); - - TitledPane tp = new TitledPane("ObservedProperties", createCollectionPaneFor(entity.observedProperties().query(), "name asc")); - accordionLinks.getPanes().add(tp); - tp = new TitledPane("Observations", createCollectionPaneFor(entity.observations().query(), "phenomenonTime asc")); - accordionLinks.getPanes().add(tp); - } catch (IOException | ServiceFailureException ex) { - LOGGER.error("Failed to create panel.", ex); - } catch (NullPointerException e) { - // Happens when entity is new. - } - } + private void addGuiElement(String name, EntityPropertyMain property, boolean editable, GridPane gridProperties) { + PropertyGuiGlue item = PropertyGuiGlue.createGuiElement(entity, property, editable, gridProperties, itemCount); + PropertyType pt = property.getType(); + controls.add(item); } } - public static class GuiControllerFeatureOfInterest implements EntityGuiController { + public static interface PropertyGuiGlue { /** - * The logger for this class. + * Read the value from the Entity and push it to the GUI element. */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); - private Label labelId; - private FeatureOfInterest entity; - private TextField textName; - private TextArea textDescription; - private TextField textEncodingType; - private TextArea textFeature; - private TextArea textProperties; + public void entityToGui(); - @Override - public void loadFields() { - if (entity == null) { - return; - } - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - textName.setText(entity.getName()); - textDescription.setText(entity.getDescription()); - textEncodingType.setText(entity.getEncodingType()); - final ObjectMapper mapper = ObjectMapperFactory.get(); - String json; - try { - json = mapper.writeValueAsString(entity.getFeature()); - textFeature.setText(json); - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } - try { - if (entity.getProperties() != null) { - String props = mapper.writeValueAsString(entity.getProperties()); - textProperties.setText(props); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } - } - - @Override - public void saveFields() { - if (!Utils.isNullOrEmpty(textName.getText())) { - entity.setName(textName.getText()); - } - if (!Utils.isNullOrEmpty(textDescription.getText())) { - entity.setDescription(textDescription.getText()); - } - if (!Utils.isNullOrEmpty(textEncodingType.getText())) { - entity.setEncodingType(textEncodingType.getText()); - } + /** + * Read the value from the Gui and push it to the Entity. + */ + public void guiToEntity(); - final ObjectMapper mapper = ObjectMapperFactory.get(); - if (!Utils.isNullOrEmpty(textFeature.getText())) { - try { - Object feature = LocationDeserializer.deserialize(textFeature.getText(), mapper); - entity.setFeature(feature); - } catch (IOException ex) { - LOGGER.error("Not valid geojson.", ex); + private static PropertyGuiGlue createGuiElement(ComplexValue entity, EntityProperty property, boolean editable, GridPane gridProperties, AtomicInteger itemCount) { + PropertyType pt = property.getType(); + if (pt instanceof TypeComplex ptc) { + if (ptc.isOpenType()) { + return new GuiGlueOpenType(entity, property) + .init(gridProperties, itemCount, editable); + } else { + return new GuiGlueComplex(entity, property) + .init(gridProperties, itemCount, editable); } - } - try { - if (!Utils.isNullOrEmpty(textProperties.getText())) { - Map properties = mapper.readValue(textProperties.getText(), TYPE_MAP_STRING_OBJECT); - entity.setProperties(properties); + } else if (pt instanceof TypePrimitive ptsp) { + switch (ptsp.getName()) { + case EDM_STRING_NAME: + default: + return new GuiGlueSimpleString(entity, property) + .init(gridProperties, itemCount, editable); } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); } + return new GuiGlueSimpleString(entity, property) + .init(gridProperties, itemCount, editable); } - @Override - public EntityType getType() { - return EntityType.FEATURE_OF_INTEREST; - } - - @Override - public void init(SensorThingsService service, FeatureOfInterest entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { - this.labelId = labelId; - this.entity = entity; - int i = 0; - textName = addFieldTo(gridProperties, i, "Name", new TextField(), false, editable); - textDescription = addFieldTo(gridProperties, ++i, "Description", new TextArea(), true, editable); - textEncodingType = addFieldTo(gridProperties, ++i, "EncodingType", new TextField(), false, editable); - textFeature = addFieldTo(gridProperties, ++i, "Feature", new TextArea(), false, editable); - textProperties = addFieldTo(gridProperties, ++i, "Properties", new TextArea(), true, editable); - - if (accordionLinks != null) { - try { - TitledPane tp = new TitledPane("Observations", createCollectionPaneFor(entity.observations().query(), "phenomenonTime asc")); - accordionLinks.getPanes().add(tp); - } catch (NullPointerException e) { - // Happens when entity is new. - } - } - } } - public static class GuiControllerHistoricalLocation implements EntityGuiController { - - /** - * The logger for this class. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); - private Label labelId; - private HistoricalLocation entity; - private TextField textTime; - - @Override - public void loadFields() { - if (entity == null) { - return; - } - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - textTime.setText(entity.getTime().toString()); - } - - @Override - public void saveFields() { - if (!Utils.isNullOrEmpty(textTime.getText())) { - entity.setTime(ZonedDateTime.parse(textTime.getText())); - } - } + public static class GuiGlueComplex implements PropertyGuiGlue { - @Override - public EntityType getType() { - return EntityType.HISTORICAL_LOCATION; - } + private final ComplexValue entity; + private final EntityProperty property; + private final Map subProperties = new HashMap<>(); + private ComplexValue value; - @Override - public void init(SensorThingsService service, HistoricalLocation entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { - this.labelId = labelId; + public GuiGlueComplex(ComplexValue entity, EntityProperty property) { this.entity = entity; - int i = 0; - textTime = addFieldTo(gridProperties, i, "Time", new TextField(), false, editable); - - if (accordionLinks != null) { - try { - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getThing(), service.things().query(), "name asc", entity::setThing)); - TitledPane tp = new TitledPane("Locations", createCollectionPaneFor(entity.locations().query(), "name asc")); - accordionLinks.getPanes().add(tp); - } catch (IOException | ServiceFailureException ex) { - LOGGER.error("Failed to create panel.", ex); - } catch (NullPointerException ex) { - // Happens when entity is new. - } - } + this.property = property; } - } - - public static class GuiControllerLocation implements EntityGuiController { - /** - * The logger for this class. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); - private Label labelId; - private Location entity; - private TextField textName; - private TextArea textDescription; - private TextField textEncodingType; - private TextArea textLocation; - private TextArea textProperties; - - @Override - public void loadFields() { - if (entity == null) { - return; - } - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - textName.setText(entity.getName()); - textDescription.setText(entity.getDescription()); - textEncodingType.setText(entity.getEncodingType()); - final ObjectMapper mapper = ObjectMapperFactory.get(); - String json; - try { - json = mapper.writeValueAsString(entity.getLocation()); - textLocation.setText(json); - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } - try { - if (entity.getProperties() != null) { - String props = mapper.writeValueAsString(entity.getProperties()); - textProperties.setText(props); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } + public GuiGlueComplex init(GridPane gridProperties, AtomicInteger itemCount, boolean editable) { + return init("", gridProperties, itemCount, editable); } - @Override - public void saveFields() { - if (!Utils.isNullOrEmpty(textName.getText())) { - entity.setName(textName.getText()); - } - if (!Utils.isNullOrEmpty(textDescription.getText())) { - entity.setDescription(textDescription.getText()); - } - if (!Utils.isNullOrEmpty(textEncodingType.getText())) { - entity.setEncodingType(textEncodingType.getText()); - } - - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - if (!Utils.isNullOrEmpty(textLocation.getText())) { - GeoJsonObject feature = mapper.readValue(textLocation.getText(), GeoJsonObject.class); - entity.setLocation(feature); + public GuiGlueComplex init(String namePrefix, GridPane gridProperties, AtomicInteger itemCount, boolean editable) { + PropertyType pt = property.getType(); + if (pt instanceof TypeComplex ptc) { + value = entity.getProperty(property); + if (value == null) { + // TODO: only instantiate when not empty... + value = ptc.instantiate(); + entity.setProperty(property, value); } - } catch (IOException ex) { - LOGGER.error("Not valid geojson.", ex); - } - try { - if (!Utils.isNullOrEmpty(textProperties.getText())) { - Map properties = mapper.readValue(textProperties.getText(), TYPE_MAP_STRING_OBJECT); - entity.setProperties(properties); + for (EntityProperty subProperty : ptc.getProperties()) { + PropertyGuiGlue subItem = PropertyGuiGlue.createGuiElement(value, subProperty, editable, gridProperties, itemCount); + subProperties.put(subProperty.getJsonName(), subItem); } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); } + return this; } @Override - public EntityType getType() { - return EntityType.LOCATION; + public void entityToGui() { + for (PropertyGuiGlue subProp : subProperties.values()) { + subProp.entityToGui(); + } } @Override - public void init(SensorThingsService service, Location entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { - this.labelId = labelId; - this.entity = entity; - int i = 0; - textName = addFieldTo(gridProperties, i, "Name", new TextField(), false, editable); - textDescription = addFieldTo(gridProperties, ++i, "Description", new TextArea(), true, editable); - textEncodingType = addFieldTo(gridProperties, ++i, "EncodingType", new TextField(), false, editable); - textLocation = addFieldTo(gridProperties, ++i, "Location", new TextArea(), false, editable); - textProperties = addFieldTo(gridProperties, ++i, "Properties", new TextArea(), true, editable); - - if (accordionLinks != null) { - try { - TitledPane tp = new TitledPane("Things", createCollectionPaneFor(entity.things().query(), "name asc")); - accordionLinks.getPanes().add(tp); - tp = new TitledPane("HistoricalLocations", createCollectionPaneFor(entity.historicalLocations().query(), "time desc")); - accordionLinks.getPanes().add(tp); - } catch (NullPointerException e) { - // Happens when entity is new. - } + public void guiToEntity() { + for (PropertyGuiGlue subProp : subProperties.values()) { + subProp.guiToEntity(); } } } - public static class GuiControllerObservation implements EntityGuiController { + public static class GuiGlueOpenType implements PropertyGuiGlue { - /** - * The logger for this class. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); - private Label labelId; - private Observation entity; - private TextField textPhenomenonTime; - private TextField textResultTime; - private TextArea textResult; - private TextField textResultQuality; - private TextField textValidTime; - private TextArea textParameters; + private static final Logger LOGGER = LoggerFactory.getLogger(GuiGlueOpenType.class); - @Override - public void loadFields() { - if (entity == null) { - return; - } - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - if (entity.getPhenomenonTime() != null) { - textPhenomenonTime.setText(entity.getPhenomenonTime().toString()); - } - if (entity.getResultTime() != null) { - textResultTime.setText(entity.getResultTime().toString()); - } - if (entity.getValidTime() != null) { - textValidTime.setText(entity.getValidTime().toString()); - } - final ObjectMapper mapper = ObjectMapperFactory.get(); - String json; - try { - if (entity.getResult() != null) { - json = mapper.writeValueAsString(entity.getResult()); - textResult.setText(json); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } - try { - if (entity.getResultQuality() != null) { - json = mapper.writeValueAsString(entity.getResultQuality()); - textResultQuality.setText(json); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } - try { - if (entity.getParameters() != null) { - json = mapper.writeValueAsString(entity.getParameters()); - textParameters.setText(json); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } + private final ComplexValue entity; + private final EntityProperty property; + private TextArea field; + public GuiGlueOpenType(ComplexValue entity, EntityProperty property) { + this.entity = entity; + this.property = property; } - @Override - public void saveFields() { - if (!textPhenomenonTime.getText().isEmpty()) { - entity.setPhenomenonTime(TimeObject.parse(textPhenomenonTime.getText())); - } - if (!textResultTime.getText().isEmpty()) { - entity.setResultTime(ZonedDateTime.parse(textResultTime.getText())); - } - if (!textValidTime.getText().isEmpty()) { - entity.setValidTime(Interval.parse(textValidTime.getText())); - } - - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - if (!Utils.isNullOrEmpty(textResult.getText())) { - JsonNode tree = mapper.readTree(textResult.getText()); - entity.setResult(tree); - } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); - } - try { - if (!Utils.isNullOrEmpty(textResultQuality.getText())) { - JsonNode tree = mapper.readTree(textResultQuality.getText()); - entity.setResultQuality(tree); - } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); - } - try { - if (!Utils.isNullOrEmpty(textParameters.getText())) { - Map map = mapper.readValue(textParameters.getText(), TYPE_MAP_STRING_OBJECT); - entity.setParameters(map); - } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); - } - } - - @Override - public EntityType getType() { - return EntityType.OBSERVATION; + public GuiGlueOpenType init(GridPane gridProperties, AtomicInteger itemCount, boolean editable) { + return init("", gridProperties, itemCount, editable); } - @Override - public void init(SensorThingsService service, Observation entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { - this.labelId = labelId; - this.entity = entity; - int i = 0; - textPhenomenonTime = addFieldTo(gridProperties, i, "PhenomenonTime", new TextField(), false, editable); - textResultTime = addFieldTo(gridProperties, ++i, "ResultTime", new TextField(), false, editable); - textResult = addFieldTo(gridProperties, ++i, "Result", new TextArea(), true, editable); - textResultQuality = addFieldTo(gridProperties, ++i, "ResultQuality", new TextField(), false, editable); - textValidTime = addFieldTo(gridProperties, ++i, "ValidTime", new TextField(), false, editable); - textParameters = addFieldTo(gridProperties, ++i, "Parameters", new TextArea(), true, editable); - - if (accordionLinks != null) { - try { - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getDatastream(), service.datastreams().query(), "name asc", entity::setDatastream)); - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getMultiDatastream(), service.multiDatastreams().query(), "name asc", entity::setMultiDatastream)); - accordionLinks.getPanes().add(createEditableEntityPane(entity, entity.getFeatureOfInterest(), service.featuresOfInterest().query(), "name asc", entity::setFeatureOfInterest)); - } catch (IOException | ServiceFailureException ex) { - LOGGER.error("Failed to create panel.", ex); - } - } + public GuiGlueOpenType init(String namePrefix, GridPane gridProperties, AtomicInteger itemCount, boolean editable) { + field = addFieldTo(gridProperties, itemCount.getAndIncrement(), namePrefix + property.getName(), new TextArea(), true, editable); + return this; } - } - - public static class GuiControllerObsProp implements EntityGuiController { - - /** - * The logger for this class. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); - private Label labelId; - private ObservedProperty entity; - - private TextField textName; - private TextField textDefinition; - private TextArea textDescription; - private TextArea textProperties; @Override - public void loadFields() { - if (entity == null) { - return; - } - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - textName.setText(entity.getName()); - textDefinition.setText(entity.getDefinition()); - textDescription.setText(entity.getDescription()); + public void entityToGui() { final ObjectMapper mapper = ObjectMapperFactory.get(); try { - if (entity.getProperties() != null) { - String props = mapper.writeValueAsString(entity.getProperties()); - textProperties.setText(props); + final MapValue value = entity.getProperty(property); + if (value != null) { + String textValue = mapper.writeValueAsString(value); + field.setText(textValue); } } catch (JsonProcessingException ex) { LOGGER.error("Properties can not be converted to JSON.", ex); } + } @Override - public void saveFields() { - if (!Utils.isNullOrEmpty(textName.getText())) { - entity.setName(textName.getText()); - } - if (!Utils.isNullOrEmpty(textDefinition.getText())) { - entity.setDefinition(textDefinition.getText()); - } - if (!Utils.isNullOrEmpty(textDescription.getText())) { - entity.setDescription(textDescription.getText()); - } + public void guiToEntity() { final ObjectMapper mapper = ObjectMapperFactory.get(); try { - if (!Utils.isNullOrEmpty(textProperties.getText())) { - Map properties = mapper.readValue(textProperties.getText(), TYPE_MAP_STRING_OBJECT); - entity.setProperties(properties); + final String textInput = field.getText(); + if (!Utils.isNullOrEmpty(textInput)) { + MapValue properties = mapper.readValue(textInput, MapValue.class); + entity.setProperty(property, properties); } } catch (IOException ex) { LOGGER.error("Not valid json.", ex); - Utils.showAlert( - Alert.AlertType.ERROR, - "Failed to update", - "Failed to update the entity.", - ex); - } - } - - @Override - public EntityType getType() { - return EntityType.OBSERVED_PROPERTY; - } - - @Override - public void init(SensorThingsService service, ObservedProperty entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { - this.labelId = labelId; - this.entity = entity; - int i = 0; - textName = addFieldTo(gridProperties, i, "Name", new TextField(), false, editable); - textDefinition = addFieldTo(gridProperties, ++i, "Definition", new TextField(), false, editable); - textDescription = addFieldTo(gridProperties, ++i, "Description", new TextArea(), true, editable); - textProperties = addFieldTo(gridProperties, ++i, "Properties", new TextArea(), true, editable); - - if (accordionLinks != null) { - try { - TitledPane tp = new TitledPane("Datastreams", createCollectionPaneFor(entity.datastreams().query(), "name asc")); - accordionLinks.getPanes().add(tp); - tp = new TitledPane("MultiDatastreams", createCollectionPaneFor(entity.multiDatastreams().query(), "name asc")); - accordionLinks.getPanes().add(tp); - } catch (NullPointerException e) { - // Happens when entity is new. - } } } } - public static class GuiControllerSensor implements EntityGuiController { - - /** - * The logger for this class. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); - private Label labelId; - private Sensor entity; - - private TextField textName; - private TextArea textDescription; - private TextField textEncodingType; - private TextArea textMetadata; - private TextArea textProperties; + public static class GuiGlueSimpleString implements PropertyGuiGlue { - @Override - public void loadFields() { - if (entity == null) { - return; - } - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - textName.setText(entity.getName()); - textDescription.setText(entity.getDescription()); - textEncodingType.setText(entity.getEncodingType()); - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - textMetadata.setText(mapper.writeValueAsString(entity.getMetadata())); - } catch (JsonProcessingException ex) { - LOGGER.error("Metadata can not be converted to JSON.", ex); - } - try { - if (entity.getProperties() != null) { - String props = mapper.writeValueAsString(entity.getProperties()); - textProperties.setText(props); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } - } - - @Override - public void saveFields() { - if (!Utils.isNullOrEmpty(textName.getText())) { - entity.setName(textName.getText()); - } - if (!Utils.isNullOrEmpty(textDescription.getText())) { - entity.setDescription(textDescription.getText()); - } - if (!Utils.isNullOrEmpty(textEncodingType.getText())) { - entity.setEncodingType(textEncodingType.getText()); - } - - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - JsonNode json = mapper.readTree(textMetadata.getText()); - entity.setMetadata(json); - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); - entity.setMetadata(textMetadata.getText()); - } - try { - if (!Utils.isNullOrEmpty(textProperties.getText())) { - Map properties = mapper.readValue(textProperties.getText(), TYPE_MAP_STRING_OBJECT); - entity.setProperties(properties); - } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); - } - } - - @Override - public EntityType getType() { - return EntityType.SENSOR; - } + private final ComplexValue entity; + private final EntityProperty property; + private TextField field; - @Override - public void init(SensorThingsService service, Sensor entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { - this.labelId = labelId; + public GuiGlueSimpleString(ComplexValue entity, EntityProperty property) { this.entity = entity; - int i = 0; - textName = addFieldTo(gridProperties, i, "Name", new TextField(), false, editable); - textDescription = addFieldTo(gridProperties, ++i, "Description", new TextArea(), true, editable); - textEncodingType = addFieldTo(gridProperties, ++i, "EncodingType", new TextField(), false, editable); - textMetadata = addFieldTo(gridProperties, ++i, "Metadata", new TextArea(), true, editable); - textProperties = addFieldTo(gridProperties, ++i, "Properties", new TextArea(), true, editable); - - if (accordionLinks != null) { - try { - TitledPane tp = new TitledPane("Datastreams", createCollectionPaneFor(entity.datastreams().query(), "name asc")); - accordionLinks.getPanes().add(tp); - tp = new TitledPane("MultiDatastreams", createCollectionPaneFor(entity.multiDatastreams().query(), "name asc")); - accordionLinks.getPanes().add(tp); - } catch (NullPointerException e) { - // Happens when entity is new. - } - } + this.property = property; } - } - - public static class GuiControllerThing implements EntityGuiController { - - /** - * The logger for this class. - */ - private static final Logger LOGGER = LoggerFactory.getLogger(GuiControllerThing.class); - private Label labelId; - private Thing entity; - private TextField textName; - private TextArea textDescription; - private TextArea textProperties; - - @Override - public void loadFields() { - if (entity == null) { - return; - } - if (entity.getId() != null) { - labelId.setText(entity.getId().toString()); - } - textName.setText(entity.getName()); - textDescription.setText(entity.getDescription()); - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - Map properties = entity.getProperties(); - if (properties != null) { - String props = mapper.writeValueAsString(properties); - textProperties.setText(props); - } - } catch (JsonProcessingException ex) { - LOGGER.error("Properties can not be converted to JSON.", ex); - } + public GuiGlueSimpleString init(GridPane gridProperties, AtomicInteger itemCount, boolean editable) { + return init("", gridProperties, itemCount, editable); } - @Override - public void saveFields() { - if (!Utils.isNullOrEmpty(textName.getText())) { - entity.setName(textName.getText()); - } - if (!Utils.isNullOrEmpty(textDescription.getText())) { - entity.setDescription(textDescription.getText()); - } - final ObjectMapper mapper = ObjectMapperFactory.get(); - try { - String jsonText = textProperties.getText(); - if (!jsonText.isEmpty()) { - Map properties = mapper.readValue(jsonText, TYPE_MAP_STRING_OBJECT); - entity.setProperties(properties); - } - } catch (IOException ex) { - LOGGER.error("Not valid json.", ex); - } + public GuiGlueSimpleString init(String namePrefix, GridPane gridProperties, AtomicInteger itemCount, boolean editable) { + field = addFieldTo(gridProperties, itemCount.getAndIncrement(), namePrefix + property, new TextField(), false, editable); + return this; } @Override - public EntityType getType() { - return EntityType.THING; + public void entityToGui() { + field.setText(Objects.toString(entity.getProperty(property))); } @Override - public void init(SensorThingsService service, Thing entity, GridPane gridProperties, Accordion accordionLinks, Label labelId, boolean editable) { - this.labelId = labelId; - this.entity = entity; - int i = 0; - textName = addFieldTo(gridProperties, i, "Name", new TextField(), false, editable); - textDescription = addFieldTo(gridProperties, ++i, "Description", new TextArea(), true, editable); - textProperties = addFieldTo(gridProperties, ++i, "Properties", new TextArea(), true, editable); - textProperties.setPrefRowCount(10); - - if (accordionLinks != null) { - try { - TitledPane tp = new TitledPane("Datastreams", createCollectionPaneFor(entity.datastreams().query(), "name asc")); - accordionLinks.getPanes().add(tp); - tp = new TitledPane("MultiDatastreams", createCollectionPaneFor(entity.multiDatastreams().query(), "name asc")); - accordionLinks.getPanes().add(tp); - ChildSetter locationChildSetter = new ChildSetter() { - @Override - public void setChild(Location child) { - throw new UnsupportedOperationException("This setter only deals with multiple childs."); - } - - @Override - public void setChildren(List children) { - EntityList locations = entity.getLocations(); - locations.clear(); - for (Location child : children) { - locations.add(child.withOnlyId()); - } - } - }; - tp = new TitledPane("Locations", createCollectionPaneFor(entity.locations().query(), "name asc", true, locationChildSetter)); - accordionLinks.getPanes().add(tp); - tp = new TitledPane("HistoricalLocations", createCollectionPaneFor(entity.historicalLocations().query(), "time desc")); - accordionLinks.getPanes().add(tp); - } catch (NullPointerException e) { - // Happens when entity is new. - } - } + public void guiToEntity() { + entity.setProperty(property, field.getText()); } + } - public static interface ChildSetter> { + public static interface ChildSetter { - public void setChild(C child); + public void setChild(Entity child); - default public void setChildren(List children) { + default public void setChildren(List children) { // Does nothing by default. } } - public static , P extends Entity

> TitledPane createEditableEntityPane( - final P parentEntity, - final C childEntity, - final Query childQuery, + public static TitledPane createEditableEntityPane( + final Entity parentEntity, + final Entity childEntity, + final Query childQuery, String orderby, - final ChildSetter setter) throws IOException { + final ChildSetter setter) throws IOException { - EntityType type = EntityType.singleForClass(childQuery.getEntityType().getType()); + EntityType type = childQuery.getEntityType(); String paneTitle; if (childEntity == null) { - paneTitle = type.getName() + ": None selected"; + paneTitle = type.getEntityName() + ": None selected"; } else { - paneTitle = childEntity.getType().getName() + ": " + childEntity.toString(); + paneTitle = childEntity.getEntityType().getEntityName() + ": " + childEntity.toString(); } Node pane = FactoryEntityPanel.getPane(childQuery.getService(), type, childEntity, false); TitledPane tp = new TitledPane(paneTitle, pane); Button edit = new Button("🔧"); tp.setGraphic(edit); edit.setOnAction((ActionEvent event) -> { - Optional> result = entitySearchDialog(childQuery, false, orderby); + Optional> result = entitySearchDialog(childQuery, false, orderby); if (result.isPresent() && !result.get().isEmpty()) { - C newChild = result.get().get(0); + Entity newChild = result.get().get(0); setter.setChild(newChild); try { tp.setContent(FactoryEntityPanel.getPane(childQuery.getService(), type, childEntity, false)); } catch (IOException ex) { LoggerFactory.getLogger(EntityGuiController.class).error("Failed to load Collection Pane.", ex); } - tp.setText(newChild.getType().getName() + ": " + newChild.toString()); + tp.setText(newChild.getEntityType().getEntityName() + ": " + newChild.toString()); } }); @@ -1086,11 +383,11 @@ public static T addFieldTo(GridPane gp, int row, String title, return node; } - public static > Pane createCollectionPaneFor(Query query, String orderBy) { + public static Pane createCollectionPaneFor(Query query, String orderBy) { return createCollectionPaneFor(query, orderBy, false, null); } - public static > Pane createCollectionPaneFor(Query query, String orderBy, boolean canLinkNew, ChildSetter childSetter) { + public static Pane createCollectionPaneFor(Query query, String orderBy, boolean canLinkNew, ChildSetter childSetter) { try { FXMLLoader loader = new FXMLLoader(EntityGuiController.class.getResource("/fxml/Collection.fxml")); AnchorPane content = (AnchorPane) loader.load(); @@ -1106,19 +403,19 @@ public static > Pane createCollectionPaneFor(Query query, return null; } - public static > Optional> entitySearchDialog(Query query, boolean multiSelect, String orderBy) { + public static Optional> entitySearchDialog(Query query, boolean multiSelect, String orderBy) { try { FXMLLoader loader = new FXMLLoader(EntityGuiController.class.getResource("/fxml/Collection.fxml")); AnchorPane content = (AnchorPane) loader.load(); - final ControllerCollection controller = loader.>getController(); + final ControllerCollection controller = loader.getController(); controller.setQuery(query, false, false, false, multiSelect, orderBy); - Dialog> dialog = new Dialog<>(); + Dialog> dialog = new Dialog<>(); dialog.setHeight(800); if (multiSelect) { - dialog.setTitle("Choose one or more " + EntityType.singleForClass(query.getEntityType().getType()).getName()); + dialog.setTitle("Choose one or more " + query.getEntityType().getEntityName()); } else { - dialog.setTitle("Choose a " + EntityType.singleForClass(query.getEntityType().getType()).getName()); + dialog.setTitle("Choose a " + query.getEntityType().getEntityName()); } dialog.setResizable(true); dialog.getDialogPane().setContent(content); @@ -1131,7 +428,7 @@ public static > Optional> entitySearchDialog(Query list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(controller.getSelectedEntity()); return list; } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/EntityListEntry.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/EntityListEntry.java index 02778db..48b12c4 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/EntityListEntry.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/EntityListEntry.java @@ -1,15 +1,14 @@ package de.fraunhofer.iosb.ilt.sensorthingsmanager.controller; -import de.fraunhofer.iosb.ilt.sta.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; /** * * @author scf - * @param The entity type. */ -public class EntityListEntry> { +public class EntityListEntry { - private T entity; + private Entity entity; private boolean changed = false; @Override @@ -20,7 +19,7 @@ public String toString() { /** * @return the entity */ - public T getEntity() { + public Entity getEntity() { return entity; } @@ -28,7 +27,7 @@ public T getEntity() { * @param entity the entity to set. * @return this EntityListEntry. */ - public EntityListEntry setEntity(T entity) { + public EntityListEntry setEntity(Entity entity) { this.entity = entity; return this; } @@ -44,7 +43,7 @@ public boolean isChanged() { * @param changed the changed to set. * @return this EntityListEntry. */ - public EntityListEntry setChanged(boolean changed) { + public EntityListEntry setChanged(boolean changed) { this.changed = changed; return this; } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/FactoryEntityPanel.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/FactoryEntityPanel.java index 2c1d058..7ec703d 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/FactoryEntityPanel.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/controller/FactoryEntityPanel.java @@ -1,21 +1,10 @@ package de.fraunhofer.iosb.ilt.sensorthingsmanager.controller; -import de.fraunhofer.iosb.ilt.sensorthingsmanager.controller.EntityGuiController; -import de.fraunhofer.iosb.ilt.sensorthingsmanager.controller.ControllerEntity; +import de.fraunhofer.iosb.ilt.frostclient.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.EntityType; import java.io.IOException; -import de.fraunhofer.iosb.ilt.sta.model.Datastream; -import de.fraunhofer.iosb.ilt.sta.model.Entity; -import de.fraunhofer.iosb.ilt.sta.model.EntityType; -import de.fraunhofer.iosb.ilt.sta.model.FeatureOfInterest; -import de.fraunhofer.iosb.ilt.sta.model.HistoricalLocation; -import de.fraunhofer.iosb.ilt.sta.model.Location; -import de.fraunhofer.iosb.ilt.sta.model.MultiDatastream; -import de.fraunhofer.iosb.ilt.sta.model.Observation; -import de.fraunhofer.iosb.ilt.sta.model.ObservedProperty; -import de.fraunhofer.iosb.ilt.sta.model.Sensor; -import de.fraunhofer.iosb.ilt.sta.model.Thing; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; import javafx.fxml.FXMLLoader; import javafx.scene.Node; import javafx.scene.control.Label; @@ -29,117 +18,17 @@ public class FactoryEntityPanel { private static final String ENTITY_PANE_FXML = "/fxml/PaneEntity.fxml"; - public static > Node getPane(SensorThingsService service, EntityType type, T entity, boolean showNavProps) throws IOException { - if (entity != null && entity.getType() != type) { + public static Node getPane(SensorThingsService service, EntityType type, Entity entity, boolean showNavProps) throws IOException { + if (entity != null && entity.getEntityType() != type) { throw new IllegalArgumentException("Entity must have given type or be null."); } - switch (type) { - case DATASTREAM: - return getDatastreamPane(service, (Datastream) entity, showNavProps); - - case FEATURE_OF_INTEREST: - return getFeatureOfInterestPane(service, (FeatureOfInterest) entity, showNavProps); - - case HISTORICAL_LOCATION: - return getHistoricalLocationPane(service, (HistoricalLocation) entity, showNavProps); - - case LOCATION: - return getLocationPane(service, (Location) entity, showNavProps); - - case MULTIDATASTREAM: - return getMultiDatastreamPane(service, (MultiDatastream) entity, showNavProps); - - case OBSERVATION: - return getObservationPane(service, (Observation) entity, showNavProps); - - case OBSERVED_PROPERTY: - return getObsPropPane(service, (ObservedProperty) entity, showNavProps); - - case SENSOR: - return getSensorPane(service, (Sensor) entity, showNavProps); - - case THING: - return getThingPane(service, (Thing) entity, showNavProps); - - } - return null; - } - - public static Node getDatastreamPane(SensorThingsService service, Datastream entity, boolean showNavProps) throws IOException { if (entity == null) { - return new Label("No Datastream."); + return new Label("No " + type.entityName + "."); } FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); Node content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerDatastream(), showNavProps); - return content; - } - - public static Node getFeatureOfInterestPane(SensorThingsService service, FeatureOfInterest entity, boolean showNavProps) throws IOException { - FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); - Pane content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerFeatureOfInterest(), showNavProps); - return content; - } - - public static Node getHistoricalLocationPane(SensorThingsService service, HistoricalLocation entity, boolean showNavProps) throws IOException { - FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); - Pane content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerHistoricalLocation(), showNavProps); - return content; - } - - public static Node getLocationPane(SensorThingsService service, Location entity, boolean showNavProps) throws IOException { - FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); - Pane content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerLocation(), showNavProps); - return content; - } - - public static Node getMultiDatastreamPane(SensorThingsService service, MultiDatastream entity, boolean showNavProps) throws IOException { - if (entity == null) { - return new Label("No MultiDatastream."); - } - FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); - Pane content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerMultiDatastream(), showNavProps); - return content; - } - - public static Node getObservationPane(SensorThingsService service, Observation entity, boolean showNavProps) throws IOException { - FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); - Pane content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerObservation(), showNavProps); - return content; - } - - public static Node getObsPropPane(SensorThingsService service, ObservedProperty entity, boolean showNavProps) throws IOException { - FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); - Pane content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerObsProp(), showNavProps); - return content; - } - - public static Node getSensorPane(SensorThingsService service, Sensor entity, boolean showNavProps) throws IOException { - FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); - Pane content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerSensor(), showNavProps); - return content; - } - - public static Node getThingPane(SensorThingsService service, Thing entity, boolean showNavProps) throws IOException { - FXMLLoader loader = new FXMLLoader(FactoryEntityPanel.class.getResource(ENTITY_PANE_FXML)); - Pane content = (Pane) loader.load(); - ControllerEntity controller = loader.>getController(); - controller.setEntity(service, entity, new EntityGuiController.GuiControllerThing(), showNavProps); + ControllerEntity controller = loader.getController(); + controller.setEntity(service, entity, new EntityGuiController.GuiControllerDefault(type), showNavProps); return content; } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/DateTimePicker.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/DateTimePicker.java index e95d463..be11adf 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/DateTimePicker.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/DateTimePicker.java @@ -26,6 +26,7 @@ import javafx.scene.control.Spinner; import javafx.scene.layout.GridPane; import javafx.scene.text.Text; +import net.time4j.Moment; /** * @@ -44,6 +45,10 @@ public DateTimePicker() { this(ZonedDateTime.now()); } + public DateTimePicker(Moment initialValue) { + this(initialValue.toTemporalAccessor()); + } + public DateTimePicker(Instant initialValue) { if (initialValue == null) { initialValue = Instant.now(); diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/ObjectMapperFactory.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/ObjectMapperFactory.java index 3820547..a5e05f1 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/ObjectMapperFactory.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/ObjectMapperFactory.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import de.fraunhofer.iosb.ilt.frostclient.json.SimpleJsonMapper; /** * Factory for ObjectMapper instances. Keeps track of configuration. @@ -26,12 +26,8 @@ private ObjectMapperFactory() { */ public static ObjectMapper get() { if (mapper == null) { - mapper = new ObjectMapper(); + mapper = SimpleJsonMapper.getSimpleObjectMapper().copy(); mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); - mapper.disable(SerializationFeature.WRITE_NULL_MAP_VALUES); - mapper.registerModule(new JavaTimeModule()); - // Write any date/time values as ISO-8601 formated strings. - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.enable(SerializationFeature.INDENT_OUTPUT); } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/Server.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/Server.java index 1d32b61..9ece0d6 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/Server.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/Server.java @@ -18,9 +18,12 @@ import de.fraunhofer.iosb.ilt.configurable.AbstractConfigurable; import de.fraunhofer.iosb.ilt.configurable.annotations.ConfigurableField; +import de.fraunhofer.iosb.ilt.configurable.editor.EditorList; import de.fraunhofer.iosb.ilt.configurable.editor.EditorString; import de.fraunhofer.iosb.ilt.configurable.editor.EditorSubclass; +import de.fraunhofer.iosb.ilt.frostclient.models.DataModel; import de.fraunhofer.iosb.ilt.sensorthingsmanager.auth.AuthMethod; +import java.util.List; /** * @@ -47,6 +50,12 @@ public class Server extends AbstractConfigurable { @EditorSubclass.EdOptsSubclass(iface = AuthMethod.class, nameField = "authClass") private AuthMethod authMethod; + @ConfigurableField(editor = EditorList.class, + label = "Data Models", description = "A list of data models, loaded in the given order.") + @EditorList.EdOptsList(editor = EditorSubclass.class) + @EditorSubclass.EdOptsSubclass(iface = DataModel.class) + private List dataModels; + /** * @return the name */ @@ -82,6 +91,14 @@ public Server setUrl(String Url) { return this; } + public List getDataModels() { + return dataModels; + } + + public void setDataModels(List dataModels) { + this.dataModels = dataModels; + } + public AuthMethod getAuthMethod() { return authMethod; } diff --git a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/Utils.java b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/Utils.java index fda3426..899a3ec 100644 --- a/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/Utils.java +++ b/src/main/java/de/fraunhofer/iosb/ilt/sensorthingsmanager/utils/Utils.java @@ -16,12 +16,11 @@ */ package de.fraunhofer.iosb.ilt.sensorthingsmanager.utils; -import de.fraunhofer.iosb.ilt.sta.ServiceFailureException; -import de.fraunhofer.iosb.ilt.sta.StatusCodeException; -import de.fraunhofer.iosb.ilt.sta.dao.BaseDao; -import de.fraunhofer.iosb.ilt.sta.model.Entity; -import de.fraunhofer.iosb.ilt.sta.model.ext.EntityList; -import de.fraunhofer.iosb.ilt.sta.service.SensorThingsService; +import de.fraunhofer.iosb.ilt.frostclient.dao.BaseDao; +import de.fraunhofer.iosb.ilt.frostclient.exception.ServiceFailureException; +import de.fraunhofer.iosb.ilt.frostclient.exception.StatusCodeException; +import de.fraunhofer.iosb.ilt.frostclient.model.Entity; +import de.fraunhofer.iosb.ilt.frostclient.model.EntitySet; import java.io.PrintWriter; import java.io.StringWriter; import javafx.scene.control.Alert; @@ -79,26 +78,17 @@ public static void showAlert(Alert.AlertType type, String title, String text, Th alert.showAndWait(); } - public static void deleteAll(SensorThingsService sts) throws ServiceFailureException { - deleteAll(sts.things()); - deleteAll(sts.locations()); - deleteAll(sts.sensors()); - deleteAll(sts.featuresOfInterest()); - deleteAll(sts.observedProperties()); - deleteAll(sts.observations()); - } - - public static > void deleteAll(BaseDao doa) throws ServiceFailureException { + public static void deleteAll(BaseDao doa) throws ServiceFailureException { boolean more = true; int count = 0; while (more) { - EntityList entities = doa.query().count().list(); + EntitySet entities = doa.query().count().list(); if (entities.getCount() > 0) { LOGGER.info("{} to go.", entities.getCount()); } else { more = false; } - for (T entity : entities) { + for (Entity entity : entities) { doa.delete(entity); count++; } diff --git a/src/main/resources/fxml/Scene.fxml b/src/main/resources/fxml/Scene.fxml index 389cfe6..b135740 100644 --- a/src/main/resources/fxml/Scene.fxml +++ b/src/main/resources/fxml/Scene.fxml @@ -18,7 +18,7 @@

- + diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 42898fc..d322173 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -6,7 +6,6 @@ -