From 3f6706a573cb865cf76cc06249d54855d4d86fce Mon Sep 17 00:00:00 2001 From: Hylke van der Schaaf Date: Sun, 19 May 2024 15:17:55 +0200 Subject: [PATCH] Reworked special handling of tables into hooks --- .../coremodel/HookPostDeleteLocation.java | 48 +++++ .../coremodel/HookPostInsertHistLoc.java | 87 ++++++++ .../HookPrePostInsertUpdateLocation.java | 191 ++++++++++++++++ .../HookPrePostInsertUpdateThing.java | 203 ++++++++++++++++++ .../coremodel/TableImpHistLocations.java | 61 +----- .../plugin/coremodel/TableImpLocations.java | 100 +-------- .../plugin/coremodel/TableImpThings.java | 85 +------- .../model/HistoricalLocation.json | 135 ++++++------ .../plugincoremodelv2/model/Location.json | 7 + Tools/ModelEditor/pom.xml | 5 + 10 files changed, 624 insertions(+), 298 deletions(-) create mode 100644 Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPostDeleteLocation.java create mode 100644 Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPostInsertHistLoc.java create mode 100644 Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPrePostInsertUpdateLocation.java create mode 100644 Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPrePostInsertUpdateThing.java diff --git a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPostDeleteLocation.java b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPostDeleteLocation.java new file mode 100644 index 000000000..8af4b60ee --- /dev/null +++ b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPostDeleteLocation.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 + * Karlsruhe, Germany. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel; + +import de.fraunhofer.iosb.ilt.frostserver.model.core.PkValue; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.JooqPersistenceManager; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPostDelete; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.TableCollection; +import de.fraunhofer.iosb.ilt.frostserver.util.exception.NoSuchEntityException; +import org.jooq.TableField; +import org.jooq.impl.DSL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author hylke + */ +class HookPostDeleteLocation implements HookPostDelete { + + private static final Logger LOGGER = LoggerFactory.getLogger(HookPostDeleteLocation.class.getName()); + + @Override + public void postDelete(JooqPersistenceManager pm, PkValue entityId) throws NoSuchEntityException { + final TableCollection tables = pm.getTableCollection(); + // Also postDelete all historicalLocations that no longer reference any location + TableImpHistLocations thl = tables.getTableForClass(TableImpHistLocations.class); + TableImpLocationsHistLocations tlhl = tables.getTableForClass(TableImpLocationsHistLocations.class); + int count = pm.getDslContext().delete(thl).where(((TableField) thl.getId()).in(DSL.select(thl.getId()).from(thl).leftJoin(tlhl).on(((TableField) thl.getId()).eq(tlhl.getHistLocationId())).where(tlhl.getLocationId().isNull()))).execute(); + LOGGER.debug("Deleted {} HistoricalLocations", count); + } + +} diff --git a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPostInsertHistLoc.java b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPostInsertHistLoc.java new file mode 100644 index 000000000..740c35c0f --- /dev/null +++ b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPostInsertHistLoc.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 + * Karlsruhe, Germany. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel; + +import de.fraunhofer.iosb.ilt.frostserver.model.EntityType; +import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity; +import de.fraunhofer.iosb.ilt.frostserver.model.ext.TimeInstant; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.JooqPersistenceManager; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.EntityFactories; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPostInsert; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.TableCollection; +import de.fraunhofer.iosb.ilt.frostserver.property.EntityPropertyMain; +import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntity; +import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntitySet; +import de.fraunhofer.iosb.ilt.frostserver.util.exception.IncompleteEntityException; +import de.fraunhofer.iosb.ilt.frostserver.util.exception.NoSuchEntityException; +import java.util.Collections; +import java.util.Map; +import net.time4j.Moment; +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.Record; +import org.jooq.TableField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author hylke + */ +class HookPostInsertHistLoc implements HookPostInsert { + + private static final Logger LOGGER = LoggerFactory.getLogger(HookPostInsertHistLoc.class.getName()); + + @Override + public boolean postInsertIntoDatabase(JooqPersistenceManager pm, Entity histLoc, Map insertFields) throws NoSuchEntityException, IncompleteEntityException { + final EntityFactories ef = pm.getEntityFactories(); + final TableCollection tc = pm.getTableCollection(); + final EntityType etHistLoc = histLoc.getEntityType(); + final NavigationPropertyEntity npThing = (NavigationPropertyEntity) etHistLoc.getNavigationProperty("Thing"); + final NavigationPropertyEntitySet npLocations = (NavigationPropertyEntitySet) etHistLoc.getNavigationProperty("Locations"); + final EntityPropertyMain epTime = etHistLoc.getEntityProperty("time"); + Entity thing = histLoc.getProperty(npThing); + Object thingId = thing.getPrimaryKeyValues().get(0); + DSLContext dslContext = pm.getDslContext(); + TableImpHistLocations thl = tc.getTableForClass(TableImpHistLocations.class); + final TimeInstant hlTime = histLoc.getProperty(epTime); + Moment newTime = hlTime.getDateTime(); + // https://github.com/opengeospatial/sensorthings/issues/30 + // Check the time of the latest HistoricalLocation of our thing. + // If this time is earlier than our time, set the Locations of our Thing to our Locations. + Record lastHistLocation = dslContext.select(Collections.emptyList()).from(thl).where(((TableField) thl.getThingId()).eq(thingId).and(thl.time.gt(newTime))).orderBy(thl.time.desc()).limit(1).fetchOne(); + if (lastHistLocation == null) { + // We are the newest. + // Unlink old Locations from Thing. + TableImpThingsLocations qtl = tc.getTableForClass(TableImpThingsLocations.class); + long count = dslContext.delete(qtl).where(((TableField) qtl.getThingId()).eq(thingId)).execute(); + LOGGER.debug(EntityFactories.UNLINKED_L_FROM_T, count, thingId); + // Link new locations to Thing. + for (Entity l : histLoc.getProperty(npLocations)) { + if (!l.getPrimaryKeyValues().isFullySet() || !ef.entityExists(pm, l, true)) { + throw new NoSuchEntityException("Location with no id."); + } + Object locationId = l.getPrimaryKeyValues().get(0); + dslContext.insertInto(qtl).set((TableField) qtl.getThingId(), thingId).set(qtl.getLocationId(), locationId).execute(); + LOGGER.debug(EntityFactories.LINKED_L_TO_T, locationId, thingId); + } + } + return true; + } + +} diff --git a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPrePostInsertUpdateLocation.java b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPrePostInsertUpdateLocation.java new file mode 100644 index 000000000..67a04c048 --- /dev/null +++ b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPrePostInsertUpdateLocation.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 + * Karlsruhe, Germany. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel; + +import de.fraunhofer.iosb.ilt.configurable.annotations.ConfigurableField; +import de.fraunhofer.iosb.ilt.configurable.editor.EditorString; +import de.fraunhofer.iosb.ilt.frostserver.model.EntityChangedMessage; +import de.fraunhofer.iosb.ilt.frostserver.model.EntityType; +import de.fraunhofer.iosb.ilt.frostserver.model.ModelRegistry; +import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity; +import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySet; +import de.fraunhofer.iosb.ilt.frostserver.model.core.PkValue; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.JooqPersistenceManager; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.EntityFactories; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPostInsert; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPostUpdate; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPreInsert; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPreUpdate; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.StaTable; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.TableCollection; +import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntitySet; +import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode; +import de.fraunhofer.iosb.ilt.frostserver.util.exception.IncompleteEntityException; +import de.fraunhofer.iosb.ilt.frostserver.util.exception.NoSuchEntityException; +import java.util.Map; +import net.time4j.Moment; +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.TableField; +import org.jooq.exception.DataAccessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author hylke + */ +public class HookPrePostInsertUpdateLocation implements HookPreInsert, HookPostInsert, HookPreUpdate, HookPostUpdate { + + private static final Logger LOGGER = LoggerFactory.getLogger(HookPrePostInsertUpdateLocation.class); + + @ConfigurableField(editor = EditorString.class, + label = "Things Locations LinkTable") + @EditorString.EdOptsString(dflt = "THINGS_LOCATIONS") + private String ttlName = "THINGS_LOCATIONS"; + + @ConfigurableField(editor = EditorString.class, + label = "LinkTable ThingId") + @EditorString.EdOptsString(dflt = "THING_ID") + private String ttlThingIdName = "THING_ID"; + + @ConfigurableField(editor = EditorString.class, + label = "LinkTable LocationId") + @EditorString.EdOptsString(dflt = "LOCATION_ID") + private String ttlLocationIdName = "LOCATION_ID"; + + @ConfigurableField(editor = EditorString.class, + label = "Locations-HistLocations LinkTable") + @EditorString.EdOptsString(dflt = "LOCATIONS_HIST_LOCATIONS") + private String tlhlName = "LOCATIONS_HIST_LOCATIONS"; + + @ConfigurableField(editor = EditorString.class, + label = "LinkTable HistLocationId") + @EditorString.EdOptsString(dflt = "HIST_LOCATION_ID") + private String tlhlHistLocationIdName = "HIST_LOCATION_ID"; + + @ConfigurableField(editor = EditorString.class, + label = "Time Field") + @EditorString.EdOptsString(dflt = "TIME") + private String thlTimeName = "TIME"; + + @Override + public boolean preInsertIntoDatabase(Phase fase, JooqPersistenceManager pm, Entity entity, Map insertFields) throws NoSuchEntityException, IncompleteEntityException { + unlinkExitingLocationsFromLinkedThings(pm, entity); + return true; + } + + @Override + public boolean postInsertIntoDatabase(JooqPersistenceManager pm, Entity entity, Map insertFields) throws NoSuchEntityException, IncompleteEntityException { + PkValue entityId = entity.getPrimaryKeyValues(); + createHistLocationLinkLocations(pm, entity, entityId); + return true; + } + + @Override + public void preUpdateInDatabase(JooqPersistenceManager pm, Entity entity, PkValue entityId, UpdateMode updateMode) throws NoSuchEntityException, IncompleteEntityException { + unlinkExitingLocationsFromLinkedThings(pm, entity); + } + + @Override + public void postUpdateInDatabase(JooqPersistenceManager pm, Entity entity, PkValue entityId, UpdateMode updateMode) throws NoSuchEntityException, IncompleteEntityException { + createHistLocationLinkLocations(pm, entity, entityId); + } + + private void unlinkExitingLocationsFromLinkedThings(JooqPersistenceManager pm, Entity entity) { + TableCollection tables = pm.getTableCollection(); + EntityType et = entity.getEntityType(); + NavigationPropertyEntitySet npLocationThings = et.getNavigationPropertyEntitySet("Things"); + if (npLocationThings == null) { + LOGGER.error("EntityType {} has no navigationPropertySet Things", et); + return; + } + NavigationPropertyEntitySet npLocationHistLocs = et.getNavigationPropertyEntitySet("HistoricalLocations"); + if (npLocationHistLocs == null) { + LOGGER.error("EntityType {} has no navigationPropertySet HistoricalLocations", et); + return; + } + EntitySet things = entity.getProperty(npLocationThings); + // Maybe create a Historical Location for things linked to this Location. + if (things != null && !things.isEmpty()) { + for (Entity thing : things) { + Object thingId = thing.getPrimaryKeyValues().get(0); + if (thingId != null) { + DSLContext dslContext = pm.getDslContext(); + StaTable ttl = tables.getTableForName(ttlName); + // Unlink old Locations from Thing. + long count = dslContext.delete(ttl).where(((TableField) ttl.field(ttlThingIdName)).eq(thingId)).execute(); + LOGGER.debug(EntityFactories.UNLINKED_L_FROM_T, count, thingId); + } + } + } + } + + public void createHistLocationLinkLocations(JooqPersistenceManager pm, Entity entity, PkValue entityId) throws DataAccessException { + TableCollection tables = pm.getTableCollection(); + EntityType et = entity.getEntityType(); + NavigationPropertyEntitySet npLocationThings = et.getNavigationPropertyEntitySet("Things"); + if (npLocationThings == null) { + LOGGER.error("EntityType {} has no navigationPropertySet Things", et); + return; + } + NavigationPropertyEntitySet npLocationHistLocs = et.getNavigationPropertyEntitySet("HistoricalLocations"); + if (npLocationHistLocs == null) { + LOGGER.error("EntityType {} has no navigationPropertySet HistoricalLocations", et); + return; + } + EntityType etHistLoc = npLocationHistLocs.getEntityType(); + EntitySet things = entity.getProperty(npLocationThings); + DSLContext dslContext = pm.getDslContext(); + Object locationId = entityId.get(0); + // Maybe create a Historical Location for things linked to this Location. + if (things != null && !things.isEmpty()) { + final ModelRegistry modelRegistry = pm.getCoreSettings().getModelRegistry(); + for (Entity thing : things) { + Object thingId = thing.getPrimaryKeyValues().get(0); + + // Create HistoricalLocation for Thing + TableImpHistLocations qhl = tables.getTableForClass(TableImpHistLocations.class); + Object histLocationId = dslContext.insertInto(qhl) + .set((TableField) qhl.getThingId(), thingId) + .set(qhl.time, Moment.nowInSystemTime()) + .returningResult(qhl.getId()) + .fetchOne(0); + LOGGER.debug(EntityFactories.CREATED_HL, histLocationId); + + // Link Location to HistoricalLocation. + TableImpLocationsHistLocations qlhl = tables.getTableForClass(TableImpLocationsHistLocations.class); + dslContext.insertInto(qlhl) + .set((TableField) qlhl.getHistLocationId(), histLocationId) + .set(qlhl.getLocationId(), locationId) + .execute(); + LOGGER.debug(EntityFactories.LINKED_L_TO_HL, locationId, histLocationId); + + // Send a message about the creation of a new HL + Entity newHl = pm.get(etHistLoc, PkValue.of(histLocationId)); + newHl.setQuery(modelRegistry.getMessageQueryGenerator().getQueryFor(newHl.getEntityType())); + pm.getEntityChangedMessages().add( + new EntityChangedMessage() + .setEventType(EntityChangedMessage.Type.CREATE) + .setEntity(newHl)); + + } + } + } + +} diff --git a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPrePostInsertUpdateThing.java b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPrePostInsertUpdateThing.java new file mode 100644 index 000000000..5126010f1 --- /dev/null +++ b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/HookPrePostInsertUpdateThing.java @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2023 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 + * Karlsruhe, Germany. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel; + +import de.fraunhofer.iosb.ilt.configurable.annotations.ConfigurableField; +import de.fraunhofer.iosb.ilt.configurable.editor.EditorString; +import de.fraunhofer.iosb.ilt.frostserver.model.EntityChangedMessage; +import de.fraunhofer.iosb.ilt.frostserver.model.EntityType; +import de.fraunhofer.iosb.ilt.frostserver.model.ModelRegistry; +import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity; +import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySet; +import de.fraunhofer.iosb.ilt.frostserver.model.core.PkValue; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.JooqPersistenceManager; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.EntityFactories; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPostInsert; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPostUpdate; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPreInsert; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.HookPreUpdate; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.StaMainTable; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.StaTable; +import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.TableCollection; +import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain.NavigationPropertyEntitySet; +import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode; +import de.fraunhofer.iosb.ilt.frostserver.util.exception.IncompleteEntityException; +import de.fraunhofer.iosb.ilt.frostserver.util.exception.NoSuchEntityException; +import java.util.Map; +import net.time4j.Moment; +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.TableField; +import org.jooq.exception.DataAccessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author hylke + */ +public class HookPrePostInsertUpdateThing implements HookPreInsert, HookPostInsert, HookPreUpdate, HookPostUpdate { + + private static final Logger LOGGER = LoggerFactory.getLogger(HookPrePostInsertUpdateThing.class); + + @ConfigurableField(editor = EditorString.class, + label = "Things Locations LinkTable") + @EditorString.EdOptsString(dflt = "THINGS_LOCATIONS") + private String ttlName = "THINGS_LOCATIONS"; + + @ConfigurableField(editor = EditorString.class, + label = "LinkTable ThingId") + @EditorString.EdOptsString(dflt = "THING_ID") + private String ttlThingIdName = "THING_ID"; + + @ConfigurableField(editor = EditorString.class, + label = "LinkTable LocationId") + @EditorString.EdOptsString(dflt = "LOCATION_ID") + private String ttlLocationIdName = "LOCATION_ID"; + + @ConfigurableField(editor = EditorString.class, + label = "Locations-HistLocations LinkTable") + @EditorString.EdOptsString(dflt = "LOCATIONS_HIST_LOCATIONS") + private String tlhlName = "LOCATIONS_HIST_LOCATIONS"; + + @ConfigurableField(editor = EditorString.class, + label = "LinkTable HistLocationId") + @EditorString.EdOptsString(dflt = "HIST_LOCATION_ID") + private String tlhlHistLocationIdName = "HIST_LOCATION_ID"; + + @ConfigurableField(editor = EditorString.class, + label = "Time Field") + @EditorString.EdOptsString(dflt = "TIME") + private String thlTimeName = "TIME"; + + @Override + public boolean preInsertIntoDatabase(Phase fase, JooqPersistenceManager pm, Entity entity, Map insertFields) throws NoSuchEntityException, IncompleteEntityException { + return true; + } + + @Override + public boolean postInsertIntoDatabase(JooqPersistenceManager pm, Entity entity, Map insertFields) throws NoSuchEntityException, IncompleteEntityException { + PkValue entityId = entity.getPrimaryKeyValues(); + createHistLocationLinkLocations(pm, entity, entityId); + return true; + } + + @Override + public void preUpdateInDatabase(JooqPersistenceManager pm, Entity entity, PkValue entityId, UpdateMode updateMode) throws NoSuchEntityException, IncompleteEntityException { + TableCollection tables = pm.getTableCollection(); + EntityType et = entity.getEntityType(); + NavigationPropertyEntitySet npThingLocations = et.getNavigationPropertyEntitySet("Locations"); + if (npThingLocations == null) { + LOGGER.error("Given Entity of type {} has no navigationPropertySet Locations", et); + return; + } + EntitySet locations = entity.getProperty(npThingLocations); + if (locations != null && !locations.isEmpty()) { + // New locations to be set, delete old locations. + Object thingId = entityId.get(0); + DSLContext dslContext = pm.getDslContext(); + StaTable ttl = tables.getTableForName(ttlName); + // Unlink old Locations from Thing. + long count = dslContext.delete(ttl).where(((TableField) ttl.field(ttlThingIdName)).eq(thingId)).execute(); + LOGGER.debug(EntityFactories.UNLINKED_L_FROM_T, count, thingId); + } + } + + @Override + public void postUpdateInDatabase(JooqPersistenceManager pm, Entity entity, PkValue entityId, UpdateMode updateMode) throws NoSuchEntityException, IncompleteEntityException { + createHistLocationLinkLocations(pm, entity, entityId); + } + + public void createHistLocationLinkLocations(JooqPersistenceManager pm, Entity entity, PkValue entityId) throws DataAccessException { + TableCollection tables = pm.getTableCollection(); + EntityType et = entity.getEntityType(); + NavigationPropertyEntitySet npThingLocations = et.getNavigationPropertyEntitySet("Locations"); + if (npThingLocations == null) { + LOGGER.error("EntityType {} has no navigationPropertySet Locations", et); + return; + } + NavigationPropertyEntitySet npThingHistLocs = et.getNavigationPropertyEntitySet("HistoricalLocations"); + if (npThingHistLocs == null) { + LOGGER.error("EntityType {} has no navigationPropertySet HistoricalLocations", et); + return; + } + EntityType etHistLoc = npThingHistLocs.getEntityType(); + EntitySet locations = entity.getProperty(npThingLocations); + DSLContext dslContext = pm.getDslContext(); + Object thingId = entityId.get(0); + // Now link the new locations also to a historicalLocation. + if (locations != null && !locations.isEmpty()) { + // Insert a new HL into the DB + StaMainTable thl = tables.getTableForType(etHistLoc); + Object histLocationId = dslContext.insertInto(thl) + .set((TableField) thl.field(thlTimeName), Moment.nowInSystemTime()) + .set((TableField) thl.field(ttlThingIdName), thingId) + .returningResult(thl.getPkFields().get(0)) + .fetchOne(0); + LOGGER.debug(EntityFactories.CREATED_HL, histLocationId); + + // Link the locations to the new HL + StaTable tlhl = tables.getTableForName(tlhlName); + for (Entity location : locations) { + Object locationId = location.getPrimaryKeyValues().get(0); + if (locationId == null) { + LOGGER.error("Location with no ID"); + } + dslContext.insertInto(tlhl) + .set(((TableField) tlhl.field(tlhlHistLocationIdName)), histLocationId) + .set((tlhl.field(ttlLocationIdName)), locationId) + .execute(); + LOGGER.debug(EntityFactories.LINKED_L_TO_HL, locationId, histLocationId); + } + + // Send a message about the creation of a new HL + Entity newHl = pm.get(etHistLoc, PkValue.of(histLocationId)); + ModelRegistry modelRegistry = pm.getCoreSettings().getModelRegistry(); + newHl.setQuery(modelRegistry.getMessageQueryGenerator().getQueryFor(newHl.getEntityType())); + pm.getEntityChangedMessages().add( + new EntityChangedMessage() + .setEventType(EntityChangedMessage.Type.CREATE) + .setEntity(newHl)); + } + } + + public void setTtlName(String ttlName) { + this.ttlName = ttlName; + } + + public void setTtlThingIdName(String ttlThingIdName) { + this.ttlThingIdName = ttlThingIdName; + } + + public void setTtlLocationIdName(String ttlLocationIdName) { + this.ttlLocationIdName = ttlLocationIdName; + } + + public void setTlhlName(String tlhlName) { + this.tlhlName = tlhlName; + } + + public void setTlhlHistLocationIdName(String tlhlHistLocationIdName) { + this.tlhlHistLocationIdName = tlhlHistLocationIdName; + } + + public void setThlTimeName(String thlTimeName) { + this.thlTimeName = thlTimeName; + } + +} diff --git a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpHistLocations.java b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpHistLocations.java index d50796dfc..09a1b00e7 100644 --- a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpHistLocations.java +++ b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpHistLocations.java @@ -18,8 +18,6 @@ package de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel; import de.fraunhofer.iosb.ilt.frostserver.model.EntityType; -import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity; -import de.fraunhofer.iosb.ilt.frostserver.model.ext.TimeInstant; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.JooqPersistenceManager; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.bindings.MomentBinding; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.factories.EntityFactories; @@ -29,15 +27,10 @@ import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.TableCollection; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.PropertyFieldRegistry; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.validator.SecurityTableWrapper; -import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode; -import de.fraunhofer.iosb.ilt.frostserver.util.exception.IncompleteEntityException; -import de.fraunhofer.iosb.ilt.frostserver.util.exception.NoSuchEntityException; import de.fraunhofer.iosb.ilt.frostserver.util.user.PrincipalExtended; import java.util.Arrays; -import java.util.Collections; import java.util.List; import net.time4j.Moment; -import org.jooq.DSLContext; import org.jooq.DataType; import org.jooq.Field; import org.jooq.Name; @@ -46,8 +39,6 @@ import org.jooq.TableField; import org.jooq.impl.DSL; import org.jooq.impl.SQLDataType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class TableImpHistLocations extends StaTableAbstract { @@ -56,7 +47,6 @@ public class TableImpHistLocations extends StaTableAbstract(pluginCoreModel.epTime, table -> table.time)); pfReg.addEntry(pluginCoreModel.npThingHistLoc, TableImpHistLocations::getThingId); pfReg.addEntry(pluginCoreModel.npLocationsHistLoc, TableImpHistLocations::getId); - } - - @Override - public boolean insertIntoDatabase(JooqPersistenceManager pm, Entity histLoc, UpdateMode updateMode) throws NoSuchEntityException, IncompleteEntityException { - super.insertIntoDatabase(pm, histLoc, updateMode); - EntityFactories entityFactories = pm.getEntityFactories(); - Entity thing = histLoc.getProperty(pluginCoreModel.npThingHistLoc); - Object thingId = thing.getPrimaryKeyValues().get(0); - DSLContext dslContext = pm.getDslContext(); - TableImpHistLocations thl = getTables().getTableForClass(TableImpHistLocations.class); - - final TimeInstant hlTime = histLoc.getProperty(pluginCoreModel.epTime); - Moment newTime = hlTime.getDateTime(); - // https://github.com/opengeospatial/sensorthings/issues/30 - // Check the time of the latest HistoricalLocation of our thing. - // If this time is earlier than our time, set the Locations of our Thing to our Locations. - Record lastHistLocation = dslContext.select(Collections.emptyList()) - .from(thl) - .where( - ((TableField) thl.getThingId()).eq(thingId) - .and(thl.time.gt(newTime))) - .orderBy(thl.time.desc()) - .limit(1) - .fetchOne(); - if (lastHistLocation == null) { - // We are the newest. - // Unlink old Locations from Thing. - TableImpThingsLocations qtl = getTables().getTableForClass(TableImpThingsLocations.class); - long count = dslContext - .delete(qtl) - .where(((TableField) qtl.getThingId()).eq(thingId)) - .execute(); - LOGGER.debug(EntityFactories.UNLINKED_L_FROM_T, count, thingId); - - // Link new locations to Thing. - for (Entity l : histLoc.getProperty(pluginCoreModel.npLocationsHistLoc)) { - if (!l.getPrimaryKeyValues().isFullySet() || !entityFactories.entityExists(pm, l, true)) { - throw new NoSuchEntityException("Location with no id."); - } - Object locationId = l.getPrimaryKeyValues().get(0); - - dslContext.insertInto(qtl) - .set(((TableField) qtl.getThingId()), thingId) - .set((qtl.getLocationId()), locationId) - .execute(); - LOGGER.debug(EntityFactories.LINKED_L_TO_T, locationId, thingId); - } - } - - return true; + registerHookPostInsert(0, new HookPostInsertHistLoc()); } @Override diff --git a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpLocations.java b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpLocations.java index 0e00e249e..20852fcc3 100644 --- a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpLocations.java +++ b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpLocations.java @@ -17,12 +17,9 @@ */ package de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel; -import de.fraunhofer.iosb.ilt.frostserver.model.EntityChangedMessage; import de.fraunhofer.iosb.ilt.frostserver.model.EntityType; import de.fraunhofer.iosb.ilt.frostserver.model.ModelRegistry; import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity; -import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySet; -import de.fraunhofer.iosb.ilt.frostserver.model.core.PkValue; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.JooqPersistenceManager; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.bindings.JsonBinding; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.bindings.JsonValue; @@ -36,15 +33,10 @@ import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.PropertyFieldRegistry.NFP; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.Utils; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.validator.SecurityTableWrapper; -import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode; -import de.fraunhofer.iosb.ilt.frostserver.util.exception.IncompleteEntityException; -import de.fraunhofer.iosb.ilt.frostserver.util.exception.NoSuchEntityException; import de.fraunhofer.iosb.ilt.frostserver.util.user.PrincipalExtended; import java.util.Arrays; import java.util.List; -import net.time4j.Moment; import org.geolatte.geom.Geometry; -import org.jooq.DSLContext; import org.jooq.DataType; import org.jooq.Field; import org.jooq.Name; @@ -54,8 +46,6 @@ import org.jooq.impl.DSL; import org.jooq.impl.DefaultDataType; import org.jooq.impl.SQLDataType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class TableImpLocations extends StaTableAbstract { @@ -69,7 +59,6 @@ public class TableImpLocations extends StaTableAbstract { public static final String NAME_COL_NAME = "NAME"; public static final String NAME_COL_PROPERTIES = "PROPERTIES"; - private static final Logger LOGGER = LoggerFactory.getLogger(TableImpLocations.class.getName()); private static final long serialVersionUID = -806078255; /** @@ -188,89 +177,12 @@ public void initProperties(final EntityFactories entityFactories) { pfReg.addEntryMap(ModelRegistry.EP_PROPERTIES, table -> table.colProperties); pfReg.addEntry(pluginCoreModel.npThingsLocation, TableImpLocations::getId); pfReg.addEntry(pluginCoreModel.npHistoricalLocationsLocation, TableImpLocations::getId); - } - - @Override - protected void updateNavigationPropertySet(Entity location, EntitySet linkedSet, JooqPersistenceManager pm, UpdateMode updateMode) throws IncompleteEntityException, NoSuchEntityException { - EntityType linkedEntityType = linkedSet.getEntityType(); - ModelRegistry modelRegistry = getModelRegistry(); - if (linkedEntityType.equals(pluginCoreModel.etThing)) { - Object locationId = location.getPrimaryKeyValues().get(0); - DSLContext dslContext = pm.getDslContext(); - EntityFactories entityFactories = pm.getEntityFactories(); - final TableCollection tables = getTables(); - TableImpThingsLocations ttl = tables.getTableForClass(TableImpThingsLocations.class); - - // Maybe Create new Things and link them to this Location. - boolean admin = PrincipalExtended.getLocalPrincipal().isAdmin(); - for (Entity t : linkedSet) { - if (updateMode.createAndLinkNew) { - entityFactories.entityExistsOrCreate(pm, t, updateMode); - } else if (!entityFactories.entityExists(pm, t, admin)) { - throw new NoSuchEntityException("Thing not found."); - } - - Object thingId = t.getPrimaryKeyValues().get(0); - - // Unlink old Locations from Thing. - long delCount = dslContext.delete(ttl) - .where(((TableField) ttl.getThingId()).eq(thingId)) - .execute(); - LOGGER.debug(EntityFactories.UNLINKED_L_FROM_T, delCount, thingId); - - // Link new Location to thing. - dslContext.insertInto(ttl) - .set((TableField) ttl.getThingId(), thingId) - .set(ttl.getLocationId(), locationId) - .execute(); - LOGGER.debug(EntityFactories.LINKED_L_TO_T, locationId, thingId); - - // Create HistoricalLocation for Thing - TableImpHistLocations qhl = tables.getTableForClass(TableImpHistLocations.class); - Object histLocationId = dslContext.insertInto(qhl) - .set((TableField) qhl.getThingId(), thingId) - .set(qhl.time, Moment.nowInSystemTime()) - .returningResult(qhl.getId()) - .fetchOne(0); - LOGGER.debug(EntityFactories.CREATED_HL, histLocationId); - - // Link Location to HistoricalLocation. - TableImpLocationsHistLocations qlhl = tables.getTableForClass(TableImpLocationsHistLocations.class); - dslContext.insertInto(qlhl) - .set((TableField) qlhl.getHistLocationId(), histLocationId) - .set(qlhl.getLocationId(), locationId) - .execute(); - LOGGER.debug(EntityFactories.LINKED_L_TO_HL, locationId, histLocationId); - - // Send a message about the creation of a new HL - Entity newHl = pm.get(pluginCoreModel.etHistoricalLocation, PkValue.of(histLocationId)); - newHl.setQuery(modelRegistry.getMessageQueryGenerator().getQueryFor(newHl.getEntityType())); - pm.getEntityChangedMessages().add( - new EntityChangedMessage() - .setEventType(EntityChangedMessage.Type.CREATE) - .setEntity(newHl)); - } - return; - } - super.updateNavigationPropertySet(location, linkedSet, pm, updateMode); - } - - @Override - public void delete(JooqPersistenceManager pm, PkValue entityId) throws NoSuchEntityException { - super.delete(pm, entityId); - final TableCollection tables = getTables(); - // Also delete all historicalLocations that no longer reference any location - TableImpHistLocations thl = tables.getTableForClass(TableImpHistLocations.class); - TableImpLocationsHistLocations tlhl = tables.getTableForClass(TableImpLocationsHistLocations.class); - int count = pm.getDslContext() - .delete(thl) - .where(((TableField) thl.getId()).in( - DSL.select(thl.getId()) - .from(thl) - .leftJoin(tlhl).on(((TableField) thl.getId()).eq(tlhl.getHistLocationId())) - .where(tlhl.getLocationId().isNull()))) - .execute(); - LOGGER.debug("Deleted {} HistoricalLocations", count); + registerHookPostDelete(0, new HookPostDeleteLocation()); + HookPrePostInsertUpdateLocation hook = new HookPrePostInsertUpdateLocation(); + registerHookPreInsert(0, hook); + registerHookPostInsert(0, hook); + registerHookPreUpdate(0, hook); + registerHookPostUpdate(0, hook); } diff --git a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpThings.java b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpThings.java index 026fe6c3d..db56b9c42 100644 --- a/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpThings.java +++ b/Plugins/CoreModel/src/main/java/de/fraunhofer/iosb/ilt/frostserver/plugin/coremodel/TableImpThings.java @@ -17,12 +17,8 @@ */ package de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel; -import de.fraunhofer.iosb.ilt.frostserver.model.EntityChangedMessage; import de.fraunhofer.iosb.ilt.frostserver.model.EntityType; import de.fraunhofer.iosb.ilt.frostserver.model.ModelRegistry; -import de.fraunhofer.iosb.ilt.frostserver.model.core.Entity; -import de.fraunhofer.iosb.ilt.frostserver.model.core.EntitySet; -import de.fraunhofer.iosb.ilt.frostserver.model.core.PkValue; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.JooqPersistenceManager; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.bindings.JsonBinding; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.bindings.JsonValue; @@ -32,15 +28,9 @@ import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.StaTableAbstract; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.tables.TableCollection; import de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.validator.SecurityTableWrapper; -import de.fraunhofer.iosb.ilt.frostserver.service.UpdateMode; -import de.fraunhofer.iosb.ilt.frostserver.util.exception.IncompleteEntityException; -import de.fraunhofer.iosb.ilt.frostserver.util.exception.NoSuchEntityException; import de.fraunhofer.iosb.ilt.frostserver.util.user.PrincipalExtended; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import net.time4j.Moment; -import org.jooq.DSLContext; import org.jooq.DataType; import org.jooq.Field; import org.jooq.Name; @@ -136,76 +126,11 @@ public void initProperties(final EntityFactories entityFactories) { pfReg.addEntry(pluginCoreModel.npDatastreamsThing, TableImpThings::getId); pfReg.addEntry(pluginCoreModel.npHistoricalLocationsThing, TableImpThings::getId); pfReg.addEntry(pluginCoreModel.npLocationsThing, TableImpThings::getId); - } - - @Override - protected void updateNavigationPropertySet(Entity thing, EntitySet linkedSet, JooqPersistenceManager pm, UpdateMode updateMode) throws IncompleteEntityException, NoSuchEntityException { - final ModelRegistry modelRegistry = getModelRegistry(); - EntityType linkedEntityType = linkedSet.getEntityType(); - if (linkedEntityType.equals(pluginCoreModel.etLocation)) { - final TableCollection tables = getTables(); - // We know a Thing has a single-valued PK. - Object thingId = thing.getPrimaryKeyValues().get(0); - DSLContext dslContext = pm.getDslContext(); - EntityFactories entityFactories = pm.getEntityFactories(); - TableImpThingsLocations ttl = tables.getTableForClass(TableImpThingsLocations.class); - - // Unlink old Locations from Thing. - long count = dslContext.delete(ttl).where(((TableField) ttl.getThingId()).eq(thingId)).execute(); - LOGGER.debug(EntityFactories.UNLINKED_L_FROM_T, count, thingId); - - // Maybe Create new Locations and link them to this Thing. - List locationIds = new ArrayList<>(); - boolean admin = PrincipalExtended.getLocalPrincipal().isAdmin(); - for (Entity l : linkedSet) { - if (updateMode.createAndLinkNew) { - entityFactories.entityExistsOrCreate(pm, l, updateMode); - } else if (!entityFactories.entityExists(pm, l, admin)) { - throw new NoSuchEntityException("Linked Location with no id."); - } - PkValue lPk = l.getPrimaryKeyValues(); - Object lId = lPk.get(0); - - dslContext.insertInto(ttl) - .set((TableField) ttl.getThingId(), thingId) - .set(ttl.getLocationId(), lId) - .execute(); - LOGGER.debug(EntityFactories.LINKED_L_TO_T, lId, thingId); - locationIds.add(lId); - } - - // Now link the new locations also to a historicalLocation. - if (!locationIds.isEmpty()) { - // Insert a new HL into the DB - TableImpHistLocations qhl = tables.getTableForClass(TableImpHistLocations.class); - Object histLocationId = dslContext.insertInto(qhl) - .set((TableField) qhl.getThingId(), thingId) - .set(qhl.time, Moment.nowInSystemTime()) - .returningResult(qhl.getId()) - .fetchOne(0); - LOGGER.debug(EntityFactories.CREATED_HL, histLocationId); - - // Link the locations to the new HL - TableImpLocationsHistLocations qlhl = tables.getTableForClass(TableImpLocationsHistLocations.class); - for (Object locId : locationIds) { - dslContext.insertInto(qlhl) - .set(((TableField) qlhl.getHistLocationId()), histLocationId) - .set((qlhl.getLocationId()), locId) - .execute(); - LOGGER.debug(EntityFactories.LINKED_L_TO_HL, locId, histLocationId); - } - - // Send a message about the creation of a new HL - Entity newHl = pm.get(pluginCoreModel.etHistoricalLocation, PkValue.of(histLocationId)); - newHl.setQuery(modelRegistry.getMessageQueryGenerator().getQueryFor(newHl.getEntityType())); - pm.getEntityChangedMessages().add( - new EntityChangedMessage() - .setEventType(EntityChangedMessage.Type.CREATE) - .setEntity(newHl)); - } - return; - } - super.updateNavigationPropertySet(thing, linkedSet, pm, updateMode); + HookPrePostInsertUpdateThing hook = new HookPrePostInsertUpdateThing(); + registerHookPreInsert(0, hook); + registerHookPostInsert(0, hook); + registerHookPreUpdate(0, hook); + registerHookPostUpdate(0, hook); } @Override diff --git a/Plugins/CoreModelV2/src/main/resources/plugincoremodelv2/model/HistoricalLocation.json b/Plugins/CoreModelV2/src/main/resources/plugincoremodelv2/model/HistoricalLocation.json index 5d6b2878a..3ff6636ca 100644 --- a/Plugins/CoreModelV2/src/main/resources/plugincoremodelv2/model/HistoricalLocation.json +++ b/Plugins/CoreModelV2/src/main/resources/plugincoremodelv2/model/HistoricalLocation.json @@ -1,69 +1,76 @@ { - "conformance": [], - "simplePropertyTypes": [], - "entityTypes": [ - { - "name": "HistoricalLocation", - "plural": "HistoricalLocations", - "adminOnly": false, - "table": "hist_locations", - "orderByDflt": [], - "entityProperties": [ + "conformance": [], + "simplePropertyTypes": [], + "entityTypes": [ { - "name": "id", - "aliases": [ - "@iot.id" - ], - "type": "Id", - "handlers": [ - { - "@class": "de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.fieldmapper.FieldMapperId", - "field": "id" - } - ], - "annotations": [] - }, - { - "name": "time", - "type": "Edm.DateTimeOffset", - "required": true, - "nullable": false, - "handlers": [ - { - "@class": "de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.fieldmapper.FieldMapperTimeInstant", - "field": "time" - } - ], - "annotations": [] - } - ], - "navigationProperties": [ - { - "name": "Thing", - "entitySet": false, - "entityType": "Thing", - "required": true, - "symmetrical": false, - "priority": 0, - "inverse": { - "name": "HistoricalLocations", - "entitySet": true, - "required": false, - "priority": 0, + "name": "HistoricalLocation", + "plural": "HistoricalLocations", + "adminOnly": false, + "table": "hist_locations", + "orderByDflt": [], + "entityProperties": [ + { + "name": "id", + "aliases": [ + "@iot.id" + ], + "type": "Id", + "handlers": [ + { + "@class": "de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.fieldmapper.FieldMapperId", + "field": "id" + } + ], + "annotations": [] + }, + { + "name": "time", + "type": "Edm.DateTimeOffset", + "required": true, + "nullable": false, + "handlers": [ + { + "@class": "de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.fieldmapper.FieldMapperTimeInstant", + "field": "time" + } + ], + "annotations": [] + } + ], + "navigationProperties": [ + { + "name": "Thing", + "entitySet": false, + "entityType": "Thing", + "required": true, + "symmetrical": false, + "priority": 0, + "inverse": { + "name": "HistoricalLocations", + "entitySet": true, + "required": false, + "priority": 0, + "annotations": [] + }, + "handlers": [ + { + "@class": "de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.fieldmapper.FieldMapperOneToMany", + "field": "thing_id", + "otherTable": "things", + "otherField": "id" + } + ], + "annotations": [] + } + ], + "hooks": [ + { + "hook": { + "@class": "de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel.HookPostInsertHistLoc" + } + } + ], "annotations": [] - }, - "handlers": [ - { - "@class": "de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.utils.fieldmapper.FieldMapperOneToMany", - "field": "thing_id", - "otherTable": "things", - "otherField": "id" - } - ], - "annotations": [] } - ], - "annotations": [] - } - ] + ] } \ No newline at end of file diff --git a/Plugins/CoreModelV2/src/main/resources/plugincoremodelv2/model/Location.json b/Plugins/CoreModelV2/src/main/resources/plugincoremodelv2/model/Location.json index 81bc02d2f..add04ba6b 100644 --- a/Plugins/CoreModelV2/src/main/resources/plugincoremodelv2/model/Location.json +++ b/Plugins/CoreModelV2/src/main/resources/plugincoremodelv2/model/Location.json @@ -113,6 +113,13 @@ "annotations": [] } ], + "hooks": [ + { + "hook": { + "@class": "de.fraunhofer.iosb.ilt.frostserver.plugin.coremodel.HookPostDeleteLocation" + } + } + ], "annotations": [] } ] diff --git a/Tools/ModelEditor/pom.xml b/Tools/ModelEditor/pom.xml index 96e326e12..9ca5248d6 100644 --- a/Tools/ModelEditor/pom.xml +++ b/Tools/ModelEditor/pom.xml @@ -29,6 +29,11 @@ FROST-Server.Core.Model ${project.version} + + ${project.groupId} + FROST-Server.Plugin.CoreModel + ${project.version} + ${project.groupId} FROST-Server.SQLjooq