1717 */
1818package de .fraunhofer .iosb .ilt .frostserver .plugin .projects ;
1919
20+ import static de .fraunhofer .iosb .ilt .frostserver .persistence .pgjooq .utils .Utils .getFieldOrNull ;
2021import static de .fraunhofer .iosb .ilt .frostserver .service .InitResult .INIT_DELAY ;
2122
23+ import de .fraunhofer .iosb .ilt .frostserver .model .EntityType ;
24+ import de .fraunhofer .iosb .ilt .frostserver .model .ModelRegistry ;
25+ import de .fraunhofer .iosb .ilt .frostserver .model .core .Entity ;
26+ import de .fraunhofer .iosb .ilt .frostserver .model .core .PkValue ;
27+ import de .fraunhofer .iosb .ilt .frostserver .persistence .PersistenceManager ;
28+ import de .fraunhofer .iosb .ilt .frostserver .persistence .pgjooq .JooqPersistenceManager ;
29+ import de .fraunhofer .iosb .ilt .frostserver .persistence .pgjooq .tables .StaMainTable ;
30+ import de .fraunhofer .iosb .ilt .frostserver .persistence .pgjooq .tables .StaTable ;
31+ import de .fraunhofer .iosb .ilt .frostserver .persistence .pgjooq .tables .TableCollection ;
2232import de .fraunhofer .iosb .ilt .frostserver .plugin .actuation .PluginActuation ;
2333import de .fraunhofer .iosb .ilt .frostserver .plugin .coremodel .PluginCoreModel ;
34+ import de .fraunhofer .iosb .ilt .frostserver .plugin .coremodel .TableImpFeatures ;
35+ import de .fraunhofer .iosb .ilt .frostserver .plugin .coremodel .TableImpLocations ;
2436import de .fraunhofer .iosb .ilt .frostserver .plugin .modelloader .PluginModelLoader ;
2537import de .fraunhofer .iosb .ilt .frostserver .plugin .multidatastream .PluginMultiDatastream ;
2638import de .fraunhofer .iosb .ilt .frostserver .service .InitResult ;
27- import de .fraunhofer .iosb .ilt .frostserver .service .Plugin ;
2839import de .fraunhofer .iosb .ilt .frostserver .service .PluginManager ;
40+ import de .fraunhofer .iosb .ilt .frostserver .service .PluginModel ;
41+ import de .fraunhofer .iosb .ilt .frostserver .service .UpdateMode ;
2942import de .fraunhofer .iosb .ilt .frostserver .settings .ConfigDefaults ;
3043import de .fraunhofer .iosb .ilt .frostserver .settings .CoreSettings ;
3144import de .fraunhofer .iosb .ilt .frostserver .settings .Settings ;
3245import de .fraunhofer .iosb .ilt .frostserver .settings .annotation .DefaultValueBoolean ;
46+ import org .jooq .Field ;
47+ import org .jooq .Record1 ;
48+ import org .jooq .Record2 ;
49+ import org .jooq .Result ;
50+ import org .jooq .TableField ;
3351import org .slf4j .Logger ;
3452import org .slf4j .LoggerFactory ;
3553
3654/**
3755 * Plugin loader for the Projects plugin.
3856 */
39- public class PluginProjects implements Plugin , ConfigDefaults {
57+ public class PluginProjects implements PluginModel , ConfigDefaults {
4058
4159 private static final Logger LOGGER = LoggerFactory .getLogger (PluginProjects .class .getName ());
4260
@@ -46,10 +64,18 @@ public class PluginProjects implements Plugin, ConfigDefaults {
4664 @ DefaultValueBoolean (true )
4765 public static final String TAG_DEFAULT_RULES = "projects.enableDefaultRules" ;
4866
67+ @ DefaultValueBoolean (false )
68+ public static final String TAG_UPDATE_FEATURE_WITH_LOCATION = "projects.updateFeatureWithLocation" ;
69+
70+ private CoreSettings coreSettings ;
71+
4972 private boolean enabled ;
73+ private boolean autoUpdateFeatures ;
74+ private boolean fullyInitialised ;
5075
5176 @ Override
5277 public InitResult init (CoreSettings coreSettings ) {
78+ this .coreSettings = coreSettings ;
5379 Settings pluginSettings = coreSettings .getPluginSettings ();
5480 enabled = pluginSettings .getBoolean (TAG_ENABLE_PROJECTS , PluginProjects .class );
5581 if (enabled ) {
@@ -116,6 +142,8 @@ public InitResult init(CoreSettings coreSettings) {
116142 pml .addSecurityFile ("pluginprojects/sta1/security/.json" );
117143 }
118144 }
145+ autoUpdateFeatures = pluginSettings .getBoolean (TAG_UPDATE_FEATURE_WITH_LOCATION , PluginProjects .class );
146+
119147 pluginManager .registerPlugin (this );
120148 }
121149 return InitResult .INIT_OK ;
@@ -126,4 +154,109 @@ public boolean isEnabled() {
126154 return enabled ;
127155 }
128156
157+ @ Override
158+ public void registerEntityTypes () {
159+ // Nothing to do here.
160+ }
161+
162+ @ Override
163+ public boolean linkEntityTypes (PersistenceManager pm ) {
164+ if (autoUpdateFeatures ) {
165+ final PluginCoreModel pluginCoreModel = coreSettings .getPluginManager ().getPlugin (PluginCoreModel .class );
166+ if (pluginCoreModel == null || !pluginCoreModel .isFullyInitialised ()) {
167+ return false ;
168+ }
169+ if (pm instanceof JooqPersistenceManager jpm ) {
170+ StaMainTable <?> tableLocations = jpm .getTableCollection ().getTableForType (pluginCoreModel .etLocation );
171+ tableLocations .registerHookPostUpdate (
172+ 11.1 ,
173+ (JooqPersistenceManager jpml , Entity entity , PkValue entityId , UpdateMode updateMode ) -> relinkProjectsToFeature (jpml , entity ));
174+ }
175+ }
176+ fullyInitialised = true ;
177+ return true ;
178+ }
179+
180+ public static void relinkProjectsToFeature (JooqPersistenceManager jpm , Entity entity ) {
181+ Object genFoiId = null ;
182+ try {
183+ final TableCollection tableCollection = jpm .getTableCollection ();
184+ final ModelRegistry mr = jpm .getCoreSettings ().getModelRegistry ();
185+
186+ EntityType etProject = mr .getEntityTypeForName ("Project" , true );
187+ if (etProject == null ) {
188+ LOGGER .error ("No Project entity type found!" );
189+ return ;
190+ }
191+ TableImpLocations ql = tableCollection .getTableForClass (TableImpLocations .class );
192+ Field <?> lRestricted = ql .field ("RESTRICTED" );
193+ final Object locationId = entity .getPrimaryKeyValues ().get (0 );
194+ Record2 <?, ?> fetchAny = jpm .getDslContext ()
195+ .select (ql .colGenFoiId , lRestricted )
196+ .from (ql )
197+ .where (((TableField ) ql .getId ()).equal (locationId ))
198+ .fetchAny ();
199+ if (fetchAny == null ) {
200+ LOGGER .error ("Location not found in table for id {}" , entity .getPrimaryKeyValues ());
201+ return ;
202+ }
203+ genFoiId = fetchAny .component1 ();
204+ if (genFoiId == null ) {
205+ // Location has no genFoiID
206+ return ;
207+ }
208+
209+ TableImpFeatures tf = tableCollection .getTableForClass (TableImpFeatures .class );
210+ TableField fRestricted = (TableField ) tf .field ("RESTRICTED" );
211+ int updated = jpm .getDslContext ()
212+ .update (tf )
213+ .set (fRestricted , fetchAny .component2 ())
214+ .where (((TableField ) tf .getId ()).eq (genFoiId ))
215+ .execute ();
216+ if (updated != 1 ) {
217+ LOGGER .warn ("Update of generated FoI resulted in {} changed rows!" , updated );
218+ }
219+
220+ StaTable tfp = tableCollection .getTableForName ("FEATURE_PROJECTS" );
221+ TableField tfpPid = (TableField ) tfp .field ("PROJECT_ID" );
222+ TableField tfpFid = (TableField ) tfp .field ("FEATURE_ID" );
223+ StaTable tlp = tableCollection .getTableForName ("LOCATION_PROJECTS" );
224+ TableField tlpPid = (TableField ) tlp .field ("PROJECT_ID" );
225+ TableField tlpLid = (TableField ) tlp .field ("LOCATION_ID" );
226+ if (tfpPid == null || tfpFid == null || tlpPid == null || tlpLid == null ) {
227+ LOGGER .error ("Failed to link Projects to generated FoI, linktables do not have correct columns." );
228+ return ;
229+ }
230+ int unlinked = jpm .getDslContext ()
231+ .deleteFrom (tfp )
232+ .where (tfpFid .eq (genFoiId ))
233+ .execute ();
234+ LOGGER .debug ("Unlinked {} projects from Feature {}" , unlinked , genFoiId );
235+ Result <Record1 <Object >> projectIds = jpm .getDslContext ()
236+ .select (tlpPid )
237+ .from (tlp )
238+ .where (tlpLid .eq (locationId ))
239+ .fetch ();
240+ int linked = 0 ;
241+ for (org .jooq .Record pidTuple : projectIds ) {
242+ Object projectId = getFieldOrNull (pidTuple , tlpPid );
243+ jpm .getDslContext ()
244+ .insertInto (tfp )
245+ .columns (tfpFid , tfpPid )
246+ .values (genFoiId , projectId )
247+ .execute ();
248+ linked ++;
249+ }
250+ LOGGER .debug ("Linked {} projects from Feature {}" , linked , genFoiId );
251+
252+ } catch (RuntimeException ex ) {
253+ LOGGER .error ("Failed to update Projects for generated FoI {} from Location {}." , genFoiId , entity , ex );
254+ }
255+ }
256+
257+ @ Override
258+ public boolean isFullyInitialised () {
259+ return fullyInitialised ;
260+ }
261+
129262}
0 commit comments