From a1ec9f93f9b5fe07e4c5aa0d3ade058722fccfd8 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Thu, 30 Apr 2026 12:08:43 +0200 Subject: [PATCH 01/15] Add audit to FeatureSchema --- .../de/ii/xtraplatform/features/domain/FeatureSchema.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java index eb28bab64..567887b7e 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java @@ -73,6 +73,8 @@ public interface FeatureSchema String CONCAT_ELEMENT = "_CONCAT_ELEMENT_"; String COALESCE_ELEMENT = "_COALESCE_ELEMENT_"; + Optional getAudit(); + @JsonIgnore @Override String getName(); @@ -1146,8 +1148,7 @@ default FeatureSchema accept(FeatureSchemaTransformer visitor, List new SimpleEntry<>( - entry.getKey(), - (FeatureSchema) visit.apply(entry.getValue()))) + entry.getKey(), visit.apply(entry.getValue()))) .collect( ImmutableMap.toImmutableMap( Map.Entry::getKey, Map.Entry::getValue))) From d9e266a382dcb90eaeec0b6fb0c4d208d6466dca Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Wed, 6 May 2026 18:34:25 +0200 Subject: [PATCH 02/15] feature: basic audit logging --- .../features/domain/FeatureStream.java | 1 + .../features/domain/FeatureStreamImpl.java | 15 +++- .../domain/FeatureTokenTransformerAudit.java | 84 +++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStream.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStream.java index bdaf88659..642a5aca4 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStream.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStream.java @@ -37,6 +37,7 @@ enum PipelineSteps { CLEAN, ETAG, METADATA, + AUDIT, ALL } diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index 65400a1a9..c36025a7f 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -50,6 +50,7 @@ public class FeatureStreamImpl implements FeatureStream { private final boolean stepClean; private final boolean stepEtag; private final boolean stepMetadata; + private final boolean stepAudit; public FeatureStreamImpl( Query query, @@ -87,6 +88,9 @@ public FeatureStreamImpl( this.stepMetadata = !query.skipPipelineSteps().contains(PipelineSteps.METADATA) && !query.skipPipelineSteps().contains(PipelineSteps.ALL); + this.stepAudit = + !query.skipPipelineSteps().contains(PipelineSteps.AUDIT) + && !query.skipPipelineSteps().contains(PipelineSteps.ALL); } @Override @@ -126,6 +130,10 @@ public CompletionStage runWith( source = source.via(new FeatureTokenTransformerMetadata(resultBuilder)); } + if (stepAudit) { + source = source.via(new FeatureTokenTransformerAudit(resultBuilder)); + } + source = source.via(new FeatureTokenTransformerHooks(resultBuilder, onCollectionMetadata)); @@ -142,7 +150,7 @@ public CompletionStage runWith( if (strongETag && x instanceof byte[]) { eTag.put((byte[]) x); } - return builder.isEmpty(x instanceof byte[] ? ((byte[]) x).length <= 0 : false); + return builder.isEmpty(x instanceof byte[] && ((byte[]) x).length <= 0); }) .handleEnd( (ImmutableResult.Builder builder1) -> { @@ -171,7 +179,7 @@ public CompletionStage> runWith( doTransform ? getFeatureTokenSourceTransformed(tokenSource, mergedTransformations) : tokenSource; - ImmutableResultReduced.Builder resultBuilder = ImmutableResultReduced.builder(); + ImmutableResultReduced.Builder resultBuilder = ImmutableResultReduced.builder(); final ETag.Incremental eTag = ETag.incremental(); final boolean strongETag = query instanceof FeatureQuery @@ -191,6 +199,9 @@ public CompletionStage> runWith( if (stepMetadata) { source = source.via(new FeatureTokenTransformerMetadata(resultBuilder)); } + if (stepAudit) { + source = source.via(new FeatureTokenTransformerAudit(resultBuilder)); + } source = source.via(new FeatureTokenTransformerHooks(resultBuilder, onCollectionMetadata)); diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java new file mode 100644 index 000000000..434fc718a --- /dev/null +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -0,0 +1,84 @@ +/* + * Copyright 2022 interactive instruments GmbH + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package de.ii.xtraplatform.features.domain; + +import de.ii.xtraplatform.crs.domain.BoundingBox; +import java.time.Instant; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { + private final Consumer lastModifiedSetter; + private final Consumer spatialExtentSetter; + private final Consumer> temporalExtentSetter; + + private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); + + public FeatureTokenTransformerAudit(ImmutableResult.Builder resultBuilder) { + this.lastModifiedSetter = resultBuilder::lastModified; + this.spatialExtentSetter = resultBuilder::spatialExtent; + this.temporalExtentSetter = resultBuilder::temporalExtent; + } + + public FeatureTokenTransformerAudit(ImmutableResultReduced.Builder resultBuilder) { + this.lastModifiedSetter = resultBuilder::lastModified; + this.spatialExtentSetter = resultBuilder::spatialExtent; + this.temporalExtentSetter = resultBuilder::temporalExtent; + } + + private final Map>> toAudit = new LinkedHashMap<>(); + + @Override + public void onStart(ModifiableContext context) { + for (String type : context.mappings().keySet()) { + Map> auditProps = + toAudit.computeIfAbsent(type, t -> new LinkedHashMap<>()); + + for (FeatureSchema prop : context.mappings().get(type).getTargetSchema().getProperties()) { + if (prop.getAudit().isPresent()) { + auditProps.computeIfAbsent(prop.getName(), p -> new LinkedHashSet<>()); + } + } + } + + super.onStart(context); + } + + @Override + public void onValue(ModifiableContext context) { + String type = context.type(); + String property = context.pathTracker().toString(); + Map> props = toAudit.get(type); + if (props != null) { + Set valueSet = props.get(property); + if (valueSet != null) { + valueSet.add(context.value()); + } + } + super.onValue(context); + } + + @Override + public void onEnd(ModifiableContext context) { + toAudit.forEach( + (type, properties) -> + properties.forEach( + (property, values) -> { + if (!values.isEmpty()) { + LOGGER.info( + "Type '{}', property '{}', accessed values {}", type, property, values); + } + })); + super.onEnd(context); + } +} From 1368091f3d4411323e3aabfe54480a466c92d97b Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Tue, 12 May 2026 10:42:03 +0200 Subject: [PATCH 03/15] extract audit code --- .../domain/FeatureTokenTransformerAudit.java | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index 434fc718a..1e60c0475 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -7,34 +7,20 @@ */ package de.ii.xtraplatform.features.domain; -import de.ii.xtraplatform.crs.domain.BoundingBox; -import java.time.Instant; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; -import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { - private final Consumer lastModifiedSetter; - private final Consumer spatialExtentSetter; - private final Consumer> temporalExtentSetter; private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); - public FeatureTokenTransformerAudit(ImmutableResult.Builder resultBuilder) { - this.lastModifiedSetter = resultBuilder::lastModified; - this.spatialExtentSetter = resultBuilder::spatialExtent; - this.temporalExtentSetter = resultBuilder::temporalExtent; - } + public FeatureTokenTransformerAudit(ImmutableResult.Builder resultBuilder) {} - public FeatureTokenTransformerAudit(ImmutableResultReduced.Builder resultBuilder) { - this.lastModifiedSetter = resultBuilder::lastModified; - this.spatialExtentSetter = resultBuilder::spatialExtent; - this.temporalExtentSetter = resultBuilder::temporalExtent; - } + public FeatureTokenTransformerAudit(ImmutableResultReduced.Builder resultBuilder) {} private final Map>> toAudit = new LinkedHashMap<>(); @@ -54,8 +40,7 @@ public void onStart(ModifiableContext context) { super.onStart(context); } - @Override - public void onValue(ModifiableContext context) { + private void audit(ModifiableContext context) { String type = context.type(); String property = context.pathTracker().toString(); Map> props = toAudit.get(type); @@ -65,6 +50,11 @@ public void onValue(ModifiableContext context) { valueSet.add(context.value()); } } + } + + @Override + public void onValue(ModifiableContext context) { + audit(context); super.onValue(context); } From e310c0cb49cb6909e9d8900ca67c3da4c2f7527e Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Fri, 15 May 2026 16:36:22 +0200 Subject: [PATCH 04/15] inject AuditLogger --- gradle/layers.versions.toml | 2 +- .../features/gml/app/FeatureProviderWfs.java | 6 +- .../graphql/app/FeatureProviderGraphQl.java | 6 +- .../oracle/app/FeatureProviderOracle.java | 3 + .../sql/domain/FeatureProviderSql.java | 16 +++-- xtraplatform-features/build.gradle | 1 + .../domain/AbstractFeatureProvider.java | 8 ++- .../features/domain/FeatureStreamImpl.java | 26 ++++++- .../domain/FeatureTokenTransformerAudit.java | 71 +++++++------------ 9 files changed, 79 insertions(+), 60 deletions(-) diff --git a/gradle/layers.versions.toml b/gradle/layers.versions.toml index c4d40b332..66c9a3e80 100644 --- a/gradle/layers.versions.toml +++ b/gradle/layers.versions.toml @@ -1,4 +1,4 @@ [versions] -xtraplatform-core = '7.0.0-SNAPSHOT' +xtraplatform-core = '7.0.0-ldp-95-audit-logging-SNAPSHOT' xtraplatform-native = '2.6.0-SNAPSHOT' diff --git a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java index 4620e2d8f..b54348f0e 100644 --- a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java +++ b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java @@ -10,6 +10,7 @@ import com.google.common.collect.ImmutableList; import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; +import de.ii.xtraplatform.base.domain.AuditLogger; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.cql.domain.Cql; @@ -142,6 +143,7 @@ public FeatureProviderWfs( Reactive reactive, ValueStore valueStore, ProviderExtensionRegistry extensionRegistry, + AuditLogger auditLogger, VolatileRegistry volatileRegistry, @Assisted FeatureProviderDataV2 data) { super( @@ -151,6 +153,7 @@ public FeatureProviderWfs( crsInfo, extensionRegistry, valueStore.forType(Codelist.class), + auditLogger, data, volatileRegistry); @@ -376,6 +379,7 @@ public FeatureStream getFeatureStreamPassThrough(FeatureQuery query) { nativeCrsIs3d, getCodelists(), this::runQuery, - false); + false, + auditLogger); } } diff --git a/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java b/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java index 4158afa5f..eac9e60f0 100644 --- a/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java +++ b/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java @@ -9,6 +9,7 @@ import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; +import de.ii.xtraplatform.base.domain.AuditLogger; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.cql.domain.Cql; @@ -197,6 +198,7 @@ public FeatureProviderGraphQl( Reactive reactive, ValueStore valueStore, ProviderExtensionRegistry extensionRegistry, + AuditLogger auditLogger, VolatileRegistry volatileRegistry, @Assisted FeatureProviderDataV2 data) { super( @@ -206,6 +208,7 @@ public FeatureProviderGraphQl( crsInfo, extensionRegistry, valueStore.forType(Codelist.class), + auditLogger, data, volatileRegistry); @@ -271,10 +274,9 @@ protected FeatureQueryEncoder getQueryEncoder() { protected FeatureTokenDecoder< byte[], FeatureSchema, SchemaMapping, ModifiableContext> getDecoder(Query query, Map mappings) { - if (!(query instanceof FeatureQuery)) { + if (!(query instanceof FeatureQuery featureQuery)) { throw new IllegalArgumentException(); } - FeatureQuery featureQuery = (FeatureQuery) query; FeatureSchema featureSchema = getSourceSchemas().get(featureQuery.getType()).get(0); String name = featureSchema.getSourcePath().map(sourcePath -> sourcePath.substring(1)).orElse(null); diff --git a/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java b/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java index 257b525a2..156e7e5fd 100644 --- a/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java +++ b/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java @@ -9,6 +9,7 @@ import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; +import de.ii.xtraplatform.base.domain.AuditLogger; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.cache.domain.Cache; import de.ii.xtraplatform.cql.domain.Cql; @@ -126,6 +127,7 @@ public FeatureProviderOracle( VolatileRegistry volatileRegistry, Cache cache, Scheduler scheduler, + AuditLogger auditLogger, @Assisted FeatureProviderDataV2 data) { super( crsTransformerFactory, @@ -140,6 +142,7 @@ public FeatureProviderOracle( volatileRegistry, cache, scheduler, + auditLogger, data, Map.of()); } diff --git a/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java b/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java index 68600a73a..2646e5353 100644 --- a/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java +++ b/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java @@ -14,6 +14,7 @@ import com.google.common.collect.ImmutableMap; import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; +import de.ii.xtraplatform.base.domain.AuditLogger; import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.cache.domain.Cache; @@ -483,6 +484,7 @@ public FeatureProviderSql( VolatileRegistry volatileRegistry, Cache cache, Scheduler scheduler, + AuditLogger auditLogger, @Assisted FeatureProviderDataV2 data) { this( crsTransformerFactory, @@ -497,6 +499,7 @@ public FeatureProviderSql( volatileRegistry, cache, scheduler, + auditLogger, data, decoderFactories.getConnectorDecoders()); } @@ -514,6 +517,7 @@ protected FeatureProviderSql( VolatileRegistry volatileRegistry, Cache cache, Scheduler scheduler, + AuditLogger auditLogger, FeatureProviderDataV2 data, Map subdecoders) { super( @@ -523,6 +527,7 @@ protected FeatureProviderSql( crsInfo, extensionRegistry, valueStore.forType(Codelist.class), + auditLogger, data, volatileRegistry); @@ -945,11 +950,7 @@ public boolean supportsMutationsInternal() { if (!Objects.equals(getData().getConnectionInfo().getDialect(), SqlDbmsPgis.ID)) { return false; } - if (!getData().getDatasetChanges().isModeCrud()) { - return false; - } - - return true; + return getData().getDatasetChanges().isModeCrud(); } @Override @@ -1335,7 +1336,7 @@ private MutationResult writeFeatures( crsTransformerFactory, getData().getNativeTimeZone(), partial ? Optional.of(FeatureTransactions.PATCH_NULL_VALUE) : Optional.empty())) - .via(Transformer.map(feature -> (FeatureDataSql) feature)); + .via(Transformer.map(feature -> feature)); if (partial) { featureSqlSource = @@ -1449,7 +1450,8 @@ public FeatureStream getFeatureStream(MultiFeatureQuery query) { nativeCrsIs3d, getCodelists(), this::runQuery, - !query.hitsOnly()); + !query.hitsOnly(), + auditLogger); } @Override diff --git a/xtraplatform-features/build.gradle b/xtraplatform-features/build.gradle index 26c542246..7313249dc 100644 --- a/xtraplatform-features/build.gradle +++ b/xtraplatform-features/build.gradle @@ -5,6 +5,7 @@ description = 'Feature providers and transformations.' descriptionDe = 'Feature-Provider und Transformationen.' dependencies { + provided 'de.interactive_instruments:xtraplatform-base' provided 'de.interactive_instruments:xtraplatform-entities' provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java index 076431621..40c1ab000 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java @@ -11,6 +11,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import de.ii.xtraplatform.base.domain.AuditLogger; import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.base.domain.resiliency.DelayedVolatile; import de.ii.xtraplatform.base.domain.resiliency.Volatile2; @@ -85,6 +86,8 @@ public abstract class AbstractFeatureProvider< private boolean datasetChangedForced; private String previousDataset; + protected AuditLogger auditLogger; + protected AbstractFeatureProvider( ConnectorFactory connectorFactory, Reactive reactive, @@ -92,6 +95,7 @@ protected AbstractFeatureProvider( CrsInfo crsInfo, ProviderExtensionRegistry extensionRegistry, Values codelistStore, + AuditLogger auditLogger, FeatureProviderDataV2 data, VolatileRegistry volatileRegistry) { super(data, volatileRegistry); @@ -101,6 +105,7 @@ protected AbstractFeatureProvider( this.crsInfo = crsInfo; this.extensionRegistry = extensionRegistry; this.codelistStore = codelistStore; + this.auditLogger = auditLogger; this.volatileRegistry = volatileRegistry; this.changeHandler = new FeatureChangeHandlerImpl(); this.connector = @@ -520,7 +525,8 @@ public FeatureStream getFeatureStream(FeatureQuery query) { nativeCrsIs3d, getCodelists(), this::runQuery, - !query.hitsOnly()); + !query.hitsOnly(), + auditLogger); } // TODO: more tests diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index c36025a7f..65c9c0caa 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -11,7 +11,9 @@ import static de.ii.xtraplatform.features.domain.transform.PropertyTransformations.WILDCARD; import com.google.common.collect.ImmutableMap; +import de.ii.xtraplatform.base.domain.AuditLogger; import de.ii.xtraplatform.base.domain.ETag; +import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.crs.domain.CrsTransformer; import de.ii.xtraplatform.crs.domain.CrsTransformerFactory; @@ -52,6 +54,8 @@ public class FeatureStreamImpl implements FeatureStream { private final boolean stepMetadata; private final boolean stepAudit; + private final AuditLogger auditLogger; + public FeatureStreamImpl( Query query, FeatureProviderDataV2 data, @@ -59,7 +63,8 @@ public FeatureStreamImpl( boolean nativeCrsIs3d, Map codelists, QueryRunner runner, - boolean doTransform) { + boolean doTransform, + AuditLogger auditLogger) { this.query = query; this.data = data; this.crsTransformerFactory = crsTransformerFactory; @@ -67,6 +72,7 @@ public FeatureStreamImpl( this.codelists = codelists; this.runner = runner; this.doTransform = doTransform; + this.auditLogger = auditLogger; this.stepMappingSchema = !query.skipPipelineSteps().contains(PipelineSteps.MAPPING_SCHEMA) @@ -131,7 +137,14 @@ public CompletionStage runWith( } if (stepAudit) { - source = source.via(new FeatureTokenTransformerAudit(resultBuilder)); + if (!LogContext.has(LogContext.CONTEXT.AUDIT)) { + throw new IllegalStateException( + "Audit logging not possible, no request-uuid provided!"); + } + String requestUuid = LogContext.get(LogContext.CONTEXT.AUDIT); + source = + source.via( + new FeatureTokenTransformerAudit(resultBuilder, requestUuid, auditLogger)); } source = @@ -200,7 +213,14 @@ public CompletionStage> runWith( source = source.via(new FeatureTokenTransformerMetadata(resultBuilder)); } if (stepAudit) { - source = source.via(new FeatureTokenTransformerAudit(resultBuilder)); + if (!LogContext.has(LogContext.CONTEXT.AUDIT)) { + throw new IllegalStateException( + "Audit logging not possible, no request-uuid provided!"); + } + String requestUuid = LogContext.get(LogContext.CONTEXT.AUDIT); + source = + source.via( + new FeatureTokenTransformerAudit(resultBuilder, requestUuid, auditLogger)); } source = source.via(new FeatureTokenTransformerHooks(resultBuilder, onCollectionMetadata)); diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index 1e60c0475..08a330715 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -7,68 +7,49 @@ */ package de.ii.xtraplatform.features.domain; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import de.ii.xtraplatform.base.domain.AuditLogger; public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { - private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); + private final String requestUuid; + private final AuditLogger auditLogger; - public FeatureTokenTransformerAudit(ImmutableResult.Builder resultBuilder) {} - - public FeatureTokenTransformerAudit(ImmutableResultReduced.Builder resultBuilder) {} + public FeatureTokenTransformerAudit( + ImmutableResult.Builder resultBuilder, String requestUuid, AuditLogger auditLogger) { + this.requestUuid = requestUuid; + this.auditLogger = auditLogger; + } - private final Map>> toAudit = new LinkedHashMap<>(); + public FeatureTokenTransformerAudit( + ImmutableResultReduced.Builder resultBuilder, + String requestUuid, + AuditLogger auditLogger) { + this.requestUuid = requestUuid; + this.auditLogger = auditLogger; + } @Override public void onStart(ModifiableContext context) { - for (String type : context.mappings().keySet()) { - Map> auditProps = - toAudit.computeIfAbsent(type, t -> new LinkedHashMap<>()); + // Annahme: Types -> Properties mapping hat immer size==1 + if (context.mappings().size() != 1) + throw new IllegalStateException("Types zu Properties Mapping ist ungleich 1."); + + String type = context.mappings().keySet().stream().findFirst().get(); + auditLogger.initType(requestUuid, type); - for (FeatureSchema prop : context.mappings().get(type).getTargetSchema().getProperties()) { - if (prop.getAudit().isPresent()) { - auditProps.computeIfAbsent(prop.getName(), p -> new LinkedHashSet<>()); - } + for (FeatureSchema prop : context.mappings().get(type).getTargetSchema().getProperties()) { + if (prop.getAudit().isPresent()) { + auditLogger.initPropertyToValueTrack(requestUuid, prop.getName()); } } super.onStart(context); } - private void audit(ModifiableContext context) { - String type = context.type(); - String property = context.pathTracker().toString(); - Map> props = toAudit.get(type); - if (props != null) { - Set valueSet = props.get(property); - if (valueSet != null) { - valueSet.add(context.value()); - } - } - } - @Override public void onValue(ModifiableContext context) { - audit(context); + String property = context.pathTracker().toString(); + auditLogger.appendPropertyValue(requestUuid, property, context.value()); super.onValue(context); } - - @Override - public void onEnd(ModifiableContext context) { - toAudit.forEach( - (type, properties) -> - properties.forEach( - (property, values) -> { - if (!values.isEmpty()) { - LOGGER.info( - "Type '{}', property '{}', accessed values {}", type, property, values); - } - })); - super.onEnd(context); - } } From 4142a500291d7b34899cfa2a40b879c10cd55e78 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Mon, 18 May 2026 10:38:30 +0200 Subject: [PATCH 05/15] apply support for access-logging --- .../features/domain/FeatureSchema.java | 2 +- .../domain/FeatureTokenTransformerAudit.java | 54 +++++++++++++++++-- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java index 567887b7e..9d771a24b 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java @@ -73,7 +73,7 @@ public interface FeatureSchema String CONCAT_ELEMENT = "_CONCAT_ELEMENT_"; String COALESCE_ELEMENT = "_COALESCE_ELEMENT_"; - Optional getAudit(); + Optional getAudit(); @JsonIgnore @Override diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index 08a330715..ac27a9438 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -8,12 +8,17 @@ package de.ii.xtraplatform.features.domain; import de.ii.xtraplatform.base.domain.AuditLogger; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { private final String requestUuid; private final AuditLogger auditLogger; + private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); + public FeatureTokenTransformerAudit( ImmutableResult.Builder resultBuilder, String requestUuid, AuditLogger auditLogger) { this.requestUuid = requestUuid; @@ -30,7 +35,7 @@ public FeatureTokenTransformerAudit( @Override public void onStart(ModifiableContext context) { - // Annahme: Types -> Properties mapping hat immer size==1 + // Annahme: Types -> Properties is always of size==1 if (context.mappings().size() != 1) throw new IllegalStateException("Types zu Properties Mapping ist ungleich 1."); @@ -39,7 +44,19 @@ public void onStart(ModifiableContext context) { for (FeatureSchema prop : context.mappings().get(type).getTargetSchema().getProperties()) { if (prop.getAudit().isPresent()) { - auditLogger.initPropertyToValueTrack(requestUuid, prop.getName()); + String audit = prop.getAudit().get().toLowerCase(); + switch (audit) { + case "access": + auditLogger.initPropertyToAccessTrack(requestUuid, prop.getName()); + continue; + case "value": + auditLogger.initPropertyToValueTrack(requestUuid, prop.getName()); + continue; + case "none": + continue; + default: + LOGGER.error("Wrong value for audit: {}", audit); + } } } @@ -48,8 +65,37 @@ public void onStart(ModifiableContext context) { @Override public void onValue(ModifiableContext context) { - String property = context.pathTracker().toString(); - auditLogger.appendPropertyValue(requestUuid, property, context.value()); + String type = context.type(); + Optional prop = + context.mappings().get(type).getTargetSchema().getProperties().stream() + .filter(p -> p.getFullPathAsString().equals(context.pathTracker().toString())) + .findFirst(); + + if (prop.isPresent()) { + if (prop.get().getAudit().isPresent()) { + String audit = prop.get().getAudit().get().toLowerCase(); + switch (audit) { + case "access": + auditLogger.markAccessed(requestUuid, prop.get().getName()); + break; + case "value": + auditLogger.appendPropertyValue(requestUuid, prop.get().getName(), context.value()); + break; + case "none": + break; + default: + LOGGER.error("Wrong value for audit: {}", audit); + } + } + } else { + LOGGER.error("No property found with path: {}", context.pathTracker().toString()); + } super.onValue(context); } + + @Override + public void onEnd(ModifiableContext context) { + auditLogger.saveToFileAndRemove(requestUuid); + super.onEnd(context); + } } From 9e8338eff17feefcee1fe4e5bf4d5e0118775379 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Tue, 19 May 2026 11:50:24 +0200 Subject: [PATCH 06/15] extract requestId from ApiRequestContext instead of LogContext --- .../features/domain/FeatureStream.java | 24 +++++++++++++++---- .../features/domain/FeatureStreamImpl.java | 18 +++++++------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStream.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStream.java index 642a5aca4..1fff6f79d 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStream.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStream.java @@ -149,23 +149,39 @@ default boolean isSuccess() { default CompletionStage runWith( Sink sink, Map propertyTransformations) { - return runWith(sink, propertyTransformations, new CompletableFuture<>()); + return runWith(sink, propertyTransformations, new CompletableFuture<>(), Optional.empty()); + } + + default CompletionStage runWith( + Sink sink, + Map propertyTransformations, + CompletableFuture onCollectionMetadata) { + return runWith(sink, propertyTransformations, onCollectionMetadata, Optional.empty()); } CompletionStage runWith( Sink sink, Map propertyTransformations, - CompletableFuture onCollectionMetadata); + CompletableFuture onCollectionMetadata, + Optional requestId); default CompletionStage> runWith( SinkReduced sink, Map propertyTransformations) { - return runWith(sink, propertyTransformations, new CompletableFuture<>()); + return runWith(sink, propertyTransformations, new CompletableFuture<>(), Optional.empty()); + } + + default CompletionStage> runWith( + SinkReduced sink, + Map propertyTransformations, + CompletableFuture onCollectionMetadata) { + return runWith(sink, propertyTransformations, onCollectionMetadata, Optional.empty()); } CompletionStage> runWith( SinkReduced sink, Map propertyTransformations, - CompletableFuture onCollectionMetadata); + CompletableFuture onCollectionMetadata, + Optional requestId); // CompletionStage runWith(SinkTransformed sink, // Optional propertyTransformations); diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index 65c9c0caa..f2b40d51a 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -13,7 +13,6 @@ import com.google.common.collect.ImmutableMap; import de.ii.xtraplatform.base.domain.AuditLogger; import de.ii.xtraplatform.base.domain.ETag; -import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.crs.domain.CrsTransformer; import de.ii.xtraplatform.crs.domain.CrsTransformerFactory; @@ -103,7 +102,8 @@ public FeatureStreamImpl( public CompletionStage runWith( Sink sink, Map propertyTransformations, - CompletableFuture onCollectionMetadata) { + CompletableFuture onCollectionMetadata, + Optional requestId) { Map mergedTransformations = getMergedTransformations(data.getTypes(), query, propertyTransformations); @@ -137,14 +137,13 @@ public CompletionStage runWith( } if (stepAudit) { - if (!LogContext.has(LogContext.CONTEXT.AUDIT)) { + if (requestId.isEmpty()) { throw new IllegalStateException( "Audit logging not possible, no request-uuid provided!"); } - String requestUuid = LogContext.get(LogContext.CONTEXT.AUDIT); source = source.via( - new FeatureTokenTransformerAudit(resultBuilder, requestUuid, auditLogger)); + new FeatureTokenTransformerAudit(resultBuilder, requestId.get(), auditLogger)); } source = @@ -181,7 +180,8 @@ public CompletionStage runWith( public CompletionStage> runWith( SinkReduced sink, Map propertyTransformations, - CompletableFuture onCollectionMetadata) { + CompletableFuture onCollectionMetadata, + Optional requestId) { Map mergedTransformations = getMergedTransformations(data.getTypes(), query, propertyTransformations); @@ -212,15 +212,15 @@ public CompletionStage> runWith( if (stepMetadata) { source = source.via(new FeatureTokenTransformerMetadata(resultBuilder)); } + Optional test = requestId; if (stepAudit) { - if (!LogContext.has(LogContext.CONTEXT.AUDIT)) { + if (requestId.isEmpty()) { throw new IllegalStateException( "Audit logging not possible, no request-uuid provided!"); } - String requestUuid = LogContext.get(LogContext.CONTEXT.AUDIT); source = source.via( - new FeatureTokenTransformerAudit(resultBuilder, requestUuid, auditLogger)); + new FeatureTokenTransformerAudit(resultBuilder, requestId.get(), auditLogger)); } source = source.via(new FeatureTokenTransformerHooks(resultBuilder, onCollectionMetadata)); From ac5756ee7666131f5709bbb801ca565d34fdff94 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Wed, 20 May 2026 13:51:57 +0200 Subject: [PATCH 07/15] apply updated AuditLogger api calls --- .../features/domain/FeatureStreamImpl.java | 6 +- .../domain/FeatureTokenTransformerAudit.java | 60 +++++++++---------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index f2b40d51a..ec48b78ed 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -139,7 +139,7 @@ public CompletionStage runWith( if (stepAudit) { if (requestId.isEmpty()) { throw new IllegalStateException( - "Audit logging not possible, no request-uuid provided!"); + "Audit logging not possible, no request-id provided!"); } source = source.via( @@ -212,11 +212,11 @@ public CompletionStage> runWith( if (stepMetadata) { source = source.via(new FeatureTokenTransformerMetadata(resultBuilder)); } - Optional test = requestId; + if (stepAudit) { if (requestId.isEmpty()) { throw new IllegalStateException( - "Audit logging not possible, no request-uuid provided!"); + "Audit logging not possible, no request-id provided!"); } source = source.via( diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index ac27a9438..326238d72 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 interactive instruments GmbH + * Copyright 2026 interactive instruments GmbH * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -14,48 +14,41 @@ public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { - private final String requestUuid; + private final String requestId; private final AuditLogger auditLogger; private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); public FeatureTokenTransformerAudit( - ImmutableResult.Builder resultBuilder, String requestUuid, AuditLogger auditLogger) { - this.requestUuid = requestUuid; + ImmutableResult.Builder resultBuilder, String requestId, AuditLogger auditLogger) { + this.requestId = requestId; this.auditLogger = auditLogger; } public FeatureTokenTransformerAudit( - ImmutableResultReduced.Builder resultBuilder, - String requestUuid, - AuditLogger auditLogger) { - this.requestUuid = requestUuid; + ImmutableResultReduced.Builder resultBuilder, String requestId, AuditLogger auditLogger) { + this.requestId = requestId; this.auditLogger = auditLogger; } @Override public void onStart(ModifiableContext context) { - // Annahme: Types -> Properties is always of size==1 - if (context.mappings().size() != 1) - throw new IllegalStateException("Types zu Properties Mapping ist ungleich 1."); - - String type = context.mappings().keySet().stream().findFirst().get(); - auditLogger.initType(requestUuid, type); - - for (FeatureSchema prop : context.mappings().get(type).getTargetSchema().getProperties()) { - if (prop.getAudit().isPresent()) { - String audit = prop.getAudit().get().toLowerCase(); - switch (audit) { - case "access": - auditLogger.initPropertyToAccessTrack(requestUuid, prop.getName()); - continue; - case "value": - auditLogger.initPropertyToValueTrack(requestUuid, prop.getName()); - continue; - case "none": - continue; - default: - LOGGER.error("Wrong value for audit: {}", audit); + for (String type : context.mappings().keySet()) { + for (FeatureSchema prop : context.mappings().get(type).getTargetSchema().getProperties()) { + if (prop.getAudit().isPresent()) { + String audit = prop.getAudit().get().toLowerCase(); + switch (audit) { + case "access": + auditLogger.initPropertyToAccessTrack(requestId, type, prop.getName()); + continue; + case "value": + auditLogger.initPropertyToValueTrack(requestId, type, prop.getName()); + continue; + case "none": + continue; + default: + LOGGER.error("Wrong entry for audit: {}", audit); + } } } } @@ -76,26 +69,27 @@ public void onValue(ModifiableContext context) { String audit = prop.get().getAudit().get().toLowerCase(); switch (audit) { case "access": - auditLogger.markAccessed(requestUuid, prop.get().getName()); + auditLogger.markPropertyAccessed(requestId, type, prop.get().getName()); break; case "value": - auditLogger.appendPropertyValue(requestUuid, prop.get().getName(), context.value()); + auditLogger.appendPropertyValue(requestId, type, prop.get().getName(), context.value()); break; case "none": break; default: - LOGGER.error("Wrong value for audit: {}", audit); + LOGGER.error("Wrong entry for audit: {}", audit); } } } else { LOGGER.error("No property found with path: {}", context.pathTracker().toString()); } + super.onValue(context); } @Override public void onEnd(ModifiableContext context) { - auditLogger.saveToFileAndRemove(requestUuid); + auditLogger.saveToFileAndRemove(requestId); super.onEnd(context); } } From 38aa8f9766647c68585b6c1f469f70fe45af2308 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Thu, 21 May 2026 16:38:07 +0200 Subject: [PATCH 08/15] apply AuditLog refactor --- .../features/gml/app/FeatureProviderWfs.java | 11 +++---- .../graphql/app/FeatureProviderGraphQl.java | 6 ++-- .../oracle/app/FeatureProviderOracle.java | 6 ++-- .../sql/domain/FeatureProviderSql.java | 12 +++---- .../domain/AbstractFeatureProvider.java | 13 ++++---- .../features/domain/FeatureStreamImpl.java | 12 +++---- .../domain/FeatureTokenTransformerAudit.java | 32 ++++++++++++------- 7 files changed, 50 insertions(+), 42 deletions(-) diff --git a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java index b54348f0e..38990e891 100644 --- a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java +++ b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java @@ -10,7 +10,7 @@ import com.google.common.collect.ImmutableList; import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.base.domain.AuditLogger; +import de.ii.xtraplatform.base.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.cql.domain.Cql; @@ -143,7 +143,7 @@ public FeatureProviderWfs( Reactive reactive, ValueStore valueStore, ProviderExtensionRegistry extensionRegistry, - AuditLogger auditLogger, + AuditLog auditLog, VolatileRegistry volatileRegistry, @Assisted FeatureProviderDataV2 data) { super( @@ -153,7 +153,7 @@ public FeatureProviderWfs( crsInfo, extensionRegistry, valueStore.forType(Codelist.class), - auditLogger, + auditLog, data, volatileRegistry); @@ -230,10 +230,9 @@ protected FeatureQueryEncoder getQueryEncoder() { private FeatureTokenDecoder< byte[], FeatureSchema, SchemaMapping, ModifiableContext> getDecoder(Query query, Map mappings, boolean passThrough) { - if (!(query instanceof FeatureQuery)) { + if (!(query instanceof FeatureQuery featureQuery)) { throw new IllegalArgumentException(); } - FeatureQuery featureQuery = (FeatureQuery) query; Map namespaces = getData().getConnectionInfo().getNamespaces(); XMLNamespaceNormalizer namespaceNormalizer = new XMLNamespaceNormalizer(namespaces); FeatureSchema featureSchema = getData().getTypes().get(featureQuery.getType()); @@ -380,6 +379,6 @@ public FeatureStream getFeatureStreamPassThrough(FeatureQuery query) { getCodelists(), this::runQuery, false, - auditLogger); + auditLog); } } diff --git a/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java b/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java index eac9e60f0..ea82aecba 100644 --- a/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java +++ b/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java @@ -9,7 +9,7 @@ import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.base.domain.AuditLogger; +import de.ii.xtraplatform.base.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.cql.domain.Cql; @@ -198,7 +198,7 @@ public FeatureProviderGraphQl( Reactive reactive, ValueStore valueStore, ProviderExtensionRegistry extensionRegistry, - AuditLogger auditLogger, + AuditLog auditLog, VolatileRegistry volatileRegistry, @Assisted FeatureProviderDataV2 data) { super( @@ -208,7 +208,7 @@ public FeatureProviderGraphQl( crsInfo, extensionRegistry, valueStore.forType(Codelist.class), - auditLogger, + auditLog, data, volatileRegistry); diff --git a/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java b/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java index 156e7e5fd..891b748d8 100644 --- a/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java +++ b/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java @@ -9,7 +9,7 @@ import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.base.domain.AuditLogger; +import de.ii.xtraplatform.base.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.cache.domain.Cache; import de.ii.xtraplatform.cql.domain.Cql; @@ -127,7 +127,7 @@ public FeatureProviderOracle( VolatileRegistry volatileRegistry, Cache cache, Scheduler scheduler, - AuditLogger auditLogger, + AuditLog auditLog, @Assisted FeatureProviderDataV2 data) { super( crsTransformerFactory, @@ -142,7 +142,7 @@ public FeatureProviderOracle( volatileRegistry, cache, scheduler, - auditLogger, + auditLog, data, Map.of()); } diff --git a/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java b/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java index 2646e5353..8cbe7b65d 100644 --- a/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java +++ b/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java @@ -14,7 +14,7 @@ import com.google.common.collect.ImmutableMap; import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.base.domain.AuditLogger; +import de.ii.xtraplatform.base.domain.AuditLog; import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.cache.domain.Cache; @@ -484,7 +484,7 @@ public FeatureProviderSql( VolatileRegistry volatileRegistry, Cache cache, Scheduler scheduler, - AuditLogger auditLogger, + AuditLog auditLog, @Assisted FeatureProviderDataV2 data) { this( crsTransformerFactory, @@ -499,7 +499,7 @@ public FeatureProviderSql( volatileRegistry, cache, scheduler, - auditLogger, + auditLog, data, decoderFactories.getConnectorDecoders()); } @@ -517,7 +517,7 @@ protected FeatureProviderSql( VolatileRegistry volatileRegistry, Cache cache, Scheduler scheduler, - AuditLogger auditLogger, + AuditLog auditLog, FeatureProviderDataV2 data, Map subdecoders) { super( @@ -527,7 +527,7 @@ protected FeatureProviderSql( crsInfo, extensionRegistry, valueStore.forType(Codelist.class), - auditLogger, + auditLog, data, volatileRegistry); @@ -1451,7 +1451,7 @@ public FeatureStream getFeatureStream(MultiFeatureQuery query) { getCodelists(), this::runQuery, !query.hitsOnly(), - auditLogger); + auditLog); } @Override diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java index 40c1ab000..e306b58ab 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java @@ -11,7 +11,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import de.ii.xtraplatform.base.domain.AuditLogger; +import de.ii.xtraplatform.base.domain.AuditLog; import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.base.domain.resiliency.DelayedVolatile; import de.ii.xtraplatform.base.domain.resiliency.Volatile2; @@ -86,7 +86,7 @@ public abstract class AbstractFeatureProvider< private boolean datasetChangedForced; private String previousDataset; - protected AuditLogger auditLogger; + protected AuditLog auditLog; protected AbstractFeatureProvider( ConnectorFactory connectorFactory, @@ -95,7 +95,7 @@ protected AbstractFeatureProvider( CrsInfo crsInfo, ProviderExtensionRegistry extensionRegistry, Values codelistStore, - AuditLogger auditLogger, + AuditLog auditLog, FeatureProviderDataV2 data, VolatileRegistry volatileRegistry) { super(data, volatileRegistry); @@ -105,7 +105,7 @@ protected AbstractFeatureProvider( this.crsInfo = crsInfo; this.extensionRegistry = extensionRegistry; this.codelistStore = codelistStore; - this.auditLogger = auditLogger; + this.auditLog = auditLog; this.volatileRegistry = volatileRegistry; this.changeHandler = new FeatureChangeHandlerImpl(); this.connector = @@ -526,7 +526,7 @@ public FeatureStream getFeatureStream(FeatureQuery query) { getCodelists(), this::runQuery, !query.hitsOnly(), - auditLogger); + auditLog); } // TODO: more tests @@ -593,8 +593,7 @@ private FeatureTokenSource getFeatureTokenSource( private Map createMapping( Query query, Map propertyTransformations) { - if (query instanceof FeatureQuery) { - FeatureQuery featureQuery = (FeatureQuery) query; + if (query instanceof FeatureQuery featureQuery) { WithScope withScope = featureQuery.getSchemaScope() == SchemaBase.Scope.RETURNABLE diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index ec48b78ed..6dfd26e13 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -11,7 +11,7 @@ import static de.ii.xtraplatform.features.domain.transform.PropertyTransformations.WILDCARD; import com.google.common.collect.ImmutableMap; -import de.ii.xtraplatform.base.domain.AuditLogger; +import de.ii.xtraplatform.base.domain.AuditLog; import de.ii.xtraplatform.base.domain.ETag; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.crs.domain.CrsTransformer; @@ -53,7 +53,7 @@ public class FeatureStreamImpl implements FeatureStream { private final boolean stepMetadata; private final boolean stepAudit; - private final AuditLogger auditLogger; + private final AuditLog auditLog; public FeatureStreamImpl( Query query, @@ -63,7 +63,7 @@ public FeatureStreamImpl( Map codelists, QueryRunner runner, boolean doTransform, - AuditLogger auditLogger) { + AuditLog auditLog) { this.query = query; this.data = data; this.crsTransformerFactory = crsTransformerFactory; @@ -71,7 +71,7 @@ public FeatureStreamImpl( this.codelists = codelists; this.runner = runner; this.doTransform = doTransform; - this.auditLogger = auditLogger; + this.auditLog = auditLog; this.stepMappingSchema = !query.skipPipelineSteps().contains(PipelineSteps.MAPPING_SCHEMA) @@ -143,7 +143,7 @@ public CompletionStage runWith( } source = source.via( - new FeatureTokenTransformerAudit(resultBuilder, requestId.get(), auditLogger)); + new FeatureTokenTransformerAudit(resultBuilder, requestId.get(), auditLog)); } source = @@ -220,7 +220,7 @@ public CompletionStage> runWith( } source = source.via( - new FeatureTokenTransformerAudit(resultBuilder, requestId.get(), auditLogger)); + new FeatureTokenTransformerAudit(resultBuilder, requestId.get(), auditLog)); } source = source.via(new FeatureTokenTransformerHooks(resultBuilder, onCollectionMetadata)); diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index 326238d72..4c3756efc 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -7,7 +7,9 @@ */ package de.ii.xtraplatform.features.domain; -import de.ii.xtraplatform.base.domain.AuditLogger; +import com.fasterxml.jackson.core.JsonProcessingException; +import de.ii.xtraplatform.base.domain.AuditLog; +import java.util.List; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,20 +17,20 @@ public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { private final String requestId; - private final AuditLogger auditLogger; + private final AuditLog auditLog; private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); public FeatureTokenTransformerAudit( - ImmutableResult.Builder resultBuilder, String requestId, AuditLogger auditLogger) { + ImmutableResult.Builder resultBuilder, String requestId, AuditLog auditLog) { this.requestId = requestId; - this.auditLogger = auditLogger; + this.auditLog = auditLog; } public FeatureTokenTransformerAudit( - ImmutableResultReduced.Builder resultBuilder, String requestId, AuditLogger auditLogger) { + ImmutableResultReduced.Builder resultBuilder, String requestId, AuditLog auditLog) { this.requestId = requestId; - this.auditLogger = auditLogger; + this.auditLog = auditLog; } @Override @@ -39,10 +41,10 @@ public void onStart(ModifiableContext context) { String audit = prop.getAudit().get().toLowerCase(); switch (audit) { case "access": - auditLogger.initPropertyToAccessTrack(requestId, type, prop.getName()); + auditLog.initPropertyToAccessTrack(requestId, type, prop.getName()); continue; case "value": - auditLogger.initPropertyToValueTrack(requestId, type, prop.getName()); + auditLog.initPropertyToValueTrack(requestId, type, prop.getName()); continue; case "none": continue; @@ -64,15 +66,19 @@ public void onValue(ModifiableContext context) { .filter(p -> p.getFullPathAsString().equals(context.pathTracker().toString())) .findFirst(); + List test = context.mappings().get(type).getTargetSchema().getProperties(); + List testid = context.mappings().get(type).getTargetSchema().getIdProperties(); + FeatureSchema testtarget = context.mappings().get(type).getTargetSchema(); + String testname = context.mappings().get(type).getTargetSchema().getName(); if (prop.isPresent()) { if (prop.get().getAudit().isPresent()) { String audit = prop.get().getAudit().get().toLowerCase(); switch (audit) { case "access": - auditLogger.markPropertyAccessed(requestId, type, prop.get().getName()); + auditLog.markPropertyAccessed(requestId, type, prop.get().getName()); break; case "value": - auditLogger.appendPropertyValue(requestId, type, prop.get().getName(), context.value()); + auditLog.appendPropertyValue(requestId, type, prop.get().getName(), context.value()); break; case "none": break; @@ -89,7 +95,11 @@ public void onValue(ModifiableContext context) { @Override public void onEnd(ModifiableContext context) { - auditLogger.saveToFileAndRemove(requestId); + try { + auditLog.saveLogToFileAndRemove(requestId); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } super.onEnd(context); } } From a1ccdf89fd5b1c28dd0c3504ff09860d5b48b315 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Fri, 22 May 2026 14:04:50 +0200 Subject: [PATCH 09/15] apply AuditLog changes --- .../features/domain/FeatureSchema.java | 2 +- .../domain/FeatureTokenTransformerAudit.java | 70 +++++++------------ 2 files changed, 26 insertions(+), 46 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java index 9d771a24b..567887b7e 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureSchema.java @@ -73,7 +73,7 @@ public interface FeatureSchema String CONCAT_ELEMENT = "_CONCAT_ELEMENT_"; String COALESCE_ELEMENT = "_COALESCE_ELEMENT_"; - Optional getAudit(); + Optional getAudit(); @JsonIgnore @Override diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index 4c3756efc..580aa8e5f 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -9,17 +9,22 @@ import com.fasterxml.jackson.core.JsonProcessingException; import de.ii.xtraplatform.base.domain.AuditLog; +import de.ii.xtraplatform.features.domain.SchemaBase.Role; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { + private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); private final String requestId; private final AuditLog auditLog; - - private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); + private final Map featureHolder = new HashMap<>(); + private final List> featureList = new ArrayList<>(); public FeatureTokenTransformerAudit( ImmutableResult.Builder resultBuilder, String requestId, AuditLog auditLog) { @@ -34,28 +39,9 @@ public FeatureTokenTransformerAudit( } @Override - public void onStart(ModifiableContext context) { - for (String type : context.mappings().keySet()) { - for (FeatureSchema prop : context.mappings().get(type).getTargetSchema().getProperties()) { - if (prop.getAudit().isPresent()) { - String audit = prop.getAudit().get().toLowerCase(); - switch (audit) { - case "access": - auditLog.initPropertyToAccessTrack(requestId, type, prop.getName()); - continue; - case "value": - auditLog.initPropertyToValueTrack(requestId, type, prop.getName()); - continue; - case "none": - continue; - default: - LOGGER.error("Wrong entry for audit: {}", audit); - } - } - } - } - - super.onStart(context); + public void onFeatureStart(ModifiableContext context) { + featureHolder.clear(); + super.onFeatureStart(context); } @Override @@ -66,36 +52,30 @@ public void onValue(ModifiableContext context) { .filter(p -> p.getFullPathAsString().equals(context.pathTracker().toString())) .findFirst(); - List test = context.mappings().get(type).getTargetSchema().getProperties(); - List testid = context.mappings().get(type).getTargetSchema().getIdProperties(); - FeatureSchema testtarget = context.mappings().get(type).getTargetSchema(); - String testname = context.mappings().get(type).getTargetSchema().getName(); - if (prop.isPresent()) { - if (prop.get().getAudit().isPresent()) { - String audit = prop.get().getAudit().get().toLowerCase(); - switch (audit) { - case "access": - auditLog.markPropertyAccessed(requestId, type, prop.get().getName()); - break; - case "value": - auditLog.appendPropertyValue(requestId, type, prop.get().getName(), context.value()); - break; - case "none": - break; - default: - LOGGER.error("Wrong entry for audit: {}", audit); - } - } - } else { + if (prop.isEmpty()) { LOGGER.error("No property found with path: {}", context.pathTracker().toString()); + super.onValue(context); + return; } + if (prop.get().getRole().filter(Role.ID::equals).isPresent()) { + featureHolder.put("id", context.value()); + } else if (prop.get().getAudit().isPresent()) { + featureHolder.put(prop.get().getName(), context.value()); + } super.onValue(context); } + @Override + public void onFeatureEnd(ModifiableContext context) { + featureList.add(new HashMap<>(featureHolder)); + super.onFeatureEnd(context); + } + @Override public void onEnd(ModifiableContext context) { try { + auditLog.initTarget(requestId, Map.of("features", featureList)); auditLog.saveLogToFileAndRemove(requestId); } catch (JsonProcessingException e) { throw new RuntimeException(e); From 35c3c8b3f9471ec361fd07f40845894d4a2c5469 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Tue, 26 May 2026 11:51:32 +0200 Subject: [PATCH 10/15] keep property order by using LinkedHashMap --- .../features/domain/FeatureTokenTransformerAudit.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index 580aa8e5f..9393cc138 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -11,7 +11,7 @@ import de.ii.xtraplatform.base.domain.AuditLog; import de.ii.xtraplatform.features.domain.SchemaBase.Role; import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -23,7 +23,7 @@ public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { private static final Logger LOGGER = LoggerFactory.getLogger(FeatureTokenTransformerAudit.class); private final String requestId; private final AuditLog auditLog; - private final Map featureHolder = new HashMap<>(); + private final Map featureHolder = new LinkedHashMap<>(); private final List> featureList = new ArrayList<>(); public FeatureTokenTransformerAudit( @@ -68,7 +68,7 @@ public void onValue(ModifiableContext context) { @Override public void onFeatureEnd(ModifiableContext context) { - featureList.add(new HashMap<>(featureHolder)); + featureList.add(new LinkedHashMap<>(featureHolder)); super.onFeatureEnd(context); } From 57f68924c2d92c081274b0d7dc1d346f86a9a051 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Wed, 27 May 2026 15:52:48 +0200 Subject: [PATCH 11/15] remove log-finalizing from onEnd --- .../features/domain/FeatureStreamImpl.java | 274 +++++++++--------- .../domain/FeatureTokenTransformerAudit.java | 17 +- 2 files changed, 137 insertions(+), 154 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index 6dfd26e13..8fa86b62c 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -98,6 +98,139 @@ public FeatureStreamImpl( && !query.skipPipelineSteps().contains(PipelineSteps.ALL); } + static Map getMergedTransformations( + Map featureSchemas, + Query query, + Map propertyTransformations) { + if (query instanceof FeatureQuery featureQuery) { + return ImmutableMap.of( + featureQuery.getType(), + getPropertyTransformations( + featureSchemas, + featureQuery, + Optional.ofNullable(propertyTransformations.get(featureQuery.getType())))); + } + + if (query instanceof MultiFeatureQuery multiFeatureQuery) { + return multiFeatureQuery.getQueries().stream() + .map( + typeQuery -> + new SimpleImmutableEntry<>( + typeQuery.getType(), + getPropertyTransformations( + featureSchemas, + typeQuery, + Optional.ofNullable(propertyTransformations.get(typeQuery.getType()))))) + .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + return ImmutableMap.of(); + } + + static PropertyTransformations getPropertyTransformations( + Map featureSchemas, + TypeQuery typeQuery, + Optional propertyTransformations) { + if (typeQuery instanceof FeatureQuery + && ((FeatureQuery) typeQuery).getSchemaScope() == SchemaBase.Scope.RECEIVABLE) { + return () -> + getProviderTransformations( + featureSchemas.get(typeQuery.getType()), SchemaBase.Scope.RECEIVABLE); + } + + PropertyTransformations providerTransformations = + () -> + getProviderTransformations( + featureSchemas.get(typeQuery.getType()), SchemaBase.Scope.RETURNABLE); + + PropertyTransformations merged = + propertyTransformations + .map(p -> p.mergeInto(providerTransformations)) + .orElse(providerTransformations); + + return applyRename(merged); + } + + private static PropertyTransformations applyRename( + PropertyTransformations propertyTransformations) { + if (propertyTransformations.getTransformations().values().stream() + .flatMap(Collection::stream) + .anyMatch(propertyTransformation -> propertyTransformation.getRename().isPresent())) { + Map> renamed = new LinkedHashMap<>(); + + propertyTransformations + .getTransformations() + .forEach( + (key, value) -> { + Optional rename = + value.stream() + .filter( + propertyTransformation -> + propertyTransformation.getRename().isPresent()) + .map(propertyTransformation -> propertyTransformation.getRename().get()) + .findFirst(); + + if (rename.isPresent()) { + renamed.put(rename.get(), value); + + String prefix = key + "."; + + propertyTransformations + .getTransformations() + .forEach( + (key2, value2) -> { + if (key2.startsWith(prefix)) { + renamed.put(key2.replace(key, rename.get()), value2); + } + }); + } + }); + + return propertyTransformations.mergeInto(() -> renamed); + } + + return propertyTransformations; + } + + private static Map> getProviderTransformations( + FeatureSchema featureSchema, SchemaBase.Scope scope) { + return featureSchema + .accept( + scope == SchemaBase.Scope.RECEIVABLE + ? AbstractFeatureProvider.WITH_SCOPE_RECEIVABLE + : AbstractFeatureProvider.WITH_SCOPE_RETURNABLE) + .accept( + (schema, visitedProperties) -> + java.util.stream.Stream.concat( + getProviderTransformationsForProperty(schema, scope), + visitedProperties.stream().flatMap(m -> m.entrySet().stream())) + .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))); + } + + private static java.util.stream.Stream>> + getProviderTransformationsForProperty(FeatureSchema schema, SchemaBase.Scope scope) { + if (schema.getTransformations().isEmpty()) { + if (schema.isTemporal() && schema.getType() == SchemaBase.Type.DATETIME) { + return java.util.stream.Stream.of( + Map.entry( + schema.getFullPathAsString(), + List.of( + new ImmutablePropertyTransformation.Builder() + .dateFormat(DATETIME_FORMAT) + .build()))); + } + return java.util.stream.Stream.empty(); + } + + return java.util.stream.Stream.of( + Map.entry( + schema.getFullPath().isEmpty() ? WILDCARD : schema.getFullPathAsString(), + schema.getTransformations().stream() + // TODO: mark transformations with scope? + .filter(pt -> scope != SchemaBase.Scope.RECEIVABLE || pt.getWrap().isPresent()) + .toList())); + } + @Override public CompletionStage runWith( Sink sink, @@ -141,9 +274,7 @@ public CompletionStage runWith( throw new IllegalStateException( "Audit logging not possible, no request-id provided!"); } - source = - source.via( - new FeatureTokenTransformerAudit(resultBuilder, requestId.get(), auditLog)); + source = source.via(new FeatureTokenTransformerAudit(requestId.get(), auditLog)); } source = @@ -218,9 +349,7 @@ public CompletionStage> runWith( throw new IllegalStateException( "Audit logging not possible, no request-id provided!"); } - source = - source.via( - new FeatureTokenTransformerAudit(resultBuilder, requestId.get(), auditLog)); + source = source.via(new FeatureTokenTransformerAudit(requestId.get(), auditLog)); } source = source.via(new FeatureTokenTransformerHooks(resultBuilder, onCollectionMetadata)); @@ -309,137 +438,4 @@ private FeatureTokenSource getFeatureTokenSourceTransformed( return tokenSourceTransformed; } - - static Map getMergedTransformations( - Map featureSchemas, - Query query, - Map propertyTransformations) { - if (query instanceof FeatureQuery featureQuery) { - return ImmutableMap.of( - featureQuery.getType(), - getPropertyTransformations( - featureSchemas, - featureQuery, - Optional.ofNullable(propertyTransformations.get(featureQuery.getType())))); - } - - if (query instanceof MultiFeatureQuery multiFeatureQuery) { - return multiFeatureQuery.getQueries().stream() - .map( - typeQuery -> - new SimpleImmutableEntry<>( - typeQuery.getType(), - getPropertyTransformations( - featureSchemas, - typeQuery, - Optional.ofNullable(propertyTransformations.get(typeQuery.getType()))))) - .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - return ImmutableMap.of(); - } - - static PropertyTransformations getPropertyTransformations( - Map featureSchemas, - TypeQuery typeQuery, - Optional propertyTransformations) { - if (typeQuery instanceof FeatureQuery - && ((FeatureQuery) typeQuery).getSchemaScope() == SchemaBase.Scope.RECEIVABLE) { - return () -> - getProviderTransformations( - featureSchemas.get(typeQuery.getType()), SchemaBase.Scope.RECEIVABLE); - } - - PropertyTransformations providerTransformations = - () -> - getProviderTransformations( - featureSchemas.get(typeQuery.getType()), SchemaBase.Scope.RETURNABLE); - - PropertyTransformations merged = - propertyTransformations - .map(p -> p.mergeInto(providerTransformations)) - .orElse(providerTransformations); - - return applyRename(merged); - } - - private static PropertyTransformations applyRename( - PropertyTransformations propertyTransformations) { - if (propertyTransformations.getTransformations().values().stream() - .flatMap(Collection::stream) - .anyMatch(propertyTransformation -> propertyTransformation.getRename().isPresent())) { - Map> renamed = new LinkedHashMap<>(); - - propertyTransformations - .getTransformations() - .forEach( - (key, value) -> { - Optional rename = - value.stream() - .filter( - propertyTransformation -> - propertyTransformation.getRename().isPresent()) - .map(propertyTransformation -> propertyTransformation.getRename().get()) - .findFirst(); - - if (rename.isPresent()) { - renamed.put(rename.get(), value); - - String prefix = key + "."; - - propertyTransformations - .getTransformations() - .forEach( - (key2, value2) -> { - if (key2.startsWith(prefix)) { - renamed.put(key2.replace(key, rename.get()), value2); - } - }); - } - }); - - return propertyTransformations.mergeInto(() -> renamed); - } - - return propertyTransformations; - } - - private static Map> getProviderTransformations( - FeatureSchema featureSchema, SchemaBase.Scope scope) { - return featureSchema - .accept( - scope == SchemaBase.Scope.RECEIVABLE - ? AbstractFeatureProvider.WITH_SCOPE_RECEIVABLE - : AbstractFeatureProvider.WITH_SCOPE_RETURNABLE) - .accept( - (schema, visitedProperties) -> - java.util.stream.Stream.concat( - getProviderTransformationsForProperty(schema, scope), - visitedProperties.stream().flatMap(m -> m.entrySet().stream())) - .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))); - } - - private static java.util.stream.Stream>> - getProviderTransformationsForProperty(FeatureSchema schema, SchemaBase.Scope scope) { - if (schema.getTransformations().isEmpty()) { - if (schema.isTemporal() && schema.getType() == SchemaBase.Type.DATETIME) { - return java.util.stream.Stream.of( - Map.entry( - schema.getFullPathAsString(), - List.of( - new ImmutablePropertyTransformation.Builder() - .dateFormat(DATETIME_FORMAT) - .build()))); - } - return java.util.stream.Stream.empty(); - } - - return java.util.stream.Stream.of( - Map.entry( - schema.getFullPath().isEmpty() ? WILDCARD : schema.getFullPathAsString(), - schema.getTransformations().stream() - // TODO: mark transformations with scope? - .filter(pt -> scope != SchemaBase.Scope.RECEIVABLE || pt.getWrap().isPresent()) - .toList())); - } } diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index 9393cc138..e0852c7d1 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -7,7 +7,6 @@ */ package de.ii.xtraplatform.features.domain; -import com.fasterxml.jackson.core.JsonProcessingException; import de.ii.xtraplatform.base.domain.AuditLog; import de.ii.xtraplatform.features.domain.SchemaBase.Role; import java.util.ArrayList; @@ -26,14 +25,7 @@ public class FeatureTokenTransformerAudit extends FeatureTokenTransformer { private final Map featureHolder = new LinkedHashMap<>(); private final List> featureList = new ArrayList<>(); - public FeatureTokenTransformerAudit( - ImmutableResult.Builder resultBuilder, String requestId, AuditLog auditLog) { - this.requestId = requestId; - this.auditLog = auditLog; - } - - public FeatureTokenTransformerAudit( - ImmutableResultReduced.Builder resultBuilder, String requestId, AuditLog auditLog) { + public FeatureTokenTransformerAudit(String requestId, AuditLog auditLog) { this.requestId = requestId; this.auditLog = auditLog; } @@ -74,12 +66,7 @@ public void onFeatureEnd(ModifiableContext context @Override public void onEnd(ModifiableContext context) { - try { - auditLog.initTarget(requestId, Map.of("features", featureList)); - auditLog.saveLogToFileAndRemove(requestId); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } + auditLog.initTarget(requestId, Map.of("features", featureList)); super.onEnd(context); } } From 627453c05bffe60401026fce741c81acc0f32518 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Thu, 28 May 2026 08:38:03 +0200 Subject: [PATCH 12/15] apply audit-log module --- gradle/layers.versions.toml | 2 +- xtraplatform-features-gml/build.gradle | 2 +- .../de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java | 2 +- xtraplatform-features-graphql/build.gradle | 1 + .../features/graphql/app/FeatureProviderGraphQl.java | 2 +- xtraplatform-features-oracle/build.gradle | 1 + .../xtraplatform/features/oracle/app/FeatureProviderOracle.java | 2 +- xtraplatform-features-sql/build.gradle | 1 + .../ii/xtraplatform/features/sql/domain/FeatureProviderSql.java | 2 +- xtraplatform-features/build.gradle | 1 + .../xtraplatform/features/domain/AbstractFeatureProvider.java | 2 +- .../de/ii/xtraplatform/features/domain/FeatureStreamImpl.java | 2 +- .../features/domain/FeatureTokenTransformerAudit.java | 2 +- 13 files changed, 13 insertions(+), 9 deletions(-) diff --git a/gradle/layers.versions.toml b/gradle/layers.versions.toml index 66c9a3e80..12460694b 100644 --- a/gradle/layers.versions.toml +++ b/gradle/layers.versions.toml @@ -1,4 +1,4 @@ [versions] -xtraplatform-core = '7.0.0-ldp-95-audit-logging-SNAPSHOT' +xtraplatform-core = '7.0.0-ldp-95-audit-logging-new-module-SNAPSHOT' xtraplatform-native = '2.6.0-SNAPSHOT' diff --git a/xtraplatform-features-gml/build.gradle b/xtraplatform-features-gml/build.gradle index 1cc0f5132..0a0354fed 100644 --- a/xtraplatform-features-gml/build.gradle +++ b/xtraplatform-features-gml/build.gradle @@ -1,4 +1,3 @@ - maturity = 'CANDIDATE' maintenance = 'NONE' description = 'WFS feature provider and GML features.' @@ -9,6 +8,7 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' provided 'de.interactive_instruments:xtraplatform-web' + provided 'de.interactive_instruments:xtraplatform-audit-log' provided project(':xtraplatform-codelists') provided project(':xtraplatform-cql') provided project(':xtraplatform-crs') diff --git a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java index 38990e891..2768a6180 100644 --- a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java +++ b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java @@ -10,7 +10,7 @@ import com.google.common.collect.ImmutableList; import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.base.domain.AuditLog; +import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.cql.domain.Cql; diff --git a/xtraplatform-features-graphql/build.gradle b/xtraplatform-features-graphql/build.gradle index ece5323a0..0df49248c 100644 --- a/xtraplatform-features-graphql/build.gradle +++ b/xtraplatform-features-graphql/build.gradle @@ -9,6 +9,7 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' provided 'de.interactive_instruments:xtraplatform-web' + provided 'de.interactive_instruments:xtraplatform-audit-log' provided project(':xtraplatform-codelists') provided project(':xtraplatform-cql') provided project(':xtraplatform-crs') diff --git a/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java b/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java index ea82aecba..613fbb056 100644 --- a/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java +++ b/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java @@ -9,7 +9,7 @@ import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.base.domain.AuditLog; +import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.cql.domain.Cql; diff --git a/xtraplatform-features-oracle/build.gradle b/xtraplatform-features-oracle/build.gradle index 0cebd0412..4fa0660d2 100644 --- a/xtraplatform-features-oracle/build.gradle +++ b/xtraplatform-features-oracle/build.gradle @@ -11,6 +11,7 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' provided 'de.interactive_instruments:xtraplatform-services' + provided 'de.interactive_instruments:xtraplatform-audit-log' provided project(':xtraplatform-cql') provided project(':xtraplatform-crs') provided project(':xtraplatform-features') diff --git a/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java b/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java index 891b748d8..85c47c8cb 100644 --- a/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java +++ b/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java @@ -9,7 +9,7 @@ import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.base.domain.AuditLog; +import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.cache.domain.Cache; import de.ii.xtraplatform.cql.domain.Cql; diff --git a/xtraplatform-features-sql/build.gradle b/xtraplatform-features-sql/build.gradle index caaee7be7..0a0cadcc8 100644 --- a/xtraplatform-features-sql/build.gradle +++ b/xtraplatform-features-sql/build.gradle @@ -14,6 +14,7 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-spatialite' provided 'de.interactive_instruments:xtraplatform-services' provided 'de.interactive_instruments:xtraplatform-web' + provided 'de.interactive_instruments:xtraplatform-audit-log' provided project(':xtraplatform-geometries') provided project(':xtraplatform-codelists') provided project(':xtraplatform-cql') diff --git a/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java b/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java index 8cbe7b65d..86bb01f0d 100644 --- a/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java +++ b/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java @@ -14,7 +14,7 @@ import com.google.common.collect.ImmutableMap; import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.base.domain.AuditLog; +import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.cache.domain.Cache; diff --git a/xtraplatform-features/build.gradle b/xtraplatform-features/build.gradle index 7313249dc..9758beadf 100644 --- a/xtraplatform-features/build.gradle +++ b/xtraplatform-features/build.gradle @@ -9,6 +9,7 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-entities' provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' + provided 'de.interactive_instruments:xtraplatform-audit-log' provided project(':xtraplatform-codelists') provided project(':xtraplatform-cql') provided project(':xtraplatform-crs') diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java index e306b58ab..af53aaca5 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java @@ -11,7 +11,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import de.ii.xtraplatform.base.domain.AuditLog; +import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.base.domain.resiliency.DelayedVolatile; import de.ii.xtraplatform.base.domain.resiliency.Volatile2; diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index 8fa86b62c..59bdd3342 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -11,7 +11,7 @@ import static de.ii.xtraplatform.features.domain.transform.PropertyTransformations.WILDCARD; import com.google.common.collect.ImmutableMap; -import de.ii.xtraplatform.base.domain.AuditLog; +import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.ETag; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.crs.domain.CrsTransformer; diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index e0852c7d1..b56b336ab 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -7,7 +7,7 @@ */ package de.ii.xtraplatform.features.domain; -import de.ii.xtraplatform.base.domain.AuditLog; +import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.features.domain.SchemaBase.Role; import java.util.ArrayList; import java.util.LinkedHashMap; From 1261ed90cf18a31c55aa21849479e9b8626a16c5 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Fri, 29 May 2026 14:31:08 +0200 Subject: [PATCH 13/15] apply auditLog moving to xtraplatform-services --- xtraplatform-features-gml/build.gradle | 2 +- .../ii/xtraplatform/features/gml/app/FeatureProviderWfs.java | 2 +- xtraplatform-features-graphql/build.gradle | 2 +- .../features/graphql/app/FeatureProviderGraphQl.java | 2 +- xtraplatform-features-oracle/build.gradle | 1 - .../features/oracle/app/FeatureProviderOracle.java | 2 +- xtraplatform-features-sql/build.gradle | 1 - .../xtraplatform/features/sql/domain/FeatureProviderSql.java | 2 +- xtraplatform-features/build.gradle | 3 +-- .../xtraplatform/features/domain/AbstractFeatureProvider.java | 2 +- .../de/ii/xtraplatform/features/domain/FeatureStreamImpl.java | 2 +- .../features/domain/FeatureTokenTransformerAudit.java | 4 ++-- 12 files changed, 11 insertions(+), 14 deletions(-) diff --git a/xtraplatform-features-gml/build.gradle b/xtraplatform-features-gml/build.gradle index 0a0354fed..b7eb10154 100644 --- a/xtraplatform-features-gml/build.gradle +++ b/xtraplatform-features-gml/build.gradle @@ -8,7 +8,7 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' provided 'de.interactive_instruments:xtraplatform-web' - provided 'de.interactive_instruments:xtraplatform-audit-log' + provided 'de.interactive_instruments:xtraplatform-services' provided project(':xtraplatform-codelists') provided project(':xtraplatform-cql') provided project(':xtraplatform-crs') diff --git a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java index 2768a6180..cbf17913e 100644 --- a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java +++ b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/app/FeatureProviderWfs.java @@ -10,7 +10,6 @@ import com.google.common.collect.ImmutableList; import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.cql.domain.Cql; @@ -58,6 +57,7 @@ import de.ii.xtraplatform.features.gml.domain.FeatureProviderWfsData; import de.ii.xtraplatform.features.gml.domain.WfsConnector; import de.ii.xtraplatform.features.gml.domain.XMLNamespaceNormalizer; +import de.ii.xtraplatform.services.domain.AuditLog; import de.ii.xtraplatform.streams.domain.Reactive; import de.ii.xtraplatform.streams.domain.Reactive.Stream; import de.ii.xtraplatform.values.domain.ValueStore; diff --git a/xtraplatform-features-graphql/build.gradle b/xtraplatform-features-graphql/build.gradle index 0df49248c..849a1e5f7 100644 --- a/xtraplatform-features-graphql/build.gradle +++ b/xtraplatform-features-graphql/build.gradle @@ -9,7 +9,7 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' provided 'de.interactive_instruments:xtraplatform-web' - provided 'de.interactive_instruments:xtraplatform-audit-log' + provided 'de.interactive_instruments:xtraplatform-services' provided project(':xtraplatform-codelists') provided project(':xtraplatform-cql') provided project(':xtraplatform-crs') diff --git a/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java b/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java index 613fbb056..0ad1914ce 100644 --- a/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java +++ b/xtraplatform-features-graphql/src/main/java/de/ii/xtraplatform/features/graphql/app/FeatureProviderGraphQl.java @@ -9,7 +9,6 @@ import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.cql.domain.Cql; @@ -50,6 +49,7 @@ import de.ii.xtraplatform.features.domain.transform.OnlySortables; import de.ii.xtraplatform.features.graphql.domain.FeatureProviderGraphQlData; import de.ii.xtraplatform.features.graphql.domain.GraphQlConnector; +import de.ii.xtraplatform.services.domain.AuditLog; import de.ii.xtraplatform.streams.domain.Reactive; import de.ii.xtraplatform.streams.domain.Reactive.Stream; import de.ii.xtraplatform.values.domain.ValueStore; diff --git a/xtraplatform-features-oracle/build.gradle b/xtraplatform-features-oracle/build.gradle index 4fa0660d2..0cebd0412 100644 --- a/xtraplatform-features-oracle/build.gradle +++ b/xtraplatform-features-oracle/build.gradle @@ -11,7 +11,6 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' provided 'de.interactive_instruments:xtraplatform-services' - provided 'de.interactive_instruments:xtraplatform-audit-log' provided project(':xtraplatform-cql') provided project(':xtraplatform-crs') provided project(':xtraplatform-features') diff --git a/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java b/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java index 85c47c8cb..c9c2bac42 100644 --- a/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java +++ b/xtraplatform-features-oracle/src/main/java/de/ii/xtraplatform/features/oracle/app/FeatureProviderOracle.java @@ -9,7 +9,6 @@ import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.cache.domain.Cache; import de.ii.xtraplatform.cql.domain.Cql; @@ -36,6 +35,7 @@ import de.ii.xtraplatform.features.sql.domain.SqlQueryOptions; import de.ii.xtraplatform.features.sql.domain.SqlRow; import de.ii.xtraplatform.geometries.domain.transcode.wktwkb.WkbDialect; +import de.ii.xtraplatform.services.domain.AuditLog; import de.ii.xtraplatform.services.domain.Scheduler; import de.ii.xtraplatform.streams.domain.Reactive; import de.ii.xtraplatform.values.domain.ValueStore; diff --git a/xtraplatform-features-sql/build.gradle b/xtraplatform-features-sql/build.gradle index 0a0cadcc8..caaee7be7 100644 --- a/xtraplatform-features-sql/build.gradle +++ b/xtraplatform-features-sql/build.gradle @@ -14,7 +14,6 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-spatialite' provided 'de.interactive_instruments:xtraplatform-services' provided 'de.interactive_instruments:xtraplatform-web' - provided 'de.interactive_instruments:xtraplatform-audit-log' provided project(':xtraplatform-geometries') provided project(':xtraplatform-codelists') provided project(':xtraplatform-cql') diff --git a/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java b/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java index 86bb01f0d..ddf8e59c2 100644 --- a/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java +++ b/xtraplatform-features-sql/src/main/java/de/ii/xtraplatform/features/sql/domain/FeatureProviderSql.java @@ -14,7 +14,6 @@ import com.google.common.collect.ImmutableMap; import dagger.assisted.Assisted; import dagger.assisted.AssistedInject; -import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.base.domain.resiliency.VolatileRegistry; import de.ii.xtraplatform.cache.domain.Cache; @@ -101,6 +100,7 @@ import de.ii.xtraplatform.features.sql.domain.SqlQueryColumn.Operation; import de.ii.xtraplatform.features.sql.infra.db.SourceSchemaValidatorSql; import de.ii.xtraplatform.geometries.domain.transcode.wktwkb.WkbDialect; +import de.ii.xtraplatform.services.domain.AuditLog; import de.ii.xtraplatform.services.domain.Scheduler; import de.ii.xtraplatform.streams.domain.Reactive; import de.ii.xtraplatform.streams.domain.Reactive.RunnableStream; diff --git a/xtraplatform-features/build.gradle b/xtraplatform-features/build.gradle index 9758beadf..f5387471f 100644 --- a/xtraplatform-features/build.gradle +++ b/xtraplatform-features/build.gradle @@ -1,4 +1,3 @@ - maturity = 'MATURE' maintenance = 'FULL' description = 'Feature providers and transformations.' @@ -9,7 +8,7 @@ dependencies { provided 'de.interactive_instruments:xtraplatform-entities' provided 'de.interactive_instruments:xtraplatform-streams' provided 'de.interactive_instruments:xtraplatform-values' - provided 'de.interactive_instruments:xtraplatform-audit-log' + provided 'de.interactive_instruments:xtraplatform-services' provided project(':xtraplatform-codelists') provided project(':xtraplatform-cql') provided project(':xtraplatform-crs') diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java index af53aaca5..65ba0ce07 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/AbstractFeatureProvider.java @@ -11,7 +11,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.LogContext; import de.ii.xtraplatform.base.domain.resiliency.DelayedVolatile; import de.ii.xtraplatform.base.domain.resiliency.Volatile2; @@ -35,6 +34,7 @@ import de.ii.xtraplatform.features.domain.transform.WithScope; import de.ii.xtraplatform.features.domain.transform.WithoutProperties; import de.ii.xtraplatform.geometries.domain.GeometryType; +import de.ii.xtraplatform.services.domain.AuditLog; import de.ii.xtraplatform.streams.domain.Reactive; import de.ii.xtraplatform.streams.domain.Reactive.Runner; import de.ii.xtraplatform.streams.domain.Reactive.Stream; diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index 59bdd3342..81d7e6863 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -11,7 +11,6 @@ import static de.ii.xtraplatform.features.domain.transform.PropertyTransformations.WILDCARD; import com.google.common.collect.ImmutableMap; -import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.base.domain.ETag; import de.ii.xtraplatform.codelists.domain.Codelist; import de.ii.xtraplatform.crs.domain.CrsTransformer; @@ -20,6 +19,7 @@ import de.ii.xtraplatform.features.domain.transform.ImmutablePropertyTransformation; import de.ii.xtraplatform.features.domain.transform.PropertyTransformation; import de.ii.xtraplatform.features.domain.transform.PropertyTransformations; +import de.ii.xtraplatform.services.domain.AuditLog; import de.ii.xtraplatform.streams.domain.Reactive; import de.ii.xtraplatform.streams.domain.Reactive.Sink; import de.ii.xtraplatform.streams.domain.Reactive.SinkReduced; diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java index b56b336ab..4eea16302 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureTokenTransformerAudit.java @@ -7,8 +7,8 @@ */ package de.ii.xtraplatform.features.domain; -import de.ii.xtraplatform.audit.log.domain.AuditLog; import de.ii.xtraplatform.features.domain.SchemaBase.Role; +import de.ii.xtraplatform.services.domain.AuditLog; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -66,7 +66,7 @@ public void onFeatureEnd(ModifiableContext context @Override public void onEnd(ModifiableContext context) { - auditLog.initTarget(requestId, Map.of("features", featureList)); + auditLog.setTarget(requestId, Map.of("features", featureList)); super.onEnd(context); } } From 0d172f387dbe18bd201311978a1661ebf6ce5a63 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Fri, 5 Jun 2026 16:22:42 +0200 Subject: [PATCH 14/15] optional property access --- .../features/domain/FeatureStreamImpl.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index 81d7e6863..fc7c780bf 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -270,11 +270,16 @@ public CompletionStage runWith( } if (stepAudit) { - if (requestId.isEmpty()) { - throw new IllegalStateException( - "Audit logging not possible, no request-id provided!"); + if (auditLog.isEnabled()) { + if (requestId.isEmpty()) { + throw new IllegalStateException( + "Audit logging not possible, no request-id provided!"); + } + + if (auditLog.logIsAvaible(requestId.get())) { + source = source.via(new FeatureTokenTransformerAudit(requestId.get(), auditLog)); + } } - source = source.via(new FeatureTokenTransformerAudit(requestId.get(), auditLog)); } source = @@ -345,12 +350,18 @@ public CompletionStage> runWith( } if (stepAudit) { - if (requestId.isEmpty()) { - throw new IllegalStateException( - "Audit logging not possible, no request-id provided!"); + if (auditLog.isEnabled()) { + if (requestId.isEmpty()) { + throw new IllegalStateException( + "Audit logging not possible, no request-id provided!"); + } + + if (auditLog.logIsAvaible(requestId.get())) { + source = source.via(new FeatureTokenTransformerAudit(requestId.get(), auditLog)); + } } - source = source.via(new FeatureTokenTransformerAudit(requestId.get(), auditLog)); } + source = source.via(new FeatureTokenTransformerHooks(resultBuilder, onCollectionMetadata)); From b5feed796baa56f7c73802e19fa7d06cec1a0b15 Mon Sep 17 00:00:00 2001 From: Afeef Neiroukh Date: Mon, 8 Jun 2026 12:36:03 +0200 Subject: [PATCH 15/15] replace throw by LOGGER.error --- .../features/domain/FeatureStreamImpl.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java index fc7c780bf..77563545d 100644 --- a/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java +++ b/xtraplatform-features/src/main/java/de/ii/xtraplatform/features/domain/FeatureStreamImpl.java @@ -272,11 +272,8 @@ public CompletionStage runWith( if (stepAudit) { if (auditLog.isEnabled()) { if (requestId.isEmpty()) { - throw new IllegalStateException( - "Audit logging not possible, no request-id provided!"); - } - - if (auditLog.logIsAvaible(requestId.get())) { + LOGGER.error("Audit logging not possible, no request-id provided!"); + } else if (auditLog.logIsAvailable(requestId.get())) { source = source.via(new FeatureTokenTransformerAudit(requestId.get(), auditLog)); } } @@ -352,11 +349,8 @@ public CompletionStage> runWith( if (stepAudit) { if (auditLog.isEnabled()) { if (requestId.isEmpty()) { - throw new IllegalStateException( - "Audit logging not possible, no request-id provided!"); - } - - if (auditLog.logIsAvaible(requestId.get())) { + LOGGER.error("Audit logging not possible, no request-id provided!"); + } else if (auditLog.logIsAvailable(requestId.get())) { source = source.via(new FeatureTokenTransformerAudit(requestId.get(), auditLog)); } }