Spaces:
Build error
Build error
Ajay Yadav
commited on
Commit
·
5cfe5c4
1
Parent(s):
fc2c890
Initial deployment of da-policyengine-dev
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- Dockerfile +27 -0
- README.md +33 -5
- build.gradle.kts +16 -0
- src/main/docker/Dockerfile +23 -0
- src/main/docker/Dockerfile.alpine-jlink +43 -0
- src/main/docker/Dockerfile.layered +34 -0
- src/main/docker/Dockerfile.native +20 -0
- src/main/java/com/dalab/policyengine/DaPolicyEngineApplication.java +37 -0
- src/main/java/com/dalab/policyengine/common/ConflictException.java +11 -0
- src/main/java/com/dalab/policyengine/common/ResourceNotFoundException.java +15 -0
- src/main/java/com/dalab/policyengine/config/OpenAPIConfiguration.java +27 -0
- src/main/java/com/dalab/policyengine/config/SecurityConfiguration.java +44 -0
- src/main/java/com/dalab/policyengine/dto/EventAnalyticsDTO.java +349 -0
- src/main/java/com/dalab/policyengine/dto/EventStreamDTO.java +216 -0
- src/main/java/com/dalab/policyengine/dto/EventSubscriptionInputDTO.java +229 -0
- src/main/java/com/dalab/policyengine/dto/EventSubscriptionOutputDTO.java +343 -0
- src/main/java/com/dalab/policyengine/dto/PolicyDraftActionDTO.java +268 -0
- src/main/java/com/dalab/policyengine/dto/PolicyDraftInputDTO.java +227 -0
- src/main/java/com/dalab/policyengine/dto/PolicyDraftOutputDTO.java +412 -0
- src/main/java/com/dalab/policyengine/dto/PolicyEvaluationOutputDTO.java +92 -0
- src/main/java/com/dalab/policyengine/dto/PolicyEvaluationRequestDTO.java +32 -0
- src/main/java/com/dalab/policyengine/dto/PolicyEvaluationSummaryDTO.java +64 -0
- src/main/java/com/dalab/policyengine/dto/PolicyImpactRequestDTO.java +211 -0
- src/main/java/com/dalab/policyengine/dto/PolicyImpactResponseDTO.java +376 -0
- src/main/java/com/dalab/policyengine/dto/PolicyInputDTO.java +80 -0
- src/main/java/com/dalab/policyengine/dto/PolicyOutputDTO.java +111 -0
- src/main/java/com/dalab/policyengine/dto/PolicyRuleDTO.java +72 -0
- src/main/java/com/dalab/policyengine/dto/PolicySummaryDTO.java +73 -0
- src/main/java/com/dalab/policyengine/event/PolicyActionEvent.java +102 -0
- src/main/java/com/dalab/policyengine/kafka/consumer/AssetChangeConsumer.java +50 -0
- src/main/java/com/dalab/policyengine/kafka/consumer/AssetChangeEventListener.java +61 -0
- src/main/java/com/dalab/policyengine/kafka/producer/PolicyActionKafkaProducer.java +54 -0
- src/main/java/com/dalab/policyengine/kafka/producer/PolicyActionProducer.java +42 -0
- src/main/java/com/dalab/policyengine/mapper/PolicyDraftMapper.java +372 -0
- src/main/java/com/dalab/policyengine/mapper/PolicyMapper.java +141 -0
- src/main/java/com/dalab/policyengine/model/EventRule.java +226 -0
- src/main/java/com/dalab/policyengine/model/EventSeverity.java +31 -0
- src/main/java/com/dalab/policyengine/model/EventSubscription.java +339 -0
- src/main/java/com/dalab/policyengine/model/EventSubscriptionStatus.java +26 -0
- src/main/java/com/dalab/policyengine/model/EventType.java +123 -0
- src/main/java/com/dalab/policyengine/model/Policy.java +171 -0
- src/main/java/com/dalab/policyengine/model/PolicyDraft.java +495 -0
- src/main/java/com/dalab/policyengine/model/PolicyDraftStatus.java +47 -0
- src/main/java/com/dalab/policyengine/model/PolicyEvaluation.java +119 -0
- src/main/java/com/dalab/policyengine/model/PolicyEvaluationStatus.java +9 -0
- src/main/java/com/dalab/policyengine/model/PolicyRule.java +137 -0
- src/main/java/com/dalab/policyengine/model/PolicyStatus.java +6 -0
- src/main/java/com/dalab/policyengine/repository/EventRuleRepository.java +86 -0
- src/main/java/com/dalab/policyengine/repository/EventSubscriptionRepository.java +100 -0
- src/main/java/com/dalab/policyengine/repository/PolicyDraftRepository.java +169 -0
Dockerfile
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM openjdk:21-jdk-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
# Install required packages
|
| 6 |
+
RUN apt-get update && apt-get install -y \
|
| 7 |
+
curl \
|
| 8 |
+
wget \
|
| 9 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 10 |
+
|
| 11 |
+
# Copy application files
|
| 12 |
+
COPY . .
|
| 13 |
+
|
| 14 |
+
# Build application (if build.gradle.kts exists)
|
| 15 |
+
RUN if [ -f "build.gradle.kts" ]; then \
|
| 16 |
+
./gradlew build -x test; \
|
| 17 |
+
fi
|
| 18 |
+
|
| 19 |
+
# Expose port
|
| 20 |
+
EXPOSE 8080
|
| 21 |
+
|
| 22 |
+
# Health check
|
| 23 |
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
| 24 |
+
CMD curl -f http://localhost:8080/actuator/health || exit 1
|
| 25 |
+
|
| 26 |
+
# Run application
|
| 27 |
+
CMD ["java", "-jar", "build/libs/da-policyengine.jar"]
|
README.md
CHANGED
|
@@ -1,10 +1,38 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
colorFrom: blue
|
| 5 |
-
colorTo:
|
| 6 |
sdk: docker
|
| 7 |
-
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: da-policyengine (dev)
|
| 3 |
+
emoji: 🔧
|
| 4 |
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
sdk: docker
|
| 7 |
+
app_port: 8080
|
| 8 |
---
|
| 9 |
|
| 10 |
+
# da-policyengine - dev Environment
|
| 11 |
+
|
| 12 |
+
This is the da-policyengine microservice deployed in the dev environment.
|
| 13 |
+
|
| 14 |
+
## Features
|
| 15 |
+
|
| 16 |
+
- RESTful API endpoints
|
| 17 |
+
- Health monitoring via Actuator
|
| 18 |
+
- JWT authentication integration
|
| 19 |
+
- PostgreSQL database connectivity
|
| 20 |
+
|
| 21 |
+
## API Documentation
|
| 22 |
+
|
| 23 |
+
Once deployed, API documentation will be available at:
|
| 24 |
+
- Swagger UI: https://huggingface.co/spaces/dalabsai/da-policyengine-dev/swagger-ui.html
|
| 25 |
+
- Health Check: https://huggingface.co/spaces/dalabsai/da-policyengine-dev/actuator/health
|
| 26 |
+
|
| 27 |
+
## Environment
|
| 28 |
+
|
| 29 |
+
- **Environment**: dev
|
| 30 |
+
- **Port**: 8080
|
| 31 |
+
- **Java Version**: 21
|
| 32 |
+
- **Framework**: Spring Boot
|
| 33 |
+
|
| 34 |
+
## Deployment
|
| 35 |
+
|
| 36 |
+
This service is automatically deployed via the DALab CI/CD pipeline.
|
| 37 |
+
|
| 38 |
+
Last updated: 2025-06-16 23:40:00
|
build.gradle.kts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// da-policyengine inherits common configuration from parent build.gradle.kts
|
| 2 |
+
// This build file adds policy-engine-specific dependencies
|
| 3 |
+
|
| 4 |
+
dependencies {
|
| 5 |
+
// Easy Rules engine for policy evaluation
|
| 6 |
+
implementation("org.jeasy:easy-rules-core:4.1.0")
|
| 7 |
+
implementation("org.jeasy:easy-rules-mvel:4.1.0")
|
| 8 |
+
|
| 9 |
+
// Additional dependencies specific to da-policyengine
|
| 10 |
+
implementation("org.springframework.cloud:spring-cloud-starter-openfeign:4.1.1")
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
// Configure main application class
|
| 14 |
+
configure<org.springframework.boot.gradle.dsl.SpringBootExtension> {
|
| 15 |
+
mainClass.set("com.dalab.policyengine.DaPolicyEngineApplication")
|
| 16 |
+
}
|
src/main/docker/Dockerfile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultra-lean container using Google Distroless
|
| 2 |
+
# Expected final size: ~120-180MB (minimal base + JRE + JAR only)
|
| 3 |
+
|
| 4 |
+
FROM gcr.io/distroless/java21-debian12:nonroot
|
| 5 |
+
|
| 6 |
+
# Set working directory
|
| 7 |
+
WORKDIR /app
|
| 8 |
+
|
| 9 |
+
# Copy JAR file
|
| 10 |
+
COPY build/libs/da-policyengine.jar app.jar
|
| 11 |
+
|
| 12 |
+
# Expose standard Spring Boot port
|
| 13 |
+
EXPOSE 8080
|
| 14 |
+
|
| 15 |
+
# Run application (distroless has no shell, so use exec form)
|
| 16 |
+
ENTRYPOINT ["java", \
|
| 17 |
+
"-XX:+UseContainerSupport", \
|
| 18 |
+
"-XX:MaxRAMPercentage=75.0", \
|
| 19 |
+
"-XX:+UseG1GC", \
|
| 20 |
+
"-XX:+UseStringDeduplication", \
|
| 21 |
+
"-Djava.security.egd=file:/dev/./urandom", \
|
| 22 |
+
"-Dspring.backgroundpreinitializer.ignore=true", \
|
| 23 |
+
"-jar", "app.jar"]
|
src/main/docker/Dockerfile.alpine-jlink
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultra-minimal Alpine + Custom JRE
|
| 2 |
+
# Expected size: ~120-160MB
|
| 3 |
+
|
| 4 |
+
# Stage 1: Create custom JRE with only needed modules
|
| 5 |
+
FROM eclipse-temurin:21-jdk-alpine as jre-builder
|
| 6 |
+
WORKDIR /app
|
| 7 |
+
|
| 8 |
+
# Analyze JAR to find required modules
|
| 9 |
+
COPY build/libs/*.jar app.jar
|
| 10 |
+
RUN jdeps --ignore-missing-deps --print-module-deps app.jar > modules.txt
|
| 11 |
+
|
| 12 |
+
# Create minimal JRE with only required modules
|
| 13 |
+
RUN jlink \
|
| 14 |
+
--add-modules $(cat modules.txt),java.logging,java.xml,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \
|
| 15 |
+
--strip-debug \
|
| 16 |
+
--no-man-pages \
|
| 17 |
+
--no-header-files \
|
| 18 |
+
--compress=2 \
|
| 19 |
+
--output /custom-jre
|
| 20 |
+
|
| 21 |
+
# Stage 2: Production image
|
| 22 |
+
FROM alpine:3.19
|
| 23 |
+
RUN apk add --no-cache tzdata && \
|
| 24 |
+
addgroup -g 1001 -S appgroup && \
|
| 25 |
+
adduser -u 1001 -S appuser -G appgroup
|
| 26 |
+
|
| 27 |
+
# Copy custom JRE
|
| 28 |
+
COPY --from=jre-builder /custom-jre /opt/java
|
| 29 |
+
ENV JAVA_HOME=/opt/java
|
| 30 |
+
ENV PATH="$JAVA_HOME/bin:$PATH"
|
| 31 |
+
|
| 32 |
+
WORKDIR /app
|
| 33 |
+
COPY build/libs/*.jar app.jar
|
| 34 |
+
RUN chown appuser:appgroup app.jar
|
| 35 |
+
|
| 36 |
+
USER appuser
|
| 37 |
+
EXPOSE 8080
|
| 38 |
+
|
| 39 |
+
ENTRYPOINT ["java", \
|
| 40 |
+
"-XX:+UseContainerSupport", \
|
| 41 |
+
"-XX:MaxRAMPercentage=70.0", \
|
| 42 |
+
"-XX:+UseG1GC", \
|
| 43 |
+
"-jar", "app.jar"]
|
src/main/docker/Dockerfile.layered
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ultra-optimized layered build using Distroless
|
| 2 |
+
# Expected size: ~180-220MB with better caching
|
| 3 |
+
|
| 4 |
+
FROM gcr.io/distroless/java21-debian12:nonroot as base
|
| 5 |
+
|
| 6 |
+
# Stage 1: Extract JAR layers for optimal caching
|
| 7 |
+
FROM eclipse-temurin:21-jdk-alpine as extractor
|
| 8 |
+
WORKDIR /app
|
| 9 |
+
COPY build/libs/*.jar app.jar
|
| 10 |
+
RUN java -Djarmode=layertools -jar app.jar extract
|
| 11 |
+
|
| 12 |
+
# Stage 2: Production image with extracted layers
|
| 13 |
+
FROM base
|
| 14 |
+
WORKDIR /app
|
| 15 |
+
|
| 16 |
+
# Copy layers in dependency order (best caching)
|
| 17 |
+
COPY --from=extractor /app/dependencies/ ./
|
| 18 |
+
COPY --from=extractor /app/spring-boot-loader/ ./
|
| 19 |
+
COPY --from=extractor /app/snapshot-dependencies/ ./
|
| 20 |
+
COPY --from=extractor /app/application/ ./
|
| 21 |
+
|
| 22 |
+
EXPOSE 8080
|
| 23 |
+
|
| 24 |
+
# Optimized JVM settings for micro-containers
|
| 25 |
+
ENTRYPOINT ["java", \
|
| 26 |
+
"-XX:+UseContainerSupport", \
|
| 27 |
+
"-XX:MaxRAMPercentage=70.0", \
|
| 28 |
+
"-XX:+UseG1GC", \
|
| 29 |
+
"-XX:+UseStringDeduplication", \
|
| 30 |
+
"-XX:+CompactStrings", \
|
| 31 |
+
"-Xshare:on", \
|
| 32 |
+
"-Djava.security.egd=file:/dev/./urandom", \
|
| 33 |
+
"-Dspring.backgroundpreinitializer.ignore=true", \
|
| 34 |
+
"org.springframework.boot.loader.JarLauncher"]
|
src/main/docker/Dockerfile.native
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# GraalVM Native Image - Ultra-fast startup, tiny size
|
| 2 |
+
# Expected size: ~50-80MB, startup <100ms
|
| 3 |
+
# Note: Requires native compilation support in Spring Boot
|
| 4 |
+
|
| 5 |
+
# Stage 1: Native compilation
|
| 6 |
+
FROM ghcr.io/graalvm/graalvm-ce:ol9-java21 as native-builder
|
| 7 |
+
WORKDIR /app
|
| 8 |
+
|
| 9 |
+
# Install native-image
|
| 10 |
+
RUN gu install native-image
|
| 11 |
+
|
| 12 |
+
# Copy source and build native executable
|
| 13 |
+
COPY . .
|
| 14 |
+
RUN ./gradlew nativeCompile
|
| 15 |
+
|
| 16 |
+
# Stage 2: Minimal runtime
|
| 17 |
+
FROM scratch
|
| 18 |
+
COPY --from=native-builder /app/build/native/nativeCompile/app /app
|
| 19 |
+
EXPOSE 8080
|
| 20 |
+
ENTRYPOINT ["/app"]
|
src/main/java/com/dalab/policyengine/DaPolicyEngineApplication.java
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine;
|
| 2 |
+
|
| 3 |
+
import org.springframework.boot.SpringApplication;
|
| 4 |
+
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
| 5 |
+
import org.springframework.cloud.openfeign.EnableFeignClients;
|
| 6 |
+
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
| 7 |
+
import org.springframework.kafka.annotation.EnableKafka;
|
| 8 |
+
import org.springframework.scheduling.annotation.EnableAsync;
|
| 9 |
+
import org.springframework.scheduling.annotation.EnableScheduling;
|
| 10 |
+
|
| 11 |
+
/**
|
| 12 |
+
* Main application class for DALab Policy Engine Service.
|
| 13 |
+
*
|
| 14 |
+
* This service handles:
|
| 15 |
+
* - Policy management and evaluation
|
| 16 |
+
* - Easy Rules engine integration
|
| 17 |
+
* - Kafka event processing for asset changes
|
| 18 |
+
* - Policy action execution and notifications
|
| 19 |
+
*
|
| 20 |
+
* @author DALab Development Team
|
| 21 |
+
* @since 1.0.0
|
| 22 |
+
*/
|
| 23 |
+
@SpringBootApplication(scanBasePackages = {
|
| 24 |
+
"com.dalab.policyengine",
|
| 25 |
+
"com.dalab.discovery.common.security" // Include common security utils
|
| 26 |
+
})
|
| 27 |
+
@EnableJpaRepositories
|
| 28 |
+
@EnableFeignClients
|
| 29 |
+
@EnableKafka
|
| 30 |
+
@EnableAsync
|
| 31 |
+
@EnableScheduling
|
| 32 |
+
public class DaPolicyEngineApplication {
|
| 33 |
+
|
| 34 |
+
public static void main(String[] args) {
|
| 35 |
+
SpringApplication.run(DaPolicyEngineApplication.class, args);
|
| 36 |
+
}
|
| 37 |
+
}
|
src/main/java/com/dalab/policyengine/common/ConflictException.java
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.common;
|
| 2 |
+
|
| 3 |
+
import org.springframework.http.HttpStatus;
|
| 4 |
+
import org.springframework.web.bind.annotation.ResponseStatus;
|
| 5 |
+
|
| 6 |
+
@ResponseStatus(HttpStatus.CONFLICT)
|
| 7 |
+
public class ConflictException extends RuntimeException {
|
| 8 |
+
public ConflictException(String message) {
|
| 9 |
+
super(message);
|
| 10 |
+
}
|
| 11 |
+
}
|
src/main/java/com/dalab/policyengine/common/ResourceNotFoundException.java
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.common;
|
| 2 |
+
|
| 3 |
+
import org.springframework.http.HttpStatus;
|
| 4 |
+
import org.springframework.web.bind.annotation.ResponseStatus;
|
| 5 |
+
|
| 6 |
+
@ResponseStatus(HttpStatus.NOT_FOUND)
|
| 7 |
+
public class ResourceNotFoundException extends RuntimeException {
|
| 8 |
+
public ResourceNotFoundException(String resourceName, String fieldName, String fieldValue) {
|
| 9 |
+
super(String.format("%s not found with %s : '%s'", resourceName, fieldName, fieldValue));
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
public ResourceNotFoundException(String message) {
|
| 13 |
+
super(message);
|
| 14 |
+
}
|
| 15 |
+
}
|
src/main/java/com/dalab/policyengine/config/OpenAPIConfiguration.java
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.config;
|
| 2 |
+
|
| 3 |
+
import org.springframework.beans.factory.annotation.Value;
|
| 4 |
+
import org.springframework.context.annotation.Bean;
|
| 5 |
+
import org.springframework.context.annotation.Configuration;
|
| 6 |
+
|
| 7 |
+
import io.swagger.v3.oas.models.OpenAPI;
|
| 8 |
+
import io.swagger.v3.oas.models.info.Info;
|
| 9 |
+
import io.swagger.v3.oas.models.info.License;
|
| 10 |
+
|
| 11 |
+
@Configuration
|
| 12 |
+
public class OpenAPIConfiguration {
|
| 13 |
+
|
| 14 |
+
@Bean
|
| 15 |
+
public OpenAPI customOpenAPI(
|
| 16 |
+
@Value("${spring.application.name}") String appName,
|
| 17 |
+
@Value("${spring.application.description:DALab Policy Engine Microservice}") String appDescription,
|
| 18 |
+
@Value("${spring.application.version:v0.0.1}") String appVersion) {
|
| 19 |
+
return new OpenAPI()
|
| 20 |
+
.info(new Info()
|
| 21 |
+
.title(appName)
|
| 22 |
+
.version(appVersion)
|
| 23 |
+
.description(appDescription)
|
| 24 |
+
.termsOfService("http://swagger.io/terms/") // Replace with actual terms
|
| 25 |
+
.license(new License().name("Apache 2.0").url("http://springdoc.org"))); // Replace with actual license
|
| 26 |
+
}
|
| 27 |
+
}
|
src/main/java/com/dalab/policyengine/config/SecurityConfiguration.java
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.config;
|
| 2 |
+
|
| 3 |
+
import org.springframework.beans.factory.annotation.Value;
|
| 4 |
+
import org.springframework.context.annotation.Bean;
|
| 5 |
+
import org.springframework.context.annotation.Configuration;
|
| 6 |
+
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
| 7 |
+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
| 8 |
+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
| 9 |
+
import org.springframework.security.config.http.SessionCreationPolicy;
|
| 10 |
+
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
| 11 |
+
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
|
| 12 |
+
import org.springframework.security.web.SecurityFilterChain;
|
| 13 |
+
|
| 14 |
+
@Configuration
|
| 15 |
+
@EnableWebSecurity
|
| 16 |
+
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
| 17 |
+
public class SecurityConfiguration {
|
| 18 |
+
|
| 19 |
+
@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
|
| 20 |
+
private String issuerUri;
|
| 21 |
+
|
| 22 |
+
@Bean
|
| 23 |
+
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
| 24 |
+
http
|
| 25 |
+
.csrf(csrf -> csrf.disable()) // Typically disable CSRF for stateless REST APIs
|
| 26 |
+
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
| 27 |
+
.authorizeHttpRequests(authz -> authz
|
| 28 |
+
// Define public endpoints if any (e.g., actuator/health, swagger-ui)
|
| 29 |
+
// .requestMatchers("/public/**").permitAll()
|
| 30 |
+
.anyRequest().authenticated() // All other requests require authentication
|
| 31 |
+
)
|
| 32 |
+
.oauth2ResourceServer(oauth2 -> oauth2
|
| 33 |
+
.jwt(jwt -> jwt.decoder(jwtDecoder()))
|
| 34 |
+
);
|
| 35 |
+
return http.build();
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
@Bean
|
| 39 |
+
public JwtDecoder jwtDecoder() {
|
| 40 |
+
// NimbusJwtDecoder automatically fetches the JWK Set URI from the issuer URI
|
| 41 |
+
// (e.g., ISSUER_URI/.well-known/openid-configuration or ISSUER_URI/protocol/openid-connect/certs)
|
| 42 |
+
return NimbusJwtDecoder.withIssuerLocation(issuerUri).build();
|
| 43 |
+
}
|
| 44 |
+
}
|
src/main/java/com/dalab/policyengine/dto/EventAnalyticsDTO.java
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.List;
|
| 5 |
+
import java.util.Map;
|
| 6 |
+
|
| 7 |
+
import com.dalab.policyengine.model.EventSeverity;
|
| 8 |
+
import com.dalab.policyengine.model.EventType;
|
| 9 |
+
|
| 10 |
+
/**
|
| 11 |
+
* DTO for Event Center analytics and metrics dashboard.
|
| 12 |
+
*/
|
| 13 |
+
public class EventAnalyticsDTO {
|
| 14 |
+
|
| 15 |
+
// Summary metrics
|
| 16 |
+
private Long totalEventsToday;
|
| 17 |
+
private Long totalEventsThisWeek;
|
| 18 |
+
private Long totalEventsThisMonth;
|
| 19 |
+
private Long totalActiveSubscriptions;
|
| 20 |
+
private Long totalUsersWithSubscriptions;
|
| 21 |
+
|
| 22 |
+
// Event distribution by type
|
| 23 |
+
private List<EventTypeCount> eventsByType;
|
| 24 |
+
|
| 25 |
+
// Event distribution by severity
|
| 26 |
+
private List<EventSeverityCount> eventsBySeverity;
|
| 27 |
+
|
| 28 |
+
// Event distribution by source service
|
| 29 |
+
private List<SourceServiceCount> eventsBySourceService;
|
| 30 |
+
|
| 31 |
+
// Top active subscriptions
|
| 32 |
+
private List<TopSubscription> topActiveSubscriptions;
|
| 33 |
+
|
| 34 |
+
// Recent event trends (hourly for last 24 hours)
|
| 35 |
+
private List<EventTrendPoint> recentTrends;
|
| 36 |
+
|
| 37 |
+
// Response time metrics
|
| 38 |
+
private ResponseTimeMetrics responseMetrics;
|
| 39 |
+
|
| 40 |
+
// Alert statistics
|
| 41 |
+
private AlertStatistics alertStats;
|
| 42 |
+
|
| 43 |
+
// Time range for this analytics report
|
| 44 |
+
private Instant fromTime;
|
| 45 |
+
private Instant toTime;
|
| 46 |
+
private Instant generatedAt;
|
| 47 |
+
|
| 48 |
+
// Constructors
|
| 49 |
+
public EventAnalyticsDTO() {
|
| 50 |
+
this.generatedAt = Instant.now();
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
public EventAnalyticsDTO(Instant fromTime, Instant toTime) {
|
| 54 |
+
this.fromTime = fromTime;
|
| 55 |
+
this.toTime = toTime;
|
| 56 |
+
this.generatedAt = Instant.now();
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
// Getters and Setters
|
| 60 |
+
|
| 61 |
+
public Long getTotalEventsToday() {
|
| 62 |
+
return totalEventsToday;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
public void setTotalEventsToday(Long totalEventsToday) {
|
| 66 |
+
this.totalEventsToday = totalEventsToday;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
public Long getTotalEventsThisWeek() {
|
| 70 |
+
return totalEventsThisWeek;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
public void setTotalEventsThisWeek(Long totalEventsThisWeek) {
|
| 74 |
+
this.totalEventsThisWeek = totalEventsThisWeek;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
public Long getTotalEventsThisMonth() {
|
| 78 |
+
return totalEventsThisMonth;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
public void setTotalEventsThisMonth(Long totalEventsThisMonth) {
|
| 82 |
+
this.totalEventsThisMonth = totalEventsThisMonth;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
public Long getTotalActiveSubscriptions() {
|
| 86 |
+
return totalActiveSubscriptions;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
public void setTotalActiveSubscriptions(Long totalActiveSubscriptions) {
|
| 90 |
+
this.totalActiveSubscriptions = totalActiveSubscriptions;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
public Long getTotalUsersWithSubscriptions() {
|
| 94 |
+
return totalUsersWithSubscriptions;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
public void setTotalUsersWithSubscriptions(Long totalUsersWithSubscriptions) {
|
| 98 |
+
this.totalUsersWithSubscriptions = totalUsersWithSubscriptions;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
public List<EventTypeCount> getEventsByType() {
|
| 102 |
+
return eventsByType;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
public void setEventsByType(List<EventTypeCount> eventsByType) {
|
| 106 |
+
this.eventsByType = eventsByType;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
public List<EventSeverityCount> getEventsBySeverity() {
|
| 110 |
+
return eventsBySeverity;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
public void setEventsBySeverity(List<EventSeverityCount> eventsBySeverity) {
|
| 114 |
+
this.eventsBySeverity = eventsBySeverity;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
public List<SourceServiceCount> getEventsBySourceService() {
|
| 118 |
+
return eventsBySourceService;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
public void setEventsBySourceService(List<SourceServiceCount> eventsBySourceService) {
|
| 122 |
+
this.eventsBySourceService = eventsBySourceService;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
public List<TopSubscription> getTopActiveSubscriptions() {
|
| 126 |
+
return topActiveSubscriptions;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
public void setTopActiveSubscriptions(List<TopSubscription> topActiveSubscriptions) {
|
| 130 |
+
this.topActiveSubscriptions = topActiveSubscriptions;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
public List<EventTrendPoint> getRecentTrends() {
|
| 134 |
+
return recentTrends;
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
public void setRecentTrends(List<EventTrendPoint> recentTrends) {
|
| 138 |
+
this.recentTrends = recentTrends;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
public ResponseTimeMetrics getResponseMetrics() {
|
| 142 |
+
return responseMetrics;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
public void setResponseMetrics(ResponseTimeMetrics responseMetrics) {
|
| 146 |
+
this.responseMetrics = responseMetrics;
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
public AlertStatistics getAlertStats() {
|
| 150 |
+
return alertStats;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
public void setAlertStats(AlertStatistics alertStats) {
|
| 154 |
+
this.alertStats = alertStats;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
public Instant getFromTime() {
|
| 158 |
+
return fromTime;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
public void setFromTime(Instant fromTime) {
|
| 162 |
+
this.fromTime = fromTime;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
public Instant getToTime() {
|
| 166 |
+
return toTime;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
public void setToTime(Instant toTime) {
|
| 170 |
+
this.toTime = toTime;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
public Instant getGeneratedAt() {
|
| 174 |
+
return generatedAt;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
public void setGeneratedAt(Instant generatedAt) {
|
| 178 |
+
this.generatedAt = generatedAt;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
@Override
|
| 182 |
+
public String toString() {
|
| 183 |
+
return "EventAnalyticsDTO{" +
|
| 184 |
+
"totalEventsToday=" + totalEventsToday +
|
| 185 |
+
", totalEventsThisWeek=" + totalEventsThisWeek +
|
| 186 |
+
", totalEventsThisMonth=" + totalEventsThisMonth +
|
| 187 |
+
", totalActiveSubscriptions=" + totalActiveSubscriptions +
|
| 188 |
+
", fromTime=" + fromTime +
|
| 189 |
+
", toTime=" + toTime +
|
| 190 |
+
", generatedAt=" + generatedAt +
|
| 191 |
+
'}';
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
// Nested classes for analytics data structures
|
| 195 |
+
|
| 196 |
+
public static class EventTypeCount {
|
| 197 |
+
private EventType eventType;
|
| 198 |
+
private Long count;
|
| 199 |
+
private Double percentage;
|
| 200 |
+
|
| 201 |
+
public EventTypeCount() {}
|
| 202 |
+
|
| 203 |
+
public EventTypeCount(EventType eventType, Long count) {
|
| 204 |
+
this.eventType = eventType;
|
| 205 |
+
this.count = count;
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
public EventType getEventType() { return eventType; }
|
| 209 |
+
public void setEventType(EventType eventType) { this.eventType = eventType; }
|
| 210 |
+
public Long getCount() { return count; }
|
| 211 |
+
public void setCount(Long count) { this.count = count; }
|
| 212 |
+
public Double getPercentage() { return percentage; }
|
| 213 |
+
public void setPercentage(Double percentage) { this.percentage = percentage; }
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
public static class EventSeverityCount {
|
| 217 |
+
private EventSeverity severity;
|
| 218 |
+
private Long count;
|
| 219 |
+
private Double percentage;
|
| 220 |
+
|
| 221 |
+
public EventSeverityCount() {}
|
| 222 |
+
|
| 223 |
+
public EventSeverityCount(EventSeverity severity, Long count) {
|
| 224 |
+
this.severity = severity;
|
| 225 |
+
this.count = count;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
public EventSeverity getSeverity() { return severity; }
|
| 229 |
+
public void setSeverity(EventSeverity severity) { this.severity = severity; }
|
| 230 |
+
public Long getCount() { return count; }
|
| 231 |
+
public void setCount(Long count) { this.count = count; }
|
| 232 |
+
public Double getPercentage() { return percentage; }
|
| 233 |
+
public void setPercentage(Double percentage) { this.percentage = percentage; }
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
public static class SourceServiceCount {
|
| 237 |
+
private String sourceService;
|
| 238 |
+
private Long count;
|
| 239 |
+
private Double percentage;
|
| 240 |
+
|
| 241 |
+
public SourceServiceCount() {}
|
| 242 |
+
|
| 243 |
+
public SourceServiceCount(String sourceService, Long count) {
|
| 244 |
+
this.sourceService = sourceService;
|
| 245 |
+
this.count = count;
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
public String getSourceService() { return sourceService; }
|
| 249 |
+
public void setSourceService(String sourceService) { this.sourceService = sourceService; }
|
| 250 |
+
public Long getCount() { return count; }
|
| 251 |
+
public void setCount(Long count) { this.count = count; }
|
| 252 |
+
public Double getPercentage() { return percentage; }
|
| 253 |
+
public void setPercentage(Double percentage) { this.percentage = percentage; }
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
public static class TopSubscription {
|
| 257 |
+
private String subscriptionName;
|
| 258 |
+
private Long eventsMatched;
|
| 259 |
+
private Long notificationsSent;
|
| 260 |
+
private String ownerName;
|
| 261 |
+
private Instant lastActivity;
|
| 262 |
+
|
| 263 |
+
public TopSubscription() {}
|
| 264 |
+
|
| 265 |
+
public TopSubscription(String subscriptionName, Long eventsMatched) {
|
| 266 |
+
this.subscriptionName = subscriptionName;
|
| 267 |
+
this.eventsMatched = eventsMatched;
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
public String getSubscriptionName() { return subscriptionName; }
|
| 271 |
+
public void setSubscriptionName(String subscriptionName) { this.subscriptionName = subscriptionName; }
|
| 272 |
+
public Long getEventsMatched() { return eventsMatched; }
|
| 273 |
+
public void setEventsMatched(Long eventsMatched) { this.eventsMatched = eventsMatched; }
|
| 274 |
+
public Long getNotificationsSent() { return notificationsSent; }
|
| 275 |
+
public void setNotificationsSent(Long notificationsSent) { this.notificationsSent = notificationsSent; }
|
| 276 |
+
public String getOwnerName() { return ownerName; }
|
| 277 |
+
public void setOwnerName(String ownerName) { this.ownerName = ownerName; }
|
| 278 |
+
public Instant getLastActivity() { return lastActivity; }
|
| 279 |
+
public void setLastActivity(Instant lastActivity) { this.lastActivity = lastActivity; }
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
public static class EventTrendPoint {
|
| 283 |
+
private Instant timestamp;
|
| 284 |
+
private Long eventCount;
|
| 285 |
+
private Long criticalCount;
|
| 286 |
+
private Long highCount;
|
| 287 |
+
private Long mediumCount;
|
| 288 |
+
private Long lowCount;
|
| 289 |
+
|
| 290 |
+
public EventTrendPoint() {}
|
| 291 |
+
|
| 292 |
+
public EventTrendPoint(Instant timestamp, Long eventCount) {
|
| 293 |
+
this.timestamp = timestamp;
|
| 294 |
+
this.eventCount = eventCount;
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
public Instant getTimestamp() { return timestamp; }
|
| 298 |
+
public void setTimestamp(Instant timestamp) { this.timestamp = timestamp; }
|
| 299 |
+
public Long getEventCount() { return eventCount; }
|
| 300 |
+
public void setEventCount(Long eventCount) { this.eventCount = eventCount; }
|
| 301 |
+
public Long getCriticalCount() { return criticalCount; }
|
| 302 |
+
public void setCriticalCount(Long criticalCount) { this.criticalCount = criticalCount; }
|
| 303 |
+
public Long getHighCount() { return highCount; }
|
| 304 |
+
public void setHighCount(Long highCount) { this.highCount = highCount; }
|
| 305 |
+
public Long getMediumCount() { return mediumCount; }
|
| 306 |
+
public void setMediumCount(Long mediumCount) { this.mediumCount = mediumCount; }
|
| 307 |
+
public Long getLowCount() { return lowCount; }
|
| 308 |
+
public void setLowCount(Long lowCount) { this.lowCount = lowCount; }
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
public static class ResponseTimeMetrics {
|
| 312 |
+
private Double averageProcessingTimeMs;
|
| 313 |
+
private Double averageNotificationTimeMs;
|
| 314 |
+
private Long totalProcessedEvents;
|
| 315 |
+
private Long failedNotifications;
|
| 316 |
+
private Double successRate;
|
| 317 |
+
|
| 318 |
+
public ResponseTimeMetrics() {}
|
| 319 |
+
|
| 320 |
+
public Double getAverageProcessingTimeMs() { return averageProcessingTimeMs; }
|
| 321 |
+
public void setAverageProcessingTimeMs(Double averageProcessingTimeMs) { this.averageProcessingTimeMs = averageProcessingTimeMs; }
|
| 322 |
+
public Double getAverageNotificationTimeMs() { return averageNotificationTimeMs; }
|
| 323 |
+
public void setAverageNotificationTimeMs(Double averageNotificationTimeMs) { this.averageNotificationTimeMs = averageNotificationTimeMs; }
|
| 324 |
+
public Long getTotalProcessedEvents() { return totalProcessedEvents; }
|
| 325 |
+
public void setTotalProcessedEvents(Long totalProcessedEvents) { this.totalProcessedEvents = totalProcessedEvents; }
|
| 326 |
+
public Long getFailedNotifications() { return failedNotifications; }
|
| 327 |
+
public void setFailedNotifications(Long failedNotifications) { this.failedNotifications = failedNotifications; }
|
| 328 |
+
public Double getSuccessRate() { return successRate; }
|
| 329 |
+
public void setSuccessRate(Double successRate) { this.successRate = successRate; }
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
public static class AlertStatistics {
|
| 333 |
+
private Long totalAlertsTriggered;
|
| 334 |
+
private Long totalNotificationsSent;
|
| 335 |
+
private Long totalActionsExecuted;
|
| 336 |
+
private Map<String, Long> alertsByChannel; // email, slack, webhook, etc.
|
| 337 |
+
|
| 338 |
+
public AlertStatistics() {}
|
| 339 |
+
|
| 340 |
+
public Long getTotalAlertsTriggered() { return totalAlertsTriggered; }
|
| 341 |
+
public void setTotalAlertsTriggered(Long totalAlertsTriggered) { this.totalAlertsTriggered = totalAlertsTriggered; }
|
| 342 |
+
public Long getTotalNotificationsSent() { return totalNotificationsSent; }
|
| 343 |
+
public void setTotalNotificationsSent(Long totalNotificationsSent) { this.totalNotificationsSent = totalNotificationsSent; }
|
| 344 |
+
public Long getTotalActionsExecuted() { return totalActionsExecuted; }
|
| 345 |
+
public void setTotalActionsExecuted(Long totalActionsExecuted) { this.totalActionsExecuted = totalActionsExecuted; }
|
| 346 |
+
public Map<String, Long> getAlertsByChannel() { return alertsByChannel; }
|
| 347 |
+
public void setAlertsByChannel(Map<String, Long> alertsByChannel) { this.alertsByChannel = alertsByChannel; }
|
| 348 |
+
}
|
| 349 |
+
}
|
src/main/java/com/dalab/policyengine/dto/EventStreamDTO.java
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
import java.util.UUID;
|
| 6 |
+
|
| 7 |
+
import com.dalab.policyengine.model.EventSeverity;
|
| 8 |
+
import com.dalab.policyengine.model.EventType;
|
| 9 |
+
|
| 10 |
+
/**
|
| 11 |
+
* DTO for streaming events in real-time to the Event Center UI.
|
| 12 |
+
*/
|
| 13 |
+
public class EventStreamDTO {
|
| 14 |
+
|
| 15 |
+
private UUID eventId;
|
| 16 |
+
private EventType eventType;
|
| 17 |
+
private EventSeverity severity;
|
| 18 |
+
private String sourceService;
|
| 19 |
+
private String title;
|
| 20 |
+
private String description;
|
| 21 |
+
private UUID assetId;
|
| 22 |
+
private String assetName;
|
| 23 |
+
private UUID policyId;
|
| 24 |
+
private String policyName;
|
| 25 |
+
private Map<String, Object> eventData;
|
| 26 |
+
private Map<String, Object> metadata;
|
| 27 |
+
private Instant timestamp;
|
| 28 |
+
private UUID userId;
|
| 29 |
+
private String userAction;
|
| 30 |
+
|
| 31 |
+
// Event processing information
|
| 32 |
+
private Boolean isProcessed;
|
| 33 |
+
private Integer matchingSubscriptionsCount;
|
| 34 |
+
private Boolean notificationSent;
|
| 35 |
+
private Boolean actionTriggered;
|
| 36 |
+
|
| 37 |
+
// Constructors
|
| 38 |
+
public EventStreamDTO() {}
|
| 39 |
+
|
| 40 |
+
public EventStreamDTO(UUID eventId, EventType eventType, EventSeverity severity, String sourceService) {
|
| 41 |
+
this.eventId = eventId;
|
| 42 |
+
this.eventType = eventType;
|
| 43 |
+
this.severity = severity;
|
| 44 |
+
this.sourceService = sourceService;
|
| 45 |
+
this.timestamp = Instant.now();
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
// Getters and Setters
|
| 49 |
+
|
| 50 |
+
public UUID getEventId() {
|
| 51 |
+
return eventId;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
public void setEventId(UUID eventId) {
|
| 55 |
+
this.eventId = eventId;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
public EventType getEventType() {
|
| 59 |
+
return eventType;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
public void setEventType(EventType eventType) {
|
| 63 |
+
this.eventType = eventType;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
public EventSeverity getSeverity() {
|
| 67 |
+
return severity;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
public void setSeverity(EventSeverity severity) {
|
| 71 |
+
this.severity = severity;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
public String getSourceService() {
|
| 75 |
+
return sourceService;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
public void setSourceService(String sourceService) {
|
| 79 |
+
this.sourceService = sourceService;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
public String getTitle() {
|
| 83 |
+
return title;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
public void setTitle(String title) {
|
| 87 |
+
this.title = title;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
public String getDescription() {
|
| 91 |
+
return description;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
public void setDescription(String description) {
|
| 95 |
+
this.description = description;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
public UUID getAssetId() {
|
| 99 |
+
return assetId;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
public void setAssetId(UUID assetId) {
|
| 103 |
+
this.assetId = assetId;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
public String getAssetName() {
|
| 107 |
+
return assetName;
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
public void setAssetName(String assetName) {
|
| 111 |
+
this.assetName = assetName;
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
public UUID getPolicyId() {
|
| 115 |
+
return policyId;
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
public void setPolicyId(UUID policyId) {
|
| 119 |
+
this.policyId = policyId;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
public String getPolicyName() {
|
| 123 |
+
return policyName;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
public void setPolicyName(String policyName) {
|
| 127 |
+
this.policyName = policyName;
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
public Map<String, Object> getEventData() {
|
| 131 |
+
return eventData;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
public void setEventData(Map<String, Object> eventData) {
|
| 135 |
+
this.eventData = eventData;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
public Map<String, Object> getMetadata() {
|
| 139 |
+
return metadata;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
public void setMetadata(Map<String, Object> metadata) {
|
| 143 |
+
this.metadata = metadata;
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
public Instant getTimestamp() {
|
| 147 |
+
return timestamp;
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
public void setTimestamp(Instant timestamp) {
|
| 151 |
+
this.timestamp = timestamp;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
public UUID getUserId() {
|
| 155 |
+
return userId;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
public void setUserId(UUID userId) {
|
| 159 |
+
this.userId = userId;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
public String getUserAction() {
|
| 163 |
+
return userAction;
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
public void setUserAction(String userAction) {
|
| 167 |
+
this.userAction = userAction;
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
public Boolean getIsProcessed() {
|
| 171 |
+
return isProcessed;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
public void setIsProcessed(Boolean isProcessed) {
|
| 175 |
+
this.isProcessed = isProcessed;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
public Integer getMatchingSubscriptionsCount() {
|
| 179 |
+
return matchingSubscriptionsCount;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
public void setMatchingSubscriptionsCount(Integer matchingSubscriptionsCount) {
|
| 183 |
+
this.matchingSubscriptionsCount = matchingSubscriptionsCount;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
public Boolean getNotificationSent() {
|
| 187 |
+
return notificationSent;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
public void setNotificationSent(Boolean notificationSent) {
|
| 191 |
+
this.notificationSent = notificationSent;
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
public Boolean getActionTriggered() {
|
| 195 |
+
return actionTriggered;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
public void setActionTriggered(Boolean actionTriggered) {
|
| 199 |
+
this.actionTriggered = actionTriggered;
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
@Override
|
| 203 |
+
public String toString() {
|
| 204 |
+
return "EventStreamDTO{" +
|
| 205 |
+
"eventId=" + eventId +
|
| 206 |
+
", eventType=" + eventType +
|
| 207 |
+
", severity=" + severity +
|
| 208 |
+
", sourceService='" + sourceService + '\'' +
|
| 209 |
+
", title='" + title + '\'' +
|
| 210 |
+
", assetId=" + assetId +
|
| 211 |
+
", policyId=" + policyId +
|
| 212 |
+
", timestamp=" + timestamp +
|
| 213 |
+
", isProcessed=" + isProcessed +
|
| 214 |
+
'}';
|
| 215 |
+
}
|
| 216 |
+
}
|
src/main/java/com/dalab/policyengine/dto/EventSubscriptionInputDTO.java
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.util.List;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
|
| 6 |
+
import jakarta.validation.constraints.NotBlank;
|
| 7 |
+
import jakarta.validation.constraints.Size;
|
| 8 |
+
|
| 9 |
+
import com.dalab.policyengine.model.EventSeverity;
|
| 10 |
+
import com.dalab.policyengine.model.EventType;
|
| 11 |
+
|
| 12 |
+
/**
|
| 13 |
+
* DTO for creating or updating event subscriptions.
|
| 14 |
+
*/
|
| 15 |
+
public class EventSubscriptionInputDTO {
|
| 16 |
+
|
| 17 |
+
@NotBlank(message = "Subscription name is required")
|
| 18 |
+
@Size(max = 255, message = "Subscription name must not exceed 255 characters")
|
| 19 |
+
private String name;
|
| 20 |
+
|
| 21 |
+
@Size(max = 1000, message = "Description must not exceed 1000 characters")
|
| 22 |
+
private String description;
|
| 23 |
+
|
| 24 |
+
/**
|
| 25 |
+
* Event types to subscribe to
|
| 26 |
+
*/
|
| 27 |
+
private List<EventType> eventTypes;
|
| 28 |
+
|
| 29 |
+
/**
|
| 30 |
+
* Event severity levels to include
|
| 31 |
+
*/
|
| 32 |
+
private List<EventSeverity> severities;
|
| 33 |
+
|
| 34 |
+
/**
|
| 35 |
+
* Source services to monitor
|
| 36 |
+
*/
|
| 37 |
+
private List<String> sourceServices;
|
| 38 |
+
|
| 39 |
+
/**
|
| 40 |
+
* Event filtering rules
|
| 41 |
+
*/
|
| 42 |
+
private List<EventRuleInputDTO> rules;
|
| 43 |
+
|
| 44 |
+
/**
|
| 45 |
+
* Notification configuration
|
| 46 |
+
* Example: { "email": true, "slack": { "channel": "#alerts", "webhook": "https://..." } }
|
| 47 |
+
*/
|
| 48 |
+
private Map<String, Object> notificationConfig;
|
| 49 |
+
|
| 50 |
+
/**
|
| 51 |
+
* Action configuration for automated responses
|
| 52 |
+
* Example: { "autoQuarantine": true, "escalateTo": "admin", "maxRetries": 3 }
|
| 53 |
+
*/
|
| 54 |
+
private Map<String, Object> actionConfig;
|
| 55 |
+
|
| 56 |
+
// Constructors
|
| 57 |
+
public EventSubscriptionInputDTO() {}
|
| 58 |
+
|
| 59 |
+
public EventSubscriptionInputDTO(String name) {
|
| 60 |
+
this.name = name;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
// Getters and Setters
|
| 64 |
+
|
| 65 |
+
public String getName() {
|
| 66 |
+
return name;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
public void setName(String name) {
|
| 70 |
+
this.name = name;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
public String getDescription() {
|
| 74 |
+
return description;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
public void setDescription(String description) {
|
| 78 |
+
this.description = description;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
public List<EventType> getEventTypes() {
|
| 82 |
+
return eventTypes;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
public void setEventTypes(List<EventType> eventTypes) {
|
| 86 |
+
this.eventTypes = eventTypes;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
public List<EventSeverity> getSeverities() {
|
| 90 |
+
return severities;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
public void setSeverities(List<EventSeverity> severities) {
|
| 94 |
+
this.severities = severities;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
public List<String> getSourceServices() {
|
| 98 |
+
return sourceServices;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
public void setSourceServices(List<String> sourceServices) {
|
| 102 |
+
this.sourceServices = sourceServices;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
public List<EventRuleInputDTO> getRules() {
|
| 106 |
+
return rules;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
public void setRules(List<EventRuleInputDTO> rules) {
|
| 110 |
+
this.rules = rules;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
public Map<String, Object> getNotificationConfig() {
|
| 114 |
+
return notificationConfig;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
public void setNotificationConfig(Map<String, Object> notificationConfig) {
|
| 118 |
+
this.notificationConfig = notificationConfig;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
public Map<String, Object> getActionConfig() {
|
| 122 |
+
return actionConfig;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
public void setActionConfig(Map<String, Object> actionConfig) {
|
| 126 |
+
this.actionConfig = actionConfig;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
@Override
|
| 130 |
+
public String toString() {
|
| 131 |
+
return "EventSubscriptionInputDTO{" +
|
| 132 |
+
"name='" + name + '\'' +
|
| 133 |
+
", description='" + description + '\'' +
|
| 134 |
+
", eventTypes=" + eventTypes +
|
| 135 |
+
", severities=" + severities +
|
| 136 |
+
", sourceServices=" + sourceServices +
|
| 137 |
+
", rulesCount=" + (rules != null ? rules.size() : 0) +
|
| 138 |
+
'}';
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
/**
|
| 142 |
+
* Nested DTO for event rules within subscription input
|
| 143 |
+
*/
|
| 144 |
+
public static class EventRuleInputDTO {
|
| 145 |
+
@NotBlank(message = "Rule name is required")
|
| 146 |
+
@Size(max = 255, message = "Rule name must not exceed 255 characters")
|
| 147 |
+
private String name;
|
| 148 |
+
|
| 149 |
+
@Size(max = 500, message = "Rule description must not exceed 500 characters")
|
| 150 |
+
private String description;
|
| 151 |
+
|
| 152 |
+
@NotBlank(message = "Rule condition is required")
|
| 153 |
+
private String condition;
|
| 154 |
+
|
| 155 |
+
private Integer priority = 1;
|
| 156 |
+
|
| 157 |
+
private Boolean enabled = true;
|
| 158 |
+
|
| 159 |
+
private Map<String, Object> parameters;
|
| 160 |
+
|
| 161 |
+
// Constructors
|
| 162 |
+
public EventRuleInputDTO() {}
|
| 163 |
+
|
| 164 |
+
public EventRuleInputDTO(String name, String condition) {
|
| 165 |
+
this.name = name;
|
| 166 |
+
this.condition = condition;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
// Getters and Setters
|
| 170 |
+
|
| 171 |
+
public String getName() {
|
| 172 |
+
return name;
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
public void setName(String name) {
|
| 176 |
+
this.name = name;
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
public String getDescription() {
|
| 180 |
+
return description;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
public void setDescription(String description) {
|
| 184 |
+
this.description = description;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
public String getCondition() {
|
| 188 |
+
return condition;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
public void setCondition(String condition) {
|
| 192 |
+
this.condition = condition;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
public Integer getPriority() {
|
| 196 |
+
return priority;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
public void setPriority(Integer priority) {
|
| 200 |
+
this.priority = priority;
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
public Boolean getEnabled() {
|
| 204 |
+
return enabled;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
public void setEnabled(Boolean enabled) {
|
| 208 |
+
this.enabled = enabled;
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
public Map<String, Object> getParameters() {
|
| 212 |
+
return parameters;
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
public void setParameters(Map<String, Object> parameters) {
|
| 216 |
+
this.parameters = parameters;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
@Override
|
| 220 |
+
public String toString() {
|
| 221 |
+
return "EventRuleInputDTO{" +
|
| 222 |
+
"name='" + name + '\'' +
|
| 223 |
+
", condition='" + condition + '\'' +
|
| 224 |
+
", priority=" + priority +
|
| 225 |
+
", enabled=" + enabled +
|
| 226 |
+
'}';
|
| 227 |
+
}
|
| 228 |
+
}
|
| 229 |
+
}
|
src/main/java/com/dalab/policyengine/dto/EventSubscriptionOutputDTO.java
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.List;
|
| 5 |
+
import java.util.Map;
|
| 6 |
+
import java.util.UUID;
|
| 7 |
+
|
| 8 |
+
import com.dalab.policyengine.model.EventSeverity;
|
| 9 |
+
import com.dalab.policyengine.model.EventSubscriptionStatus;
|
| 10 |
+
import com.dalab.policyengine.model.EventType;
|
| 11 |
+
|
| 12 |
+
/**
|
| 13 |
+
* DTO for returning event subscription information.
|
| 14 |
+
*/
|
| 15 |
+
public class EventSubscriptionOutputDTO {
|
| 16 |
+
|
| 17 |
+
private UUID id;
|
| 18 |
+
private String name;
|
| 19 |
+
private String description;
|
| 20 |
+
private UUID userId;
|
| 21 |
+
private EventSubscriptionStatus status;
|
| 22 |
+
private List<EventType> eventTypes;
|
| 23 |
+
private List<EventSeverity> severities;
|
| 24 |
+
private List<String> sourceServices;
|
| 25 |
+
private List<EventRuleOutputDTO> rules;
|
| 26 |
+
private Map<String, Object> notificationConfig;
|
| 27 |
+
private Map<String, Object> actionConfig;
|
| 28 |
+
private Instant createdAt;
|
| 29 |
+
private Instant updatedAt;
|
| 30 |
+
private UUID createdByUserId;
|
| 31 |
+
private UUID updatedByUserId;
|
| 32 |
+
|
| 33 |
+
// Statistics
|
| 34 |
+
private Long totalRulesCount;
|
| 35 |
+
private Long enabledRulesCount;
|
| 36 |
+
private Long eventsMatchedCount;
|
| 37 |
+
private Instant lastEventMatchedAt;
|
| 38 |
+
|
| 39 |
+
// Constructors
|
| 40 |
+
public EventSubscriptionOutputDTO() {}
|
| 41 |
+
|
| 42 |
+
public EventSubscriptionOutputDTO(UUID id, String name, UUID userId, EventSubscriptionStatus status) {
|
| 43 |
+
this.id = id;
|
| 44 |
+
this.name = name;
|
| 45 |
+
this.userId = userId;
|
| 46 |
+
this.status = status;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
// Getters and Setters
|
| 50 |
+
|
| 51 |
+
public UUID getId() {
|
| 52 |
+
return id;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
public void setId(UUID id) {
|
| 56 |
+
this.id = id;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
public String getName() {
|
| 60 |
+
return name;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
public void setName(String name) {
|
| 64 |
+
this.name = name;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
public String getDescription() {
|
| 68 |
+
return description;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
public void setDescription(String description) {
|
| 72 |
+
this.description = description;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
public UUID getUserId() {
|
| 76 |
+
return userId;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
public void setUserId(UUID userId) {
|
| 80 |
+
this.userId = userId;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
public EventSubscriptionStatus getStatus() {
|
| 84 |
+
return status;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
public void setStatus(EventSubscriptionStatus status) {
|
| 88 |
+
this.status = status;
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
public List<EventType> getEventTypes() {
|
| 92 |
+
return eventTypes;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
public void setEventTypes(List<EventType> eventTypes) {
|
| 96 |
+
this.eventTypes = eventTypes;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
public List<EventSeverity> getSeverities() {
|
| 100 |
+
return severities;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
public void setSeverities(List<EventSeverity> severities) {
|
| 104 |
+
this.severities = severities;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
public List<String> getSourceServices() {
|
| 108 |
+
return sourceServices;
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
public void setSourceServices(List<String> sourceServices) {
|
| 112 |
+
this.sourceServices = sourceServices;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
public List<EventRuleOutputDTO> getRules() {
|
| 116 |
+
return rules;
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
public void setRules(List<EventRuleOutputDTO> rules) {
|
| 120 |
+
this.rules = rules;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
public Map<String, Object> getNotificationConfig() {
|
| 124 |
+
return notificationConfig;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
public void setNotificationConfig(Map<String, Object> notificationConfig) {
|
| 128 |
+
this.notificationConfig = notificationConfig;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
public Map<String, Object> getActionConfig() {
|
| 132 |
+
return actionConfig;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
public void setActionConfig(Map<String, Object> actionConfig) {
|
| 136 |
+
this.actionConfig = actionConfig;
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
public Instant getCreatedAt() {
|
| 140 |
+
return createdAt;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
public void setCreatedAt(Instant createdAt) {
|
| 144 |
+
this.createdAt = createdAt;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
public Instant getUpdatedAt() {
|
| 148 |
+
return updatedAt;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 152 |
+
this.updatedAt = updatedAt;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
public UUID getCreatedByUserId() {
|
| 156 |
+
return createdByUserId;
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
public void setCreatedByUserId(UUID createdByUserId) {
|
| 160 |
+
this.createdByUserId = createdByUserId;
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
public UUID getUpdatedByUserId() {
|
| 164 |
+
return updatedByUserId;
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
public void setUpdatedByUserId(UUID updatedByUserId) {
|
| 168 |
+
this.updatedByUserId = updatedByUserId;
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
public Long getTotalRulesCount() {
|
| 172 |
+
return totalRulesCount;
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
public void setTotalRulesCount(Long totalRulesCount) {
|
| 176 |
+
this.totalRulesCount = totalRulesCount;
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
public Long getEnabledRulesCount() {
|
| 180 |
+
return enabledRulesCount;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
public void setEnabledRulesCount(Long enabledRulesCount) {
|
| 184 |
+
this.enabledRulesCount = enabledRulesCount;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
public Long getEventsMatchedCount() {
|
| 188 |
+
return eventsMatchedCount;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
public void setEventsMatchedCount(Long eventsMatchedCount) {
|
| 192 |
+
this.eventsMatchedCount = eventsMatchedCount;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
public Instant getLastEventMatchedAt() {
|
| 196 |
+
return lastEventMatchedAt;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
public void setLastEventMatchedAt(Instant lastEventMatchedAt) {
|
| 200 |
+
this.lastEventMatchedAt = lastEventMatchedAt;
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
@Override
|
| 204 |
+
public String toString() {
|
| 205 |
+
return "EventSubscriptionOutputDTO{" +
|
| 206 |
+
"id=" + id +
|
| 207 |
+
", name='" + name + '\'' +
|
| 208 |
+
", userId=" + userId +
|
| 209 |
+
", status=" + status +
|
| 210 |
+
", eventTypes=" + eventTypes +
|
| 211 |
+
", severities=" + severities +
|
| 212 |
+
", rulesCount=" + totalRulesCount +
|
| 213 |
+
", eventsMatchedCount=" + eventsMatchedCount +
|
| 214 |
+
'}';
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
/**
|
| 218 |
+
* Nested DTO for event rules within subscription output
|
| 219 |
+
*/
|
| 220 |
+
public static class EventRuleOutputDTO {
|
| 221 |
+
private UUID id;
|
| 222 |
+
private String name;
|
| 223 |
+
private String description;
|
| 224 |
+
private String condition;
|
| 225 |
+
private Integer priority;
|
| 226 |
+
private Boolean enabled;
|
| 227 |
+
private Map<String, Object> parameters;
|
| 228 |
+
private Instant createdAt;
|
| 229 |
+
private Instant updatedAt;
|
| 230 |
+
private UUID createdByUserId;
|
| 231 |
+
private UUID updatedByUserId;
|
| 232 |
+
|
| 233 |
+
// Constructors
|
| 234 |
+
public EventRuleOutputDTO() {}
|
| 235 |
+
|
| 236 |
+
public EventRuleOutputDTO(UUID id, String name, String condition) {
|
| 237 |
+
this.id = id;
|
| 238 |
+
this.name = name;
|
| 239 |
+
this.condition = condition;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
// Getters and Setters
|
| 243 |
+
|
| 244 |
+
public UUID getId() {
|
| 245 |
+
return id;
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
public void setId(UUID id) {
|
| 249 |
+
this.id = id;
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
public String getName() {
|
| 253 |
+
return name;
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
public void setName(String name) {
|
| 257 |
+
this.name = name;
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
public String getDescription() {
|
| 261 |
+
return description;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
public void setDescription(String description) {
|
| 265 |
+
this.description = description;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
public String getCondition() {
|
| 269 |
+
return condition;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
public void setCondition(String condition) {
|
| 273 |
+
this.condition = condition;
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
public Integer getPriority() {
|
| 277 |
+
return priority;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
public void setPriority(Integer priority) {
|
| 281 |
+
this.priority = priority;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
public Boolean getEnabled() {
|
| 285 |
+
return enabled;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
public void setEnabled(Boolean enabled) {
|
| 289 |
+
this.enabled = enabled;
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
public Map<String, Object> getParameters() {
|
| 293 |
+
return parameters;
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
public void setParameters(Map<String, Object> parameters) {
|
| 297 |
+
this.parameters = parameters;
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
public Instant getCreatedAt() {
|
| 301 |
+
return createdAt;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
public void setCreatedAt(Instant createdAt) {
|
| 305 |
+
this.createdAt = createdAt;
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
public Instant getUpdatedAt() {
|
| 309 |
+
return updatedAt;
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 313 |
+
this.updatedAt = updatedAt;
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
public UUID getCreatedByUserId() {
|
| 317 |
+
return createdByUserId;
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
public void setCreatedByUserId(UUID createdByUserId) {
|
| 321 |
+
this.createdByUserId = createdByUserId;
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
public UUID getUpdatedByUserId() {
|
| 325 |
+
return updatedByUserId;
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
public void setUpdatedByUserId(UUID updatedByUserId) {
|
| 329 |
+
this.updatedByUserId = updatedByUserId;
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
@Override
|
| 333 |
+
public String toString() {
|
| 334 |
+
return "EventRuleOutputDTO{" +
|
| 335 |
+
"id=" + id +
|
| 336 |
+
", name='" + name + '\'' +
|
| 337 |
+
", condition='" + condition + '\'' +
|
| 338 |
+
", priority=" + priority +
|
| 339 |
+
", enabled=" + enabled +
|
| 340 |
+
'}';
|
| 341 |
+
}
|
| 342 |
+
}
|
| 343 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyDraftActionDTO.java
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import jakarta.validation.constraints.NotBlank;
|
| 4 |
+
import jakarta.validation.constraints.Size;
|
| 5 |
+
|
| 6 |
+
/**
|
| 7 |
+
* DTO for policy draft workflow actions (submit, approve, reject, etc.).
|
| 8 |
+
* Used for all workflow transition operations.
|
| 9 |
+
*/
|
| 10 |
+
public class PolicyDraftActionDTO {
|
| 11 |
+
|
| 12 |
+
/**
|
| 13 |
+
* The action to perform (SUBMIT, APPROVE, REJECT, REQUEST_CHANGES, ARCHIVE).
|
| 14 |
+
*/
|
| 15 |
+
@NotBlank(message = "Action type is required")
|
| 16 |
+
private String actionType;
|
| 17 |
+
|
| 18 |
+
/**
|
| 19 |
+
* Comment or reason for the action (required for rejection and optional for others).
|
| 20 |
+
*/
|
| 21 |
+
@Size(max = 2000, message = "Comment must not exceed 2000 characters")
|
| 22 |
+
private String comment;
|
| 23 |
+
|
| 24 |
+
/**
|
| 25 |
+
* Priority level if submitting or approving (HIGH, MEDIUM, LOW).
|
| 26 |
+
*/
|
| 27 |
+
private String priority;
|
| 28 |
+
|
| 29 |
+
/**
|
| 30 |
+
* Target implementation date if approving for publication.
|
| 31 |
+
*/
|
| 32 |
+
private String targetImplementationDate;
|
| 33 |
+
|
| 34 |
+
/**
|
| 35 |
+
* Additional metadata for the action.
|
| 36 |
+
*/
|
| 37 |
+
private String metadata;
|
| 38 |
+
|
| 39 |
+
// Constructors
|
| 40 |
+
public PolicyDraftActionDTO() {}
|
| 41 |
+
|
| 42 |
+
public PolicyDraftActionDTO(String actionType) {
|
| 43 |
+
this.actionType = actionType;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
public PolicyDraftActionDTO(String actionType, String comment) {
|
| 47 |
+
this.actionType = actionType;
|
| 48 |
+
this.comment = comment;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
// Getters and Setters
|
| 52 |
+
public String getActionType() {
|
| 53 |
+
return actionType;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
public void setActionType(String actionType) {
|
| 57 |
+
this.actionType = actionType;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
public String getComment() {
|
| 61 |
+
return comment;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
public void setComment(String comment) {
|
| 65 |
+
this.comment = comment;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
public String getPriority() {
|
| 69 |
+
return priority;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
public void setPriority(String priority) {
|
| 73 |
+
this.priority = priority;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
public String getTargetImplementationDate() {
|
| 77 |
+
return targetImplementationDate;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
public void setTargetImplementationDate(String targetImplementationDate) {
|
| 81 |
+
this.targetImplementationDate = targetImplementationDate;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
public String getMetadata() {
|
| 85 |
+
return metadata;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
public void setMetadata(String metadata) {
|
| 89 |
+
this.metadata = metadata;
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
/**
|
| 94 |
+
* DTO for bulk operations on multiple policy drafts.
|
| 95 |
+
*/
|
| 96 |
+
class PolicyDraftBulkActionDTO {
|
| 97 |
+
|
| 98 |
+
/**
|
| 99 |
+
* List of draft IDs to perform action on.
|
| 100 |
+
*/
|
| 101 |
+
@NotBlank(message = "Draft IDs are required")
|
| 102 |
+
private java.util.List<java.util.UUID> draftIds;
|
| 103 |
+
|
| 104 |
+
/**
|
| 105 |
+
* The action to perform on all selected drafts.
|
| 106 |
+
*/
|
| 107 |
+
@NotBlank(message = "Action type is required")
|
| 108 |
+
private String actionType;
|
| 109 |
+
|
| 110 |
+
/**
|
| 111 |
+
* Comment for the bulk action.
|
| 112 |
+
*/
|
| 113 |
+
@Size(max = 1000, message = "Comment must not exceed 1000 characters")
|
| 114 |
+
private String comment;
|
| 115 |
+
|
| 116 |
+
// Constructors
|
| 117 |
+
public PolicyDraftBulkActionDTO() {}
|
| 118 |
+
|
| 119 |
+
// Getters and Setters
|
| 120 |
+
public java.util.List<java.util.UUID> getDraftIds() {
|
| 121 |
+
return draftIds;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
public void setDraftIds(java.util.List<java.util.UUID> draftIds) {
|
| 125 |
+
this.draftIds = draftIds;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
public String getActionType() {
|
| 129 |
+
return actionType;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
public void setActionType(String actionType) {
|
| 133 |
+
this.actionType = actionType;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
public String getComment() {
|
| 137 |
+
return comment;
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
public void setComment(String comment) {
|
| 141 |
+
this.comment = comment;
|
| 142 |
+
}
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
/**
|
| 146 |
+
* DTO for policy draft summary information (for list views).
|
| 147 |
+
*/
|
| 148 |
+
class PolicyDraftSummaryDTO {
|
| 149 |
+
|
| 150 |
+
private java.util.UUID id;
|
| 151 |
+
private String name;
|
| 152 |
+
private String status;
|
| 153 |
+
private Integer version;
|
| 154 |
+
private String priority;
|
| 155 |
+
private String category;
|
| 156 |
+
private java.time.Instant createdAt;
|
| 157 |
+
private java.time.Instant updatedAt;
|
| 158 |
+
private java.util.UUID createdByUserId;
|
| 159 |
+
private java.time.Instant targetImplementationDate;
|
| 160 |
+
private int reviewCommentsCount;
|
| 161 |
+
private boolean isOverdue;
|
| 162 |
+
|
| 163 |
+
// Constructors
|
| 164 |
+
public PolicyDraftSummaryDTO() {}
|
| 165 |
+
|
| 166 |
+
public PolicyDraftSummaryDTO(java.util.UUID id, String name, String status) {
|
| 167 |
+
this.id = id;
|
| 168 |
+
this.name = name;
|
| 169 |
+
this.status = status;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
// Getters and Setters
|
| 173 |
+
public java.util.UUID getId() {
|
| 174 |
+
return id;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
public void setId(java.util.UUID id) {
|
| 178 |
+
this.id = id;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
public String getName() {
|
| 182 |
+
return name;
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
public void setName(String name) {
|
| 186 |
+
this.name = name;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
public String getStatus() {
|
| 190 |
+
return status;
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
public void setStatus(String status) {
|
| 194 |
+
this.status = status;
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
public Integer getVersion() {
|
| 198 |
+
return version;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
public void setVersion(Integer version) {
|
| 202 |
+
this.version = version;
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
public String getPriority() {
|
| 206 |
+
return priority;
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
public void setPriority(String priority) {
|
| 210 |
+
this.priority = priority;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
public String getCategory() {
|
| 214 |
+
return category;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
public void setCategory(String category) {
|
| 218 |
+
this.category = category;
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
public java.time.Instant getCreatedAt() {
|
| 222 |
+
return createdAt;
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
public void setCreatedAt(java.time.Instant createdAt) {
|
| 226 |
+
this.createdAt = createdAt;
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
public java.time.Instant getUpdatedAt() {
|
| 230 |
+
return updatedAt;
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
public void setUpdatedAt(java.time.Instant updatedAt) {
|
| 234 |
+
this.updatedAt = updatedAt;
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
public java.util.UUID getCreatedByUserId() {
|
| 238 |
+
return createdByUserId;
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
public void setCreatedByUserId(java.util.UUID createdByUserId) {
|
| 242 |
+
this.createdByUserId = createdByUserId;
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
public java.time.Instant getTargetImplementationDate() {
|
| 246 |
+
return targetImplementationDate;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
public void setTargetImplementationDate(java.time.Instant targetImplementationDate) {
|
| 250 |
+
this.targetImplementationDate = targetImplementationDate;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
public int getReviewCommentsCount() {
|
| 254 |
+
return reviewCommentsCount;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
public void setReviewCommentsCount(int reviewCommentsCount) {
|
| 258 |
+
this.reviewCommentsCount = reviewCommentsCount;
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
public boolean isOverdue() {
|
| 262 |
+
return isOverdue;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
public void setOverdue(boolean overdue) {
|
| 266 |
+
isOverdue = overdue;
|
| 267 |
+
}
|
| 268 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyDraftInputDTO.java
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.List;
|
| 5 |
+
import java.util.Map;
|
| 6 |
+
import java.util.UUID;
|
| 7 |
+
|
| 8 |
+
import jakarta.validation.constraints.NotBlank;
|
| 9 |
+
import jakarta.validation.constraints.Size;
|
| 10 |
+
|
| 11 |
+
/**
|
| 12 |
+
* DTO for creating and updating policy drafts.
|
| 13 |
+
* Contains all information needed for draft management and workflow.
|
| 14 |
+
*/
|
| 15 |
+
public class PolicyDraftInputDTO {
|
| 16 |
+
|
| 17 |
+
/**
|
| 18 |
+
* Name of the policy (must be unique when published).
|
| 19 |
+
*/
|
| 20 |
+
@NotBlank(message = "Policy name is required")
|
| 21 |
+
@Size(max = 255, message = "Policy name must not exceed 255 characters")
|
| 22 |
+
private String name;
|
| 23 |
+
|
| 24 |
+
/**
|
| 25 |
+
* Detailed description of the policy's purpose and scope.
|
| 26 |
+
*/
|
| 27 |
+
@Size(max = 2000, message = "Description must not exceed 2000 characters")
|
| 28 |
+
private String description;
|
| 29 |
+
|
| 30 |
+
/**
|
| 31 |
+
* Reference to the published policy if this is an update.
|
| 32 |
+
*/
|
| 33 |
+
private UUID basePolicyId;
|
| 34 |
+
|
| 35 |
+
/**
|
| 36 |
+
* MVEL condition logic for the policy evaluation.
|
| 37 |
+
*/
|
| 38 |
+
private String conditionLogic;
|
| 39 |
+
|
| 40 |
+
/**
|
| 41 |
+
* JSON representation of policy rules structure.
|
| 42 |
+
*/
|
| 43 |
+
private List<Map<String, Object>> rulesDefinition;
|
| 44 |
+
|
| 45 |
+
/**
|
| 46 |
+
* JSON representation of actions to be taken when policy is triggered.
|
| 47 |
+
*/
|
| 48 |
+
private Map<String, Object> actions;
|
| 49 |
+
|
| 50 |
+
/**
|
| 51 |
+
* Change summary describing what was modified in this version.
|
| 52 |
+
*/
|
| 53 |
+
@Size(max = 1000, message = "Change summary must not exceed 1000 characters")
|
| 54 |
+
private String changeSummary;
|
| 55 |
+
|
| 56 |
+
/**
|
| 57 |
+
* Justification for the policy changes or creation.
|
| 58 |
+
*/
|
| 59 |
+
@Size(max = 2000, message = "Justification must not exceed 2000 characters")
|
| 60 |
+
private String justification;
|
| 61 |
+
|
| 62 |
+
/**
|
| 63 |
+
* Expected impact of implementing this policy.
|
| 64 |
+
*/
|
| 65 |
+
@Size(max = 1000, message = "Expected impact must not exceed 1000 characters")
|
| 66 |
+
private String expectedImpact;
|
| 67 |
+
|
| 68 |
+
/**
|
| 69 |
+
* Target implementation date for the policy.
|
| 70 |
+
*/
|
| 71 |
+
private Instant targetImplementationDate;
|
| 72 |
+
|
| 73 |
+
/**
|
| 74 |
+
* Priority level for policy implementation.
|
| 75 |
+
*/
|
| 76 |
+
private String priority = "MEDIUM";
|
| 77 |
+
|
| 78 |
+
/**
|
| 79 |
+
* Business category or domain this policy applies to.
|
| 80 |
+
*/
|
| 81 |
+
@Size(max = 100, message = "Category must not exceed 100 characters")
|
| 82 |
+
private String category;
|
| 83 |
+
|
| 84 |
+
/**
|
| 85 |
+
* Tags for categorization and searchability.
|
| 86 |
+
*/
|
| 87 |
+
private List<String> tags;
|
| 88 |
+
|
| 89 |
+
/**
|
| 90 |
+
* Stakeholders who should be notified about this policy.
|
| 91 |
+
*/
|
| 92 |
+
private List<UUID> stakeholders;
|
| 93 |
+
|
| 94 |
+
/**
|
| 95 |
+
* Additional metadata for workflow management.
|
| 96 |
+
*/
|
| 97 |
+
private Map<String, Object> workflowMetadata;
|
| 98 |
+
|
| 99 |
+
// Constructors
|
| 100 |
+
public PolicyDraftInputDTO() {}
|
| 101 |
+
|
| 102 |
+
public PolicyDraftInputDTO(String name, String description) {
|
| 103 |
+
this.name = name;
|
| 104 |
+
this.description = description;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
// Getters and Setters
|
| 108 |
+
public String getName() {
|
| 109 |
+
return name;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
public void setName(String name) {
|
| 113 |
+
this.name = name;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
public String getDescription() {
|
| 117 |
+
return description;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
public void setDescription(String description) {
|
| 121 |
+
this.description = description;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
public UUID getBasePolicyId() {
|
| 125 |
+
return basePolicyId;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
public void setBasePolicyId(UUID basePolicyId) {
|
| 129 |
+
this.basePolicyId = basePolicyId;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
public String getConditionLogic() {
|
| 133 |
+
return conditionLogic;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
public void setConditionLogic(String conditionLogic) {
|
| 137 |
+
this.conditionLogic = conditionLogic;
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
public List<Map<String, Object>> getRulesDefinition() {
|
| 141 |
+
return rulesDefinition;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
public void setRulesDefinition(List<Map<String, Object>> rulesDefinition) {
|
| 145 |
+
this.rulesDefinition = rulesDefinition;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
public Map<String, Object> getActions() {
|
| 149 |
+
return actions;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
public void setActions(Map<String, Object> actions) {
|
| 153 |
+
this.actions = actions;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
public String getChangeSummary() {
|
| 157 |
+
return changeSummary;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
public void setChangeSummary(String changeSummary) {
|
| 161 |
+
this.changeSummary = changeSummary;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
public String getJustification() {
|
| 165 |
+
return justification;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
public void setJustification(String justification) {
|
| 169 |
+
this.justification = justification;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
public String getExpectedImpact() {
|
| 173 |
+
return expectedImpact;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
public void setExpectedImpact(String expectedImpact) {
|
| 177 |
+
this.expectedImpact = expectedImpact;
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
public Instant getTargetImplementationDate() {
|
| 181 |
+
return targetImplementationDate;
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
public void setTargetImplementationDate(Instant targetImplementationDate) {
|
| 185 |
+
this.targetImplementationDate = targetImplementationDate;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
public String getPriority() {
|
| 189 |
+
return priority;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
public void setPriority(String priority) {
|
| 193 |
+
this.priority = priority;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
public String getCategory() {
|
| 197 |
+
return category;
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
public void setCategory(String category) {
|
| 201 |
+
this.category = category;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
public List<String> getTags() {
|
| 205 |
+
return tags;
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
public void setTags(List<String> tags) {
|
| 209 |
+
this.tags = tags;
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
public List<UUID> getStakeholders() {
|
| 213 |
+
return stakeholders;
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
public void setStakeholders(List<UUID> stakeholders) {
|
| 217 |
+
this.stakeholders = stakeholders;
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
public Map<String, Object> getWorkflowMetadata() {
|
| 221 |
+
return workflowMetadata;
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
public void setWorkflowMetadata(Map<String, Object> workflowMetadata) {
|
| 225 |
+
this.workflowMetadata = workflowMetadata;
|
| 226 |
+
}
|
| 227 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyDraftOutputDTO.java
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.List;
|
| 5 |
+
import java.util.Map;
|
| 6 |
+
import java.util.UUID;
|
| 7 |
+
|
| 8 |
+
/**
|
| 9 |
+
* DTO for returning policy draft information including workflow status and audit trail.
|
| 10 |
+
* Contains comprehensive information for UI display and workflow management.
|
| 11 |
+
*/
|
| 12 |
+
public class PolicyDraftOutputDTO {
|
| 13 |
+
|
| 14 |
+
private UUID id;
|
| 15 |
+
private String name;
|
| 16 |
+
private String description;
|
| 17 |
+
private String status;
|
| 18 |
+
private Integer version;
|
| 19 |
+
private UUID basePolicyId;
|
| 20 |
+
private String conditionLogic;
|
| 21 |
+
private List<Map<String, Object>> rulesDefinition;
|
| 22 |
+
private Map<String, Object> actions;
|
| 23 |
+
private String changeSummary;
|
| 24 |
+
private String justification;
|
| 25 |
+
private String expectedImpact;
|
| 26 |
+
private Instant targetImplementationDate;
|
| 27 |
+
private String priority;
|
| 28 |
+
private String category;
|
| 29 |
+
private List<String> tags;
|
| 30 |
+
private List<UUID> stakeholders;
|
| 31 |
+
private Map<String, Object> approvalMetadata;
|
| 32 |
+
private List<Map<String, Object>> reviewComments;
|
| 33 |
+
|
| 34 |
+
// Audit trail information
|
| 35 |
+
private Instant createdAt;
|
| 36 |
+
private Instant updatedAt;
|
| 37 |
+
private UUID createdByUserId;
|
| 38 |
+
private UUID updatedByUserId;
|
| 39 |
+
private Instant submittedAt;
|
| 40 |
+
private UUID submittedByUserId;
|
| 41 |
+
private Instant approvedAt;
|
| 42 |
+
private UUID approvedByUserId;
|
| 43 |
+
private Instant rejectedAt;
|
| 44 |
+
private UUID rejectedByUserId;
|
| 45 |
+
private Instant publishedAt;
|
| 46 |
+
private UUID publishedByUserId;
|
| 47 |
+
|
| 48 |
+
// Enhanced workflow information
|
| 49 |
+
private WorkflowStatusDTO workflowStatus;
|
| 50 |
+
private List<WorkflowActionDTO> availableActions;
|
| 51 |
+
|
| 52 |
+
// Constructors
|
| 53 |
+
public PolicyDraftOutputDTO() {}
|
| 54 |
+
|
| 55 |
+
public PolicyDraftOutputDTO(UUID id, String name, String status) {
|
| 56 |
+
this.id = id;
|
| 57 |
+
this.name = name;
|
| 58 |
+
this.status = status;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
// Getters and Setters
|
| 62 |
+
public UUID getId() {
|
| 63 |
+
return id;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
public void setId(UUID id) {
|
| 67 |
+
this.id = id;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
public String getName() {
|
| 71 |
+
return name;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
public void setName(String name) {
|
| 75 |
+
this.name = name;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
public String getDescription() {
|
| 79 |
+
return description;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
public void setDescription(String description) {
|
| 83 |
+
this.description = description;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
public String getStatus() {
|
| 87 |
+
return status;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
public void setStatus(String status) {
|
| 91 |
+
this.status = status;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
public Integer getVersion() {
|
| 95 |
+
return version;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
public void setVersion(Integer version) {
|
| 99 |
+
this.version = version;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
public UUID getBasePolicyId() {
|
| 103 |
+
return basePolicyId;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
public void setBasePolicyId(UUID basePolicyId) {
|
| 107 |
+
this.basePolicyId = basePolicyId;
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
public String getConditionLogic() {
|
| 111 |
+
return conditionLogic;
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
public void setConditionLogic(String conditionLogic) {
|
| 115 |
+
this.conditionLogic = conditionLogic;
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
public List<Map<String, Object>> getRulesDefinition() {
|
| 119 |
+
return rulesDefinition;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
public void setRulesDefinition(List<Map<String, Object>> rulesDefinition) {
|
| 123 |
+
this.rulesDefinition = rulesDefinition;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
public Map<String, Object> getActions() {
|
| 127 |
+
return actions;
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
public void setActions(Map<String, Object> actions) {
|
| 131 |
+
this.actions = actions;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
public String getChangeSummary() {
|
| 135 |
+
return changeSummary;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
public void setChangeSummary(String changeSummary) {
|
| 139 |
+
this.changeSummary = changeSummary;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
public String getJustification() {
|
| 143 |
+
return justification;
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
public void setJustification(String justification) {
|
| 147 |
+
this.justification = justification;
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
public String getExpectedImpact() {
|
| 151 |
+
return expectedImpact;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
public void setExpectedImpact(String expectedImpact) {
|
| 155 |
+
this.expectedImpact = expectedImpact;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
public Instant getTargetImplementationDate() {
|
| 159 |
+
return targetImplementationDate;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
public void setTargetImplementationDate(Instant targetImplementationDate) {
|
| 163 |
+
this.targetImplementationDate = targetImplementationDate;
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
public String getPriority() {
|
| 167 |
+
return priority;
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
public void setPriority(String priority) {
|
| 171 |
+
this.priority = priority;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
public String getCategory() {
|
| 175 |
+
return category;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
public void setCategory(String category) {
|
| 179 |
+
this.category = category;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
public List<String> getTags() {
|
| 183 |
+
return tags;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
public void setTags(List<String> tags) {
|
| 187 |
+
this.tags = tags;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
public List<UUID> getStakeholders() {
|
| 191 |
+
return stakeholders;
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
public void setStakeholders(List<UUID> stakeholders) {
|
| 195 |
+
this.stakeholders = stakeholders;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
public Map<String, Object> getApprovalMetadata() {
|
| 199 |
+
return approvalMetadata;
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
public void setApprovalMetadata(Map<String, Object> approvalMetadata) {
|
| 203 |
+
this.approvalMetadata = approvalMetadata;
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
public List<Map<String, Object>> getReviewComments() {
|
| 207 |
+
return reviewComments;
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
public void setReviewComments(List<Map<String, Object>> reviewComments) {
|
| 211 |
+
this.reviewComments = reviewComments;
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
public Instant getCreatedAt() {
|
| 215 |
+
return createdAt;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
public void setCreatedAt(Instant createdAt) {
|
| 219 |
+
this.createdAt = createdAt;
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
public Instant getUpdatedAt() {
|
| 223 |
+
return updatedAt;
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 227 |
+
this.updatedAt = updatedAt;
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
public UUID getCreatedByUserId() {
|
| 231 |
+
return createdByUserId;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
public void setCreatedByUserId(UUID createdByUserId) {
|
| 235 |
+
this.createdByUserId = createdByUserId;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
public UUID getUpdatedByUserId() {
|
| 239 |
+
return updatedByUserId;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
public void setUpdatedByUserId(UUID updatedByUserId) {
|
| 243 |
+
this.updatedByUserId = updatedByUserId;
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
public Instant getSubmittedAt() {
|
| 247 |
+
return submittedAt;
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
public void setSubmittedAt(Instant submittedAt) {
|
| 251 |
+
this.submittedAt = submittedAt;
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
public UUID getSubmittedByUserId() {
|
| 255 |
+
return submittedByUserId;
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
public void setSubmittedByUserId(UUID submittedByUserId) {
|
| 259 |
+
this.submittedByUserId = submittedByUserId;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
public Instant getApprovedAt() {
|
| 263 |
+
return approvedAt;
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
public void setApprovedAt(Instant approvedAt) {
|
| 267 |
+
this.approvedAt = approvedAt;
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
public UUID getApprovedByUserId() {
|
| 271 |
+
return approvedByUserId;
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
public void setApprovedByUserId(UUID approvedByUserId) {
|
| 275 |
+
this.approvedByUserId = approvedByUserId;
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
public Instant getRejectedAt() {
|
| 279 |
+
return rejectedAt;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
public void setRejectedAt(Instant rejectedAt) {
|
| 283 |
+
this.rejectedAt = rejectedAt;
|
| 284 |
+
}
|
| 285 |
+
|
| 286 |
+
public UUID getRejectedByUserId() {
|
| 287 |
+
return rejectedByUserId;
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
public void setRejectedByUserId(UUID rejectedByUserId) {
|
| 291 |
+
this.rejectedByUserId = rejectedByUserId;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
public Instant getPublishedAt() {
|
| 295 |
+
return publishedAt;
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
public void setPublishedAt(Instant publishedAt) {
|
| 299 |
+
this.publishedAt = publishedAt;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
public UUID getPublishedByUserId() {
|
| 303 |
+
return publishedByUserId;
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
public void setPublishedByUserId(UUID publishedByUserId) {
|
| 307 |
+
this.publishedByUserId = publishedByUserId;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
public WorkflowStatusDTO getWorkflowStatus() {
|
| 311 |
+
return workflowStatus;
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
public void setWorkflowStatus(WorkflowStatusDTO workflowStatus) {
|
| 315 |
+
this.workflowStatus = workflowStatus;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
public List<WorkflowActionDTO> getAvailableActions() {
|
| 319 |
+
return availableActions;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
public void setAvailableActions(List<WorkflowActionDTO> availableActions) {
|
| 323 |
+
this.availableActions = availableActions;
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
/**
|
| 327 |
+
* Nested DTO for workflow status information.
|
| 328 |
+
*/
|
| 329 |
+
public static class WorkflowStatusDTO {
|
| 330 |
+
private String currentStage;
|
| 331 |
+
private String statusDescription;
|
| 332 |
+
private List<String> nextPossibleStates;
|
| 333 |
+
private boolean canEdit;
|
| 334 |
+
private boolean canSubmit;
|
| 335 |
+
private boolean canApprove;
|
| 336 |
+
private boolean canReject;
|
| 337 |
+
private boolean canPublish;
|
| 338 |
+
private String stageColor; // For UI status indicators
|
| 339 |
+
private Integer daysInCurrentStatus;
|
| 340 |
+
|
| 341 |
+
// Constructors, getters, and setters
|
| 342 |
+
public WorkflowStatusDTO() {}
|
| 343 |
+
|
| 344 |
+
public String getCurrentStage() { return currentStage; }
|
| 345 |
+
public void setCurrentStage(String currentStage) { this.currentStage = currentStage; }
|
| 346 |
+
|
| 347 |
+
public String getStatusDescription() { return statusDescription; }
|
| 348 |
+
public void setStatusDescription(String statusDescription) { this.statusDescription = statusDescription; }
|
| 349 |
+
|
| 350 |
+
public List<String> getNextPossibleStates() { return nextPossibleStates; }
|
| 351 |
+
public void setNextPossibleStates(List<String> nextPossibleStates) { this.nextPossibleStates = nextPossibleStates; }
|
| 352 |
+
|
| 353 |
+
public boolean isCanEdit() { return canEdit; }
|
| 354 |
+
public void setCanEdit(boolean canEdit) { this.canEdit = canEdit; }
|
| 355 |
+
|
| 356 |
+
public boolean isCanSubmit() { return canSubmit; }
|
| 357 |
+
public void setCanSubmit(boolean canSubmit) { this.canSubmit = canSubmit; }
|
| 358 |
+
|
| 359 |
+
public boolean isCanApprove() { return canApprove; }
|
| 360 |
+
public void setCanApprove(boolean canApprove) { this.canApprove = canApprove; }
|
| 361 |
+
|
| 362 |
+
public boolean isCanReject() { return canReject; }
|
| 363 |
+
public void setCanReject(boolean canReject) { this.canReject = canReject; }
|
| 364 |
+
|
| 365 |
+
public boolean isCanPublish() { return canPublish; }
|
| 366 |
+
public void setCanPublish(boolean canPublish) { this.canPublish = canPublish; }
|
| 367 |
+
|
| 368 |
+
public String getStageColor() { return stageColor; }
|
| 369 |
+
public void setStageColor(String stageColor) { this.stageColor = stageColor; }
|
| 370 |
+
|
| 371 |
+
public Integer getDaysInCurrentStatus() { return daysInCurrentStatus; }
|
| 372 |
+
public void setDaysInCurrentStatus(Integer daysInCurrentStatus) { this.daysInCurrentStatus = daysInCurrentStatus; }
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
/**
|
| 376 |
+
* Nested DTO for available workflow actions.
|
| 377 |
+
*/
|
| 378 |
+
public static class WorkflowActionDTO {
|
| 379 |
+
private String actionType;
|
| 380 |
+
private String actionLabel;
|
| 381 |
+
private String actionDescription;
|
| 382 |
+
private boolean requiresComment;
|
| 383 |
+
private String confirmationMessage;
|
| 384 |
+
private String buttonStyle; // For UI styling
|
| 385 |
+
|
| 386 |
+
// Constructors, getters, and setters
|
| 387 |
+
public WorkflowActionDTO() {}
|
| 388 |
+
|
| 389 |
+
public WorkflowActionDTO(String actionType, String actionLabel) {
|
| 390 |
+
this.actionType = actionType;
|
| 391 |
+
this.actionLabel = actionLabel;
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
public String getActionType() { return actionType; }
|
| 395 |
+
public void setActionType(String actionType) { this.actionType = actionType; }
|
| 396 |
+
|
| 397 |
+
public String getActionLabel() { return actionLabel; }
|
| 398 |
+
public void setActionLabel(String actionLabel) { this.actionLabel = actionLabel; }
|
| 399 |
+
|
| 400 |
+
public String getActionDescription() { return actionDescription; }
|
| 401 |
+
public void setActionDescription(String actionDescription) { this.actionDescription = actionDescription; }
|
| 402 |
+
|
| 403 |
+
public boolean isRequiresComment() { return requiresComment; }
|
| 404 |
+
public void setRequiresComment(boolean requiresComment) { this.requiresComment = requiresComment; }
|
| 405 |
+
|
| 406 |
+
public String getConfirmationMessage() { return confirmationMessage; }
|
| 407 |
+
public void setConfirmationMessage(String confirmationMessage) { this.confirmationMessage = confirmationMessage; }
|
| 408 |
+
|
| 409 |
+
public String getButtonStyle() { return buttonStyle; }
|
| 410 |
+
public void setButtonStyle(String buttonStyle) { this.buttonStyle = buttonStyle; }
|
| 411 |
+
}
|
| 412 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyEvaluationOutputDTO.java
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
import java.util.UUID;
|
| 6 |
+
|
| 7 |
+
import com.dalab.policyengine.model.PolicyEvaluationStatus;
|
| 8 |
+
|
| 9 |
+
public class PolicyEvaluationOutputDTO {
|
| 10 |
+
private UUID id;
|
| 11 |
+
private UUID policyId;
|
| 12 |
+
private String policyName; // For convenience
|
| 13 |
+
private String targetAssetId;
|
| 14 |
+
private PolicyEvaluationStatus status;
|
| 15 |
+
private Map<String, Object> evaluationDetails; // e.g., facts used, rules evaluated, outcome per rule
|
| 16 |
+
private Map<String, Object> triggeredActions; // Actions taken based on the policy
|
| 17 |
+
private Instant evaluatedAt;
|
| 18 |
+
private UUID evaluationTriggeredByUserId;
|
| 19 |
+
|
| 20 |
+
// Getters and Setters
|
| 21 |
+
public UUID getId() {
|
| 22 |
+
return id;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
public void setId(UUID id) {
|
| 26 |
+
this.id = id;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
public UUID getPolicyId() {
|
| 30 |
+
return policyId;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
public void setPolicyId(UUID policyId) {
|
| 34 |
+
this.policyId = policyId;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
public String getPolicyName() {
|
| 38 |
+
return policyName;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
public void setPolicyName(String policyName) {
|
| 42 |
+
this.policyName = policyName;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
public String getTargetAssetId() {
|
| 46 |
+
return targetAssetId;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
public void setTargetAssetId(String targetAssetId) {
|
| 50 |
+
this.targetAssetId = targetAssetId;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
public PolicyEvaluationStatus getStatus() {
|
| 54 |
+
return status;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
public void setStatus(PolicyEvaluationStatus status) {
|
| 58 |
+
this.status = status;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
public Map<String, Object> getEvaluationDetails() {
|
| 62 |
+
return evaluationDetails;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
public void setEvaluationDetails(Map<String, Object> evaluationDetails) {
|
| 66 |
+
this.evaluationDetails = evaluationDetails;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
public Map<String, Object> getTriggeredActions() {
|
| 70 |
+
return triggeredActions;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
public void setTriggeredActions(Map<String, Object> triggeredActions) {
|
| 74 |
+
this.triggeredActions = triggeredActions;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
public Instant getEvaluatedAt() {
|
| 78 |
+
return evaluatedAt;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
public void setEvaluatedAt(Instant evaluatedAt) {
|
| 82 |
+
this.evaluatedAt = evaluatedAt;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
public UUID getEvaluationTriggeredByUserId() {
|
| 86 |
+
return evaluationTriggeredByUserId;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
public void setEvaluationTriggeredByUserId(UUID evaluationTriggeredByUserId) {
|
| 90 |
+
this.evaluationTriggeredByUserId = evaluationTriggeredByUserId;
|
| 91 |
+
}
|
| 92 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyEvaluationRequestDTO.java
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.util.Map;
|
| 4 |
+
|
| 5 |
+
import jakarta.validation.constraints.NotBlank;
|
| 6 |
+
|
| 7 |
+
public class PolicyEvaluationRequestDTO {
|
| 8 |
+
|
| 9 |
+
@NotBlank
|
| 10 |
+
private String targetAssetId; // The ID of the asset to be evaluated (e.g., from da-catalog)
|
| 11 |
+
|
| 12 |
+
// Optional: Additional context or facts that might not be directly part of the asset
|
| 13 |
+
// but are relevant for this specific evaluation.
|
| 14 |
+
private Map<String, Object> evaluationContext;
|
| 15 |
+
|
| 16 |
+
// Getters and Setters
|
| 17 |
+
public String getTargetAssetId() {
|
| 18 |
+
return targetAssetId;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
public void setTargetAssetId(String targetAssetId) {
|
| 22 |
+
this.targetAssetId = targetAssetId;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
public Map<String, Object> getEvaluationContext() {
|
| 26 |
+
return evaluationContext;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
public void setEvaluationContext(Map<String, Object> evaluationContext) {
|
| 30 |
+
this.evaluationContext = evaluationContext;
|
| 31 |
+
}
|
| 32 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyEvaluationSummaryDTO.java
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.UUID;
|
| 5 |
+
|
| 6 |
+
import com.dalab.policyengine.model.PolicyEvaluationStatus;
|
| 7 |
+
|
| 8 |
+
public class PolicyEvaluationSummaryDTO {
|
| 9 |
+
private UUID id;
|
| 10 |
+
private UUID policyId;
|
| 11 |
+
private String policyName;
|
| 12 |
+
private String targetAssetId;
|
| 13 |
+
private PolicyEvaluationStatus status;
|
| 14 |
+
private Instant evaluatedAt;
|
| 15 |
+
|
| 16 |
+
// Getters and Setters
|
| 17 |
+
public UUID getId() {
|
| 18 |
+
return id;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
public void setId(UUID id) {
|
| 22 |
+
this.id = id;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
public UUID getPolicyId() {
|
| 26 |
+
return policyId;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
public void setPolicyId(UUID policyId) {
|
| 30 |
+
this.policyId = policyId;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
public String getPolicyName() {
|
| 34 |
+
return policyName;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
public void setPolicyName(String policyName) {
|
| 38 |
+
this.policyName = policyName;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
public String getTargetAssetId() {
|
| 42 |
+
return targetAssetId;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
public void setTargetAssetId(String targetAssetId) {
|
| 46 |
+
this.targetAssetId = targetAssetId;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
public PolicyEvaluationStatus getStatus() {
|
| 50 |
+
return status;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
public void setStatus(PolicyEvaluationStatus status) {
|
| 54 |
+
this.status = status;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
public Instant getEvaluatedAt() {
|
| 58 |
+
return evaluatedAt;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
public void setEvaluatedAt(Instant evaluatedAt) {
|
| 62 |
+
this.evaluatedAt = evaluatedAt;
|
| 63 |
+
}
|
| 64 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyImpactRequestDTO.java
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.util.List;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
|
| 6 |
+
import jakarta.validation.constraints.NotBlank;
|
| 7 |
+
|
| 8 |
+
/**
|
| 9 |
+
* DTO for requesting policy impact analysis preview.
|
| 10 |
+
* This allows users to see what assets would be affected by policy changes before implementation.
|
| 11 |
+
*/
|
| 12 |
+
public class PolicyImpactRequestDTO {
|
| 13 |
+
|
| 14 |
+
/**
|
| 15 |
+
* The policy rules content to analyze for impact (JSON format).
|
| 16 |
+
* Required field containing the policy rules that need impact analysis.
|
| 17 |
+
*/
|
| 18 |
+
@NotBlank(message = "Policy rules content is required")
|
| 19 |
+
private String rulesContent;
|
| 20 |
+
|
| 21 |
+
/**
|
| 22 |
+
* Type of analysis to perform: FULL, QUICK, or TARGETED.
|
| 23 |
+
* - FULL: Comprehensive analysis across all assets
|
| 24 |
+
* - QUICK: Fast analysis with sampling
|
| 25 |
+
* - TARGETED: Analysis for specific asset types/groups
|
| 26 |
+
*/
|
| 27 |
+
@NotBlank(message = "Analysis type is required")
|
| 28 |
+
private String analysisType;
|
| 29 |
+
|
| 30 |
+
/**
|
| 31 |
+
* Optional scope limitations for targeted analysis.
|
| 32 |
+
* Can include asset types, data sources, or specific asset IDs.
|
| 33 |
+
*/
|
| 34 |
+
private PolicyImpactScopeDTO scope;
|
| 35 |
+
|
| 36 |
+
/**
|
| 37 |
+
* Include estimated performance impact in the analysis.
|
| 38 |
+
* When true, includes estimates for processing time and resource usage.
|
| 39 |
+
*/
|
| 40 |
+
private Boolean includePerformanceEstimate = false;
|
| 41 |
+
|
| 42 |
+
/**
|
| 43 |
+
* Include cost impact analysis in the preview.
|
| 44 |
+
* When true, estimates potential costs of policy enforcement.
|
| 45 |
+
*/
|
| 46 |
+
private Boolean includeCostImpact = false;
|
| 47 |
+
|
| 48 |
+
/**
|
| 49 |
+
* Include compliance impact analysis.
|
| 50 |
+
* When true, shows how this policy affects compliance with other policies.
|
| 51 |
+
*/
|
| 52 |
+
private Boolean includeComplianceImpact = false;
|
| 53 |
+
|
| 54 |
+
/**
|
| 55 |
+
* Additional context parameters for policy evaluation.
|
| 56 |
+
* Flexible map for custom analysis parameters.
|
| 57 |
+
*/
|
| 58 |
+
private Map<String, Object> contextParameters;
|
| 59 |
+
|
| 60 |
+
// Constructors
|
| 61 |
+
public PolicyImpactRequestDTO() {}
|
| 62 |
+
|
| 63 |
+
public PolicyImpactRequestDTO(String rulesContent, String analysisType) {
|
| 64 |
+
this.rulesContent = rulesContent;
|
| 65 |
+
this.analysisType = analysisType;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
// Getters and Setters
|
| 69 |
+
public String getRulesContent() {
|
| 70 |
+
return rulesContent;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
public void setRulesContent(String rulesContent) {
|
| 74 |
+
this.rulesContent = rulesContent;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
public String getAnalysisType() {
|
| 78 |
+
return analysisType;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
public void setAnalysisType(String analysisType) {
|
| 82 |
+
this.analysisType = analysisType;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
public PolicyImpactScopeDTO getScope() {
|
| 86 |
+
return scope;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
public void setScope(PolicyImpactScopeDTO scope) {
|
| 90 |
+
this.scope = scope;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
public Boolean getIncludePerformanceEstimate() {
|
| 94 |
+
return includePerformanceEstimate;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
public void setIncludePerformanceEstimate(Boolean includePerformanceEstimate) {
|
| 98 |
+
this.includePerformanceEstimate = includePerformanceEstimate;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
public Boolean getIncludeCostImpact() {
|
| 102 |
+
return includeCostImpact;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
public void setIncludeCostImpact(Boolean includeCostImpact) {
|
| 106 |
+
this.includeCostImpact = includeCostImpact;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
public Boolean getIncludeComplianceImpact() {
|
| 110 |
+
return includeComplianceImpact;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
public void setIncludeComplianceImpact(Boolean includeComplianceImpact) {
|
| 114 |
+
this.includeComplianceImpact = includeComplianceImpact;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
public Map<String, Object> getContextParameters() {
|
| 118 |
+
return contextParameters;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
public void setContextParameters(Map<String, Object> contextParameters) {
|
| 122 |
+
this.contextParameters = contextParameters;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
/**
|
| 126 |
+
* Nested DTO for defining analysis scope limitations.
|
| 127 |
+
*/
|
| 128 |
+
public static class PolicyImpactScopeDTO {
|
| 129 |
+
/**
|
| 130 |
+
* Specific asset types to include in analysis (e.g., "database", "file", "api").
|
| 131 |
+
*/
|
| 132 |
+
private List<String> assetTypes;
|
| 133 |
+
|
| 134 |
+
/**
|
| 135 |
+
* Specific data sources to include (e.g., connection IDs or source names).
|
| 136 |
+
*/
|
| 137 |
+
private List<String> dataSources;
|
| 138 |
+
|
| 139 |
+
/**
|
| 140 |
+
* Specific asset IDs to analyze (for targeted analysis).
|
| 141 |
+
*/
|
| 142 |
+
private List<String> assetIds;
|
| 143 |
+
|
| 144 |
+
/**
|
| 145 |
+
* Include only assets with specific labels.
|
| 146 |
+
*/
|
| 147 |
+
private List<String> requiredLabels;
|
| 148 |
+
|
| 149 |
+
/**
|
| 150 |
+
* Exclude assets with specific labels.
|
| 151 |
+
*/
|
| 152 |
+
private List<String> excludedLabels;
|
| 153 |
+
|
| 154 |
+
/**
|
| 155 |
+
* Maximum number of assets to analyze (for performance control).
|
| 156 |
+
*/
|
| 157 |
+
private Integer maxAssets;
|
| 158 |
+
|
| 159 |
+
// Constructors
|
| 160 |
+
public PolicyImpactScopeDTO() {}
|
| 161 |
+
|
| 162 |
+
// Getters and Setters
|
| 163 |
+
public List<String> getAssetTypes() {
|
| 164 |
+
return assetTypes;
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
public void setAssetTypes(List<String> assetTypes) {
|
| 168 |
+
this.assetTypes = assetTypes;
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
public List<String> getDataSources() {
|
| 172 |
+
return dataSources;
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
public void setDataSources(List<String> dataSources) {
|
| 176 |
+
this.dataSources = dataSources;
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
public List<String> getAssetIds() {
|
| 180 |
+
return assetIds;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
public void setAssetIds(List<String> assetIds) {
|
| 184 |
+
this.assetIds = assetIds;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
public List<String> getRequiredLabels() {
|
| 188 |
+
return requiredLabels;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
public void setRequiredLabels(List<String> requiredLabels) {
|
| 192 |
+
this.requiredLabels = requiredLabels;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
public List<String> getExcludedLabels() {
|
| 196 |
+
return excludedLabels;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
public void setExcludedLabels(List<String> excludedLabels) {
|
| 200 |
+
this.excludedLabels = excludedLabels;
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
public Integer getMaxAssets() {
|
| 204 |
+
return maxAssets;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
public void setMaxAssets(Integer maxAssets) {
|
| 208 |
+
this.maxAssets = maxAssets;
|
| 209 |
+
}
|
| 210 |
+
}
|
| 211 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyImpactResponseDTO.java
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.List;
|
| 5 |
+
import java.util.Map;
|
| 6 |
+
|
| 7 |
+
/**
|
| 8 |
+
* Comprehensive DTO for policy impact analysis response.
|
| 9 |
+
* Contains detailed analysis of what assets would be affected by policy changes.
|
| 10 |
+
*/
|
| 11 |
+
public class PolicyImpactResponseDTO {
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Unique identifier for this impact analysis.
|
| 15 |
+
*/
|
| 16 |
+
private String analysisId;
|
| 17 |
+
|
| 18 |
+
/**
|
| 19 |
+
* Timestamp when the analysis was performed.
|
| 20 |
+
*/
|
| 21 |
+
private Instant analyzedAt;
|
| 22 |
+
|
| 23 |
+
/**
|
| 24 |
+
* Type of analysis performed: FULL, QUICK, or TARGETED.
|
| 25 |
+
*/
|
| 26 |
+
private String analysisType;
|
| 27 |
+
|
| 28 |
+
/**
|
| 29 |
+
* Overall impact summary with key metrics.
|
| 30 |
+
*/
|
| 31 |
+
private ImpactSummaryDTO summary;
|
| 32 |
+
|
| 33 |
+
/**
|
| 34 |
+
* Detailed breakdown of affected assets by category.
|
| 35 |
+
*/
|
| 36 |
+
private List<AssetImpactDTO> affectedAssets;
|
| 37 |
+
|
| 38 |
+
/**
|
| 39 |
+
* Performance impact estimates (if requested).
|
| 40 |
+
*/
|
| 41 |
+
private PerformanceImpactDTO performanceImpact;
|
| 42 |
+
|
| 43 |
+
/**
|
| 44 |
+
* Cost impact analysis (if requested).
|
| 45 |
+
*/
|
| 46 |
+
private CostImpactDTO costImpact;
|
| 47 |
+
|
| 48 |
+
/**
|
| 49 |
+
* Compliance impact analysis (if requested).
|
| 50 |
+
*/
|
| 51 |
+
private ComplianceImpactDTO complianceImpact;
|
| 52 |
+
|
| 53 |
+
/**
|
| 54 |
+
* Risk assessment for implementing this policy.
|
| 55 |
+
*/
|
| 56 |
+
private RiskAssessmentDTO riskAssessment;
|
| 57 |
+
|
| 58 |
+
/**
|
| 59 |
+
* Recommendations for policy implementation.
|
| 60 |
+
*/
|
| 61 |
+
private List<String> recommendations;
|
| 62 |
+
|
| 63 |
+
/**
|
| 64 |
+
* Analysis execution metadata.
|
| 65 |
+
*/
|
| 66 |
+
private AnalysisMetadataDTO metadata;
|
| 67 |
+
|
| 68 |
+
// Constructors
|
| 69 |
+
public PolicyImpactResponseDTO() {}
|
| 70 |
+
|
| 71 |
+
public PolicyImpactResponseDTO(String analysisId, String analysisType) {
|
| 72 |
+
this.analysisId = analysisId;
|
| 73 |
+
this.analysisType = analysisType;
|
| 74 |
+
this.analyzedAt = Instant.now();
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
// Getters and Setters
|
| 78 |
+
public String getAnalysisId() {
|
| 79 |
+
return analysisId;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
public void setAnalysisId(String analysisId) {
|
| 83 |
+
this.analysisId = analysisId;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
public Instant getAnalyzedAt() {
|
| 87 |
+
return analyzedAt;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
public void setAnalyzedAt(Instant analyzedAt) {
|
| 91 |
+
this.analyzedAt = analyzedAt;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
public String getAnalysisType() {
|
| 95 |
+
return analysisType;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
public void setAnalysisType(String analysisType) {
|
| 99 |
+
this.analysisType = analysisType;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
public ImpactSummaryDTO getSummary() {
|
| 103 |
+
return summary;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
public void setSummary(ImpactSummaryDTO summary) {
|
| 107 |
+
this.summary = summary;
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
public List<AssetImpactDTO> getAffectedAssets() {
|
| 111 |
+
return affectedAssets;
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
public void setAffectedAssets(List<AssetImpactDTO> affectedAssets) {
|
| 115 |
+
this.affectedAssets = affectedAssets;
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
public PerformanceImpactDTO getPerformanceImpact() {
|
| 119 |
+
return performanceImpact;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
public void setPerformanceImpact(PerformanceImpactDTO performanceImpact) {
|
| 123 |
+
this.performanceImpact = performanceImpact;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
public CostImpactDTO getCostImpact() {
|
| 127 |
+
return costImpact;
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
public void setCostImpact(CostImpactDTO costImpact) {
|
| 131 |
+
this.costImpact = costImpact;
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
public ComplianceImpactDTO getComplianceImpact() {
|
| 135 |
+
return complianceImpact;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
public void setComplianceImpact(ComplianceImpactDTO complianceImpact) {
|
| 139 |
+
this.complianceImpact = complianceImpact;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
public RiskAssessmentDTO getRiskAssessment() {
|
| 143 |
+
return riskAssessment;
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
public void setRiskAssessment(RiskAssessmentDTO riskAssessment) {
|
| 147 |
+
this.riskAssessment = riskAssessment;
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
public List<String> getRecommendations() {
|
| 151 |
+
return recommendations;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
public void setRecommendations(List<String> recommendations) {
|
| 155 |
+
this.recommendations = recommendations;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
public AnalysisMetadataDTO getMetadata() {
|
| 159 |
+
return metadata;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
public void setMetadata(AnalysisMetadataDTO metadata) {
|
| 163 |
+
this.metadata = metadata;
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
/**
|
| 167 |
+
* Overall impact summary with key metrics.
|
| 168 |
+
*/
|
| 169 |
+
public static class ImpactSummaryDTO {
|
| 170 |
+
private Integer totalAssetsAnalyzed;
|
| 171 |
+
private Integer totalAssetsAffected;
|
| 172 |
+
private Integer highImpactAssets;
|
| 173 |
+
private Integer mediumImpactAssets;
|
| 174 |
+
private Integer lowImpactAssets;
|
| 175 |
+
private String overallRiskLevel; // LOW, MEDIUM, HIGH, CRITICAL
|
| 176 |
+
private Double impactPercentage;
|
| 177 |
+
|
| 178 |
+
// Constructors, getters, and setters
|
| 179 |
+
public ImpactSummaryDTO() {}
|
| 180 |
+
|
| 181 |
+
public Integer getTotalAssetsAnalyzed() { return totalAssetsAnalyzed; }
|
| 182 |
+
public void setTotalAssetsAnalyzed(Integer totalAssetsAnalyzed) { this.totalAssetsAnalyzed = totalAssetsAnalyzed; }
|
| 183 |
+
|
| 184 |
+
public Integer getTotalAssetsAffected() { return totalAssetsAffected; }
|
| 185 |
+
public void setTotalAssetsAffected(Integer totalAssetsAffected) { this.totalAssetsAffected = totalAssetsAffected; }
|
| 186 |
+
|
| 187 |
+
public Integer getHighImpactAssets() { return highImpactAssets; }
|
| 188 |
+
public void setHighImpactAssets(Integer highImpactAssets) { this.highImpactAssets = highImpactAssets; }
|
| 189 |
+
|
| 190 |
+
public Integer getMediumImpactAssets() { return mediumImpactAssets; }
|
| 191 |
+
public void setMediumImpactAssets(Integer mediumImpactAssets) { this.mediumImpactAssets = mediumImpactAssets; }
|
| 192 |
+
|
| 193 |
+
public Integer getLowImpactAssets() { return lowImpactAssets; }
|
| 194 |
+
public void setLowImpactAssets(Integer lowImpactAssets) { this.lowImpactAssets = lowImpactAssets; }
|
| 195 |
+
|
| 196 |
+
public String getOverallRiskLevel() { return overallRiskLevel; }
|
| 197 |
+
public void setOverallRiskLevel(String overallRiskLevel) { this.overallRiskLevel = overallRiskLevel; }
|
| 198 |
+
|
| 199 |
+
public Double getImpactPercentage() { return impactPercentage; }
|
| 200 |
+
public void setImpactPercentage(Double impactPercentage) { this.impactPercentage = impactPercentage; }
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
/**
|
| 204 |
+
* Individual asset impact details.
|
| 205 |
+
*/
|
| 206 |
+
public static class AssetImpactDTO {
|
| 207 |
+
private String assetId;
|
| 208 |
+
private String assetName;
|
| 209 |
+
private String assetType;
|
| 210 |
+
private String impactLevel; // HIGH, MEDIUM, LOW
|
| 211 |
+
private List<String> affectedAttributes;
|
| 212 |
+
private List<String> appliedActions;
|
| 213 |
+
private String riskAssessment;
|
| 214 |
+
private Map<String, Object> impactDetails;
|
| 215 |
+
|
| 216 |
+
// Constructors, getters, and setters
|
| 217 |
+
public AssetImpactDTO() {}
|
| 218 |
+
|
| 219 |
+
public String getAssetId() { return assetId; }
|
| 220 |
+
public void setAssetId(String assetId) { this.assetId = assetId; }
|
| 221 |
+
|
| 222 |
+
public String getAssetName() { return assetName; }
|
| 223 |
+
public void setAssetName(String assetName) { this.assetName = assetName; }
|
| 224 |
+
|
| 225 |
+
public String getAssetType() { return assetType; }
|
| 226 |
+
public void setAssetType(String assetType) { this.assetType = assetType; }
|
| 227 |
+
|
| 228 |
+
public String getImpactLevel() { return impactLevel; }
|
| 229 |
+
public void setImpactLevel(String impactLevel) { this.impactLevel = impactLevel; }
|
| 230 |
+
|
| 231 |
+
public List<String> getAffectedAttributes() { return affectedAttributes; }
|
| 232 |
+
public void setAffectedAttributes(List<String> affectedAttributes) { this.affectedAttributes = affectedAttributes; }
|
| 233 |
+
|
| 234 |
+
public List<String> getAppliedActions() { return appliedActions; }
|
| 235 |
+
public void setAppliedActions(List<String> appliedActions) { this.appliedActions = appliedActions; }
|
| 236 |
+
|
| 237 |
+
public String getRiskAssessment() { return riskAssessment; }
|
| 238 |
+
public void setRiskAssessment(String riskAssessment) { this.riskAssessment = riskAssessment; }
|
| 239 |
+
|
| 240 |
+
public Map<String, Object> getImpactDetails() { return impactDetails; }
|
| 241 |
+
public void setImpactDetails(Map<String, Object> impactDetails) { this.impactDetails = impactDetails; }
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
/**
|
| 245 |
+
* Performance impact estimates.
|
| 246 |
+
*/
|
| 247 |
+
public static class PerformanceImpactDTO {
|
| 248 |
+
private Long estimatedProcessingTimeMs;
|
| 249 |
+
private Double cpuUtilizationIncrease;
|
| 250 |
+
private Double memoryUtilizationIncrease;
|
| 251 |
+
private Integer estimatedApiCalls;
|
| 252 |
+
private String performanceRiskLevel;
|
| 253 |
+
|
| 254 |
+
// Constructors, getters, and setters
|
| 255 |
+
public PerformanceImpactDTO() {}
|
| 256 |
+
|
| 257 |
+
public Long getEstimatedProcessingTimeMs() { return estimatedProcessingTimeMs; }
|
| 258 |
+
public void setEstimatedProcessingTimeMs(Long estimatedProcessingTimeMs) { this.estimatedProcessingTimeMs = estimatedProcessingTimeMs; }
|
| 259 |
+
|
| 260 |
+
public Double getCpuUtilizationIncrease() { return cpuUtilizationIncrease; }
|
| 261 |
+
public void setCpuUtilizationIncrease(Double cpuUtilizationIncrease) { this.cpuUtilizationIncrease = cpuUtilizationIncrease; }
|
| 262 |
+
|
| 263 |
+
public Double getMemoryUtilizationIncrease() { return memoryUtilizationIncrease; }
|
| 264 |
+
public void setMemoryUtilizationIncrease(Double memoryUtilizationIncrease) { this.memoryUtilizationIncrease = memoryUtilizationIncrease; }
|
| 265 |
+
|
| 266 |
+
public Integer getEstimatedApiCalls() { return estimatedApiCalls; }
|
| 267 |
+
public void setEstimatedApiCalls(Integer estimatedApiCalls) { this.estimatedApiCalls = estimatedApiCalls; }
|
| 268 |
+
|
| 269 |
+
public String getPerformanceRiskLevel() { return performanceRiskLevel; }
|
| 270 |
+
public void setPerformanceRiskLevel(String performanceRiskLevel) { this.performanceRiskLevel = performanceRiskLevel; }
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
/**
|
| 274 |
+
* Cost impact analysis.
|
| 275 |
+
*/
|
| 276 |
+
public static class CostImpactDTO {
|
| 277 |
+
private Double estimatedMonthlyCost;
|
| 278 |
+
private Double estimatedImplementationCost;
|
| 279 |
+
private Double potentialSavings;
|
| 280 |
+
private String costRiskLevel;
|
| 281 |
+
private Map<String, Double> costBreakdown;
|
| 282 |
+
|
| 283 |
+
// Constructors, getters, and setters
|
| 284 |
+
public CostImpactDTO() {}
|
| 285 |
+
|
| 286 |
+
public Double getEstimatedMonthlyCost() { return estimatedMonthlyCost; }
|
| 287 |
+
public void setEstimatedMonthlyCost(Double estimatedMonthlyCost) { this.estimatedMonthlyCost = estimatedMonthlyCost; }
|
| 288 |
+
|
| 289 |
+
public Double getEstimatedImplementationCost() { return estimatedImplementationCost; }
|
| 290 |
+
public void setEstimatedImplementationCost(Double estimatedImplementationCost) { this.estimatedImplementationCost = estimatedImplementationCost; }
|
| 291 |
+
|
| 292 |
+
public Double getPotentialSavings() { return potentialSavings; }
|
| 293 |
+
public void setPotentialSavings(Double potentialSavings) { this.potentialSavings = potentialSavings; }
|
| 294 |
+
|
| 295 |
+
public String getCostRiskLevel() { return costRiskLevel; }
|
| 296 |
+
public void setCostRiskLevel(String costRiskLevel) { this.costRiskLevel = costRiskLevel; }
|
| 297 |
+
|
| 298 |
+
public Map<String, Double> getCostBreakdown() { return costBreakdown; }
|
| 299 |
+
public void setCostBreakdown(Map<String, Double> costBreakdown) { this.costBreakdown = costBreakdown; }
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
/**
|
| 303 |
+
* Compliance impact analysis.
|
| 304 |
+
*/
|
| 305 |
+
public static class ComplianceImpactDTO {
|
| 306 |
+
private Integer conflictingPolicies;
|
| 307 |
+
private List<String> complianceFrameworksAffected;
|
| 308 |
+
private String complianceRiskLevel;
|
| 309 |
+
private List<String> potentialViolations;
|
| 310 |
+
|
| 311 |
+
// Constructors, getters, and setters
|
| 312 |
+
public ComplianceImpactDTO() {}
|
| 313 |
+
|
| 314 |
+
public Integer getConflictingPolicies() { return conflictingPolicies; }
|
| 315 |
+
public void setConflictingPolicies(Integer conflictingPolicies) { this.conflictingPolicies = conflictingPolicies; }
|
| 316 |
+
|
| 317 |
+
public List<String> getComplianceFrameworksAffected() { return complianceFrameworksAffected; }
|
| 318 |
+
public void setComplianceFrameworksAffected(List<String> complianceFrameworksAffected) { this.complianceFrameworksAffected = complianceFrameworksAffected; }
|
| 319 |
+
|
| 320 |
+
public String getComplianceRiskLevel() { return complianceRiskLevel; }
|
| 321 |
+
public void setComplianceRiskLevel(String complianceRiskLevel) { this.complianceRiskLevel = complianceRiskLevel; }
|
| 322 |
+
|
| 323 |
+
public List<String> getPotentialViolations() { return potentialViolations; }
|
| 324 |
+
public void setPotentialViolations(List<String> potentialViolations) { this.potentialViolations = potentialViolations; }
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
/**
|
| 328 |
+
* Risk assessment for policy implementation.
|
| 329 |
+
*/
|
| 330 |
+
public static class RiskAssessmentDTO {
|
| 331 |
+
private String overallRiskLevel;
|
| 332 |
+
private List<String> identifiedRisks;
|
| 333 |
+
private List<String> mitigationStrategies;
|
| 334 |
+
private Double riskScore;
|
| 335 |
+
|
| 336 |
+
// Constructors, getters, and setters
|
| 337 |
+
public RiskAssessmentDTO() {}
|
| 338 |
+
|
| 339 |
+
public String getOverallRiskLevel() { return overallRiskLevel; }
|
| 340 |
+
public void setOverallRiskLevel(String overallRiskLevel) { this.overallRiskLevel = overallRiskLevel; }
|
| 341 |
+
|
| 342 |
+
public List<String> getIdentifiedRisks() { return identifiedRisks; }
|
| 343 |
+
public void setIdentifiedRisks(List<String> identifiedRisks) { this.identifiedRisks = identifiedRisks; }
|
| 344 |
+
|
| 345 |
+
public List<String> getMitigationStrategies() { return mitigationStrategies; }
|
| 346 |
+
public void setMitigationStrategies(List<String> mitigationStrategies) { this.mitigationStrategies = mitigationStrategies; }
|
| 347 |
+
|
| 348 |
+
public Double getRiskScore() { return riskScore; }
|
| 349 |
+
public void setRiskScore(Double riskScore) { this.riskScore = riskScore; }
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
/**
|
| 353 |
+
* Analysis execution metadata.
|
| 354 |
+
*/
|
| 355 |
+
public static class AnalysisMetadataDTO {
|
| 356 |
+
private Long executionTimeMs;
|
| 357 |
+
private String analysisVersion;
|
| 358 |
+
private Boolean usesCachedData;
|
| 359 |
+
private Instant dataFreshnessTimestamp;
|
| 360 |
+
|
| 361 |
+
// Constructors, getters, and setters
|
| 362 |
+
public AnalysisMetadataDTO() {}
|
| 363 |
+
|
| 364 |
+
public Long getExecutionTimeMs() { return executionTimeMs; }
|
| 365 |
+
public void setExecutionTimeMs(Long executionTimeMs) { this.executionTimeMs = executionTimeMs; }
|
| 366 |
+
|
| 367 |
+
public String getAnalysisVersion() { return analysisVersion; }
|
| 368 |
+
public void setAnalysisVersion(String analysisVersion) { this.analysisVersion = analysisVersion; }
|
| 369 |
+
|
| 370 |
+
public Boolean getUsesCachedData() { return usesCachedData; }
|
| 371 |
+
public void setUsesCachedData(Boolean usesCachedData) { this.usesCachedData = usesCachedData; }
|
| 372 |
+
|
| 373 |
+
public Instant getDataFreshnessTimestamp() { return dataFreshnessTimestamp; }
|
| 374 |
+
public void setDataFreshnessTimestamp(Instant dataFreshnessTimestamp) { this.dataFreshnessTimestamp = dataFreshnessTimestamp; }
|
| 375 |
+
}
|
| 376 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyInputDTO.java
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.util.List;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
|
| 6 |
+
import com.dalab.policyengine.model.PolicyStatus;
|
| 7 |
+
|
| 8 |
+
import jakarta.validation.Valid;
|
| 9 |
+
import jakarta.validation.constraints.NotBlank;
|
| 10 |
+
import jakarta.validation.constraints.NotEmpty;
|
| 11 |
+
import jakarta.validation.constraints.Size;
|
| 12 |
+
|
| 13 |
+
public class PolicyInputDTO {
|
| 14 |
+
|
| 15 |
+
@NotBlank
|
| 16 |
+
@Size(max = 255)
|
| 17 |
+
private String name;
|
| 18 |
+
|
| 19 |
+
@Size(max = 1000)
|
| 20 |
+
private String description;
|
| 21 |
+
|
| 22 |
+
private PolicyStatus status = PolicyStatus.DISABLED;
|
| 23 |
+
|
| 24 |
+
private String conditionLogic; // e.g., "rule1 && (rule2 || rule3)"
|
| 25 |
+
|
| 26 |
+
@NotEmpty
|
| 27 |
+
@Valid
|
| 28 |
+
private List<PolicyRuleDTO> rules;
|
| 29 |
+
|
| 30 |
+
private Map<String, Object> actions; // Policy-level actions
|
| 31 |
+
|
| 32 |
+
// Getters and Setters
|
| 33 |
+
public String getName() {
|
| 34 |
+
return name;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
public void setName(String name) {
|
| 38 |
+
this.name = name;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
public String getDescription() {
|
| 42 |
+
return description;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
public void setDescription(String description) {
|
| 46 |
+
this.description = description;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
public PolicyStatus getStatus() {
|
| 50 |
+
return status;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
public void setStatus(PolicyStatus status) {
|
| 54 |
+
this.status = status;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
public String getConditionLogic() {
|
| 58 |
+
return conditionLogic;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
public void setConditionLogic(String conditionLogic) {
|
| 62 |
+
this.conditionLogic = conditionLogic;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
public List<PolicyRuleDTO> getRules() {
|
| 66 |
+
return rules;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
public void setRules(List<PolicyRuleDTO> rules) {
|
| 70 |
+
this.rules = rules;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
public Map<String, Object> getActions() {
|
| 74 |
+
return actions;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
public void setActions(Map<String, Object> actions) {
|
| 78 |
+
this.actions = actions;
|
| 79 |
+
}
|
| 80 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyOutputDTO.java
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.List;
|
| 5 |
+
import java.util.Map;
|
| 6 |
+
import java.util.UUID;
|
| 7 |
+
|
| 8 |
+
import com.dalab.policyengine.model.PolicyStatus;
|
| 9 |
+
|
| 10 |
+
public class PolicyOutputDTO {
|
| 11 |
+
private UUID id;
|
| 12 |
+
private String name;
|
| 13 |
+
private String description;
|
| 14 |
+
private PolicyStatus status;
|
| 15 |
+
private String conditionLogic;
|
| 16 |
+
private List<PolicyRuleDTO> rules;
|
| 17 |
+
private Map<String, Object> actions;
|
| 18 |
+
private Instant createdAt;
|
| 19 |
+
private Instant updatedAt;
|
| 20 |
+
private UUID createdByUserId;
|
| 21 |
+
private UUID updatedByUserId;
|
| 22 |
+
|
| 23 |
+
// Getters and Setters
|
| 24 |
+
public UUID getId() {
|
| 25 |
+
return id;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
public void setId(UUID id) {
|
| 29 |
+
this.id = id;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
public String getName() {
|
| 33 |
+
return name;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
public void setName(String name) {
|
| 37 |
+
this.name = name;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
public String getDescription() {
|
| 41 |
+
return description;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
public void setDescription(String description) {
|
| 45 |
+
this.description = description;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
public PolicyStatus getStatus() {
|
| 49 |
+
return status;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
public void setStatus(PolicyStatus status) {
|
| 53 |
+
this.status = status;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
public String getConditionLogic() {
|
| 57 |
+
return conditionLogic;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
public void setConditionLogic(String conditionLogic) {
|
| 61 |
+
this.conditionLogic = conditionLogic;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
public List<PolicyRuleDTO> getRules() {
|
| 65 |
+
return rules;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
public void setRules(List<PolicyRuleDTO> rules) {
|
| 69 |
+
this.rules = rules;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
public Map<String, Object> getActions() {
|
| 73 |
+
return actions;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
public void setActions(Map<String, Object> actions) {
|
| 77 |
+
this.actions = actions;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
public Instant getCreatedAt() {
|
| 81 |
+
return createdAt;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
public void setCreatedAt(Instant createdAt) {
|
| 85 |
+
this.createdAt = createdAt;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
public Instant getUpdatedAt() {
|
| 89 |
+
return updatedAt;
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 93 |
+
this.updatedAt = updatedAt;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
public UUID getCreatedByUserId() {
|
| 97 |
+
return createdByUserId;
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
public void setCreatedByUserId(UUID createdByUserId) {
|
| 101 |
+
this.createdByUserId = createdByUserId;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
public UUID getUpdatedByUserId() {
|
| 105 |
+
return updatedByUserId;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
public void setUpdatedByUserId(UUID updatedByUserId) {
|
| 109 |
+
this.updatedByUserId = updatedByUserId;
|
| 110 |
+
}
|
| 111 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicyRuleDTO.java
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.util.Map;
|
| 4 |
+
|
| 5 |
+
import jakarta.validation.constraints.NotBlank;
|
| 6 |
+
import jakarta.validation.constraints.Size;
|
| 7 |
+
|
| 8 |
+
public class PolicyRuleDTO {
|
| 9 |
+
private String id; // UUID as String, can be null for new rules in create/update
|
| 10 |
+
|
| 11 |
+
@NotBlank
|
| 12 |
+
@Size(max = 255)
|
| 13 |
+
private String name;
|
| 14 |
+
|
| 15 |
+
@Size(max = 1000)
|
| 16 |
+
private String description;
|
| 17 |
+
|
| 18 |
+
@NotBlank
|
| 19 |
+
private String condition; // MVEL expression
|
| 20 |
+
|
| 21 |
+
private int priority = 1;
|
| 22 |
+
private Map<String, Object> actions; // Optional rule-specific actions
|
| 23 |
+
|
| 24 |
+
// Getters and Setters
|
| 25 |
+
public String getId() {
|
| 26 |
+
return id;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
public void setId(String id) {
|
| 30 |
+
this.id = id;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
public String getName() {
|
| 34 |
+
return name;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
public void setName(String name) {
|
| 38 |
+
this.name = name;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
public String getDescription() {
|
| 42 |
+
return description;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
public void setDescription(String description) {
|
| 46 |
+
this.description = description;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
public String getCondition() {
|
| 50 |
+
return condition;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
public void setCondition(String condition) {
|
| 54 |
+
this.condition = condition;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
public int getPriority() {
|
| 58 |
+
return priority;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
public void setPriority(int priority) {
|
| 62 |
+
this.priority = priority;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
public Map<String, Object> getActions() {
|
| 66 |
+
return actions;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
public void setActions(Map<String, Object> actions) {
|
| 70 |
+
this.actions = actions;
|
| 71 |
+
}
|
| 72 |
+
}
|
src/main/java/com/dalab/policyengine/dto/PolicySummaryDTO.java
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.dto;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.UUID;
|
| 5 |
+
|
| 6 |
+
import com.dalab.policyengine.model.PolicyStatus;
|
| 7 |
+
|
| 8 |
+
public class PolicySummaryDTO {
|
| 9 |
+
private UUID id;
|
| 10 |
+
private String name;
|
| 11 |
+
private String description;
|
| 12 |
+
private PolicyStatus status;
|
| 13 |
+
private int ruleCount;
|
| 14 |
+
private Instant createdAt;
|
| 15 |
+
private Instant updatedAt;
|
| 16 |
+
|
| 17 |
+
// Getters and Setters
|
| 18 |
+
public UUID getId() {
|
| 19 |
+
return id;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
public void setId(UUID id) {
|
| 23 |
+
this.id = id;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
public String getName() {
|
| 27 |
+
return name;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
public void setName(String name) {
|
| 31 |
+
this.name = name;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
public String getDescription() {
|
| 35 |
+
return description;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
public void setDescription(String description) {
|
| 39 |
+
this.description = description;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
public PolicyStatus getStatus() {
|
| 43 |
+
return status;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
public void setStatus(PolicyStatus status) {
|
| 47 |
+
this.status = status;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
public int getRuleCount() {
|
| 51 |
+
return ruleCount;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
public void setRuleCount(int ruleCount) {
|
| 55 |
+
this.ruleCount = ruleCount;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
public Instant getCreatedAt() {
|
| 59 |
+
return createdAt;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
public void setCreatedAt(Instant createdAt) {
|
| 63 |
+
this.createdAt = createdAt;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
public Instant getUpdatedAt() {
|
| 67 |
+
return updatedAt;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 71 |
+
this.updatedAt = updatedAt;
|
| 72 |
+
}
|
| 73 |
+
}
|
src/main/java/com/dalab/policyengine/event/PolicyActionEvent.java
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.event;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
import java.util.UUID;
|
| 6 |
+
|
| 7 |
+
// This DTO represents an action triggered by a policy evaluation,
|
| 8 |
+
// to be published to a Kafka topic.
|
| 9 |
+
public class PolicyActionEvent {
|
| 10 |
+
private UUID eventId;
|
| 11 |
+
private String policyId;
|
| 12 |
+
private String policyName;
|
| 13 |
+
private String targetAssetId;
|
| 14 |
+
private String actionType; // e.g., "ADD_LABEL", "NOTIFY_EMAIL", "ARCHIVE_ASSET"
|
| 15 |
+
private Map<String, Object> actionParameters; // Parameters for the action, e.g., {"labelName": "PII", "confidence": 0.9} or {"to": "user@example.com", "subject": "Alert"}
|
| 16 |
+
private Instant timestamp;
|
| 17 |
+
private UUID triggeredByEvaluationId; // Link back to the PolicyEvaluation record
|
| 18 |
+
|
| 19 |
+
public PolicyActionEvent() {
|
| 20 |
+
this.eventId = UUID.randomUUID();
|
| 21 |
+
this.timestamp = Instant.now();
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
// Getters and Setters
|
| 25 |
+
public UUID getEventId() {
|
| 26 |
+
return eventId;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
public void setEventId(UUID eventId) {
|
| 30 |
+
this.eventId = eventId;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
public String getPolicyId() {
|
| 34 |
+
return policyId;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
public void setPolicyId(String policyId) {
|
| 38 |
+
this.policyId = policyId;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
public String getPolicyName() {
|
| 42 |
+
return policyName;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
public void setPolicyName(String policyName) {
|
| 46 |
+
this.policyName = policyName;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
public String getTargetAssetId() {
|
| 50 |
+
return targetAssetId;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
public void setTargetAssetId(String targetAssetId) {
|
| 54 |
+
this.targetAssetId = targetAssetId;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
public String getActionType() {
|
| 58 |
+
return actionType;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
public void setActionType(String actionType) {
|
| 62 |
+
this.actionType = actionType;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
public Map<String, Object> getActionParameters() {
|
| 66 |
+
return actionParameters;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
public void setActionParameters(Map<String, Object> actionParameters) {
|
| 70 |
+
this.actionParameters = actionParameters;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
public Instant getTimestamp() {
|
| 74 |
+
return timestamp;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
public void setTimestamp(Instant timestamp) {
|
| 78 |
+
this.timestamp = timestamp;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
public UUID getTriggeredByEvaluationId() {
|
| 82 |
+
return triggeredByEvaluationId;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
public void setTriggeredByEvaluationId(UUID triggeredByEvaluationId) {
|
| 86 |
+
this.triggeredByEvaluationId = triggeredByEvaluationId;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
@Override
|
| 90 |
+
public String toString() {
|
| 91 |
+
return "PolicyActionEvent{" +
|
| 92 |
+
"eventId=" + eventId +
|
| 93 |
+
", policyId='" + policyId + '\'' +
|
| 94 |
+
", policyName='" + policyName + '\'' +
|
| 95 |
+
", targetAssetId='" + targetAssetId + '\'' +
|
| 96 |
+
", actionType='" + actionType + '\'' +
|
| 97 |
+
", actionParameters=" + actionParameters +
|
| 98 |
+
", timestamp=" + timestamp +
|
| 99 |
+
", triggeredByEvaluationId=" + triggeredByEvaluationId +
|
| 100 |
+
'}';
|
| 101 |
+
}
|
| 102 |
+
}
|
src/main/java/com/dalab/policyengine/kafka/consumer/AssetChangeConsumer.java
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.kafka.consumer;
|
| 2 |
+
|
| 3 |
+
import java.util.UUID;
|
| 4 |
+
|
| 5 |
+
import org.slf4j.Logger;
|
| 6 |
+
import org.slf4j.LoggerFactory;
|
| 7 |
+
import org.springframework.beans.factory.annotation.Autowired;
|
| 8 |
+
import org.springframework.kafka.annotation.KafkaListener;
|
| 9 |
+
import org.springframework.messaging.handler.annotation.Payload;
|
| 10 |
+
import org.springframework.stereotype.Component;
|
| 11 |
+
import org.springframework.util.StringUtils;
|
| 12 |
+
|
| 13 |
+
// Import the common AssetChangeEvent from da-protos
|
| 14 |
+
import com.dalab.common.event.AssetChangeEvent;
|
| 15 |
+
import com.dalab.policyengine.service.IPolicyEvaluationService;
|
| 16 |
+
|
| 17 |
+
@Component
|
| 18 |
+
public class AssetChangeConsumer {
|
| 19 |
+
|
| 20 |
+
private static final Logger log = LoggerFactory.getLogger(AssetChangeConsumer.class);
|
| 21 |
+
// System UUID for actions triggered by Kafka consumer events
|
| 22 |
+
private static final UUID KAFKA_CONSUMER_USER_ID = UUID.fromString("00000000-0000-0000-0000-000000000001");
|
| 23 |
+
|
| 24 |
+
private final IPolicyEvaluationService policyEvaluationService;
|
| 25 |
+
|
| 26 |
+
@Autowired
|
| 27 |
+
public AssetChangeConsumer(IPolicyEvaluationService policyEvaluationService) {
|
| 28 |
+
this.policyEvaluationService = policyEvaluationService;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
// Update KafkaListener to consume the common AssetChangeEvent
|
| 32 |
+
@KafkaListener(topics = "${app.kafka.topic.asset-change-event:asset-change-events}", groupId = "${spring.kafka.consumer.group-id}")
|
| 33 |
+
public void handleAssetChangeEvent(@Payload AssetChangeEvent event) {
|
| 34 |
+
log.info("Received AssetChangeEvent: AssetId={}, EventType={}", event.getAssetId(), event.getEventType());
|
| 35 |
+
|
| 36 |
+
try {
|
| 37 |
+
if (event == null || event.getAssetId() == null || !StringUtils.hasText(event.getAssetId())) {
|
| 38 |
+
log.error("AssetChangeEvent is null or missing assetId. Skipping.");
|
| 39 |
+
return;
|
| 40 |
+
}
|
| 41 |
+
// The PolicyEvaluationService will now fetch active policies and iterate.
|
| 42 |
+
policyEvaluationService.evaluatePolicyForAssetInternal(event, KAFKA_CONSUMER_USER_ID);
|
| 43 |
+
|
| 44 |
+
} catch (Exception e) {
|
| 45 |
+
log.error("Failed to process AssetChangeEvent for assetId {}: {}. Error: {}",
|
| 46 |
+
event != null && event.getAssetId() != null ? event.getAssetId() : "unknown",
|
| 47 |
+
e.getMessage(), e);
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
}
|
src/main/java/com/dalab/policyengine/kafka/consumer/AssetChangeEventListener.java
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.kafka.consumer;
|
| 2 |
+
|
| 3 |
+
import java.util.UUID;
|
| 4 |
+
|
| 5 |
+
import org.slf4j.Logger;
|
| 6 |
+
import org.slf4j.LoggerFactory;
|
| 7 |
+
import org.springframework.kafka.annotation.KafkaListener;
|
| 8 |
+
import org.springframework.kafka.support.KafkaHeaders;
|
| 9 |
+
import org.springframework.messaging.handler.annotation.Header;
|
| 10 |
+
import org.springframework.messaging.handler.annotation.Payload;
|
| 11 |
+
import org.springframework.stereotype.Component;
|
| 12 |
+
|
| 13 |
+
import com.dalab.common.event.AssetChangeEvent;
|
| 14 |
+
import com.dalab.policyengine.service.IPolicyEvaluationService;
|
| 15 |
+
|
| 16 |
+
@Component
|
| 17 |
+
public class AssetChangeEventListener {
|
| 18 |
+
|
| 19 |
+
private static final Logger LOGGER = LoggerFactory.getLogger(AssetChangeEventListener.class);
|
| 20 |
+
|
| 21 |
+
private final IPolicyEvaluationService policyEvaluationService;
|
| 22 |
+
|
| 23 |
+
public AssetChangeEventListener(IPolicyEvaluationService policyEvaluationService) {
|
| 24 |
+
this.policyEvaluationService = policyEvaluationService;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
@KafkaListener(
|
| 28 |
+
topics = "#{'${app.kafka.topic.asset-change-event}'}",
|
| 29 |
+
groupId = "#{'${spring.kafka.consumer.group-id}'}"
|
| 30 |
+
// containerFactory = "assetChangeKafkaListenerContainerFactory" // If using custom factory
|
| 31 |
+
)
|
| 32 |
+
public void handleAssetChangeEvent(
|
| 33 |
+
@Payload AssetChangeEvent event,
|
| 34 |
+
@Header(KafkaHeaders.RECEIVED_TOPIC) String topic,
|
| 35 |
+
@Header(KafkaHeaders.RECEIVED_PARTITION) int partition,
|
| 36 |
+
@Header(KafkaHeaders.OFFSET) long offset
|
| 37 |
+
) {
|
| 38 |
+
LOGGER.info(
|
| 39 |
+
"Received AssetChangeEvent on topic: {}, partition: {}, offset: {}: Asset ID: {}, EventType: {}",
|
| 40 |
+
topic, partition, offset, event.getAssetId(), event.getEventType()
|
| 41 |
+
);
|
| 42 |
+
|
| 43 |
+
try {
|
| 44 |
+
// Trigger policy evaluation based on the asset change
|
| 45 |
+
UUID initiatorUuid = null;
|
| 46 |
+
if (event.getUserId() != null && !event.getUserId().isEmpty()) {
|
| 47 |
+
try {
|
| 48 |
+
initiatorUuid = UUID.fromString(event.getUserId());
|
| 49 |
+
} catch (IllegalArgumentException e) {
|
| 50 |
+
LOGGER.warn("Could not parse userId '{}' from AssetChangeEvent to UUID. Proceeding with null initiator.", event.getUserId(), e);
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
policyEvaluationService.evaluatePolicyForAssetInternal(event, initiatorUuid);
|
| 54 |
+
LOGGER.debug("Successfully processed AssetChangeEvent for assetId: {}", event.getAssetId());
|
| 55 |
+
} catch (Exception e) {
|
| 56 |
+
// TODO: Implement proper error handling and dead-letter queue (DLQ) strategy
|
| 57 |
+
LOGGER.error("Error processing AssetChangeEvent for assetId: {}. Error: {}", event.getAssetId(), e.getMessage(), e);
|
| 58 |
+
// Depending on the error, you might rethrow to trigger Kafka's error handlers, or send to DLQ
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
}
|
src/main/java/com/dalab/policyengine/kafka/producer/PolicyActionKafkaProducer.java
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.kafka.producer;
|
| 2 |
+
|
| 3 |
+
import java.util.concurrent.CompletableFuture;
|
| 4 |
+
|
| 5 |
+
import org.slf4j.Logger;
|
| 6 |
+
import org.slf4j.LoggerFactory;
|
| 7 |
+
import org.springframework.beans.factory.annotation.Value;
|
| 8 |
+
import org.springframework.kafka.core.KafkaTemplate;
|
| 9 |
+
import org.springframework.kafka.support.SendResult;
|
| 10 |
+
import org.springframework.stereotype.Component;
|
| 11 |
+
|
| 12 |
+
import com.dalab.policyengine.event.PolicyActionEvent;
|
| 13 |
+
|
| 14 |
+
@Component
|
| 15 |
+
public class PolicyActionKafkaProducer {
|
| 16 |
+
|
| 17 |
+
private static final Logger LOGGER = LoggerFactory.getLogger(PolicyActionKafkaProducer.class);
|
| 18 |
+
|
| 19 |
+
private final KafkaTemplate<String, PolicyActionEvent> kafkaTemplate;
|
| 20 |
+
|
| 21 |
+
@Value("${app.kafka.topic.policy-action-event}")
|
| 22 |
+
private String topicName;
|
| 23 |
+
|
| 24 |
+
public PolicyActionKafkaProducer(KafkaTemplate<String, PolicyActionEvent> kafkaTemplate) {
|
| 25 |
+
this.kafkaTemplate = kafkaTemplate;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
public void sendPolicyActionEvent(PolicyActionEvent event) {
|
| 29 |
+
LOGGER.info("Sending PolicyActionEvent with eventId: {} to topic: {}", event.getEventId(), topicName);
|
| 30 |
+
|
| 31 |
+
String eventKey = event.getTargetAssetId();
|
| 32 |
+
if (eventKey == null || eventKey.isEmpty()) {
|
| 33 |
+
eventKey = event.getPolicyId();
|
| 34 |
+
}
|
| 35 |
+
final String finalEventKey = eventKey;
|
| 36 |
+
|
| 37 |
+
CompletableFuture<SendResult<String, PolicyActionEvent>> future = kafkaTemplate.send(topicName, finalEventKey, event);
|
| 38 |
+
|
| 39 |
+
future.whenComplete((result, ex) -> {
|
| 40 |
+
if (ex == null) {
|
| 41 |
+
LOGGER.info(
|
| 42 |
+
"Successfully sent PolicyActionEvent [eventId: {}, key: {}] with offset: {}",
|
| 43 |
+
event.getEventId(), finalEventKey, result.getRecordMetadata().offset()
|
| 44 |
+
);
|
| 45 |
+
} else {
|
| 46 |
+
LOGGER.error(
|
| 47 |
+
"Failed to send PolicyActionEvent [eventId: {}, key: {}]: {}",
|
| 48 |
+
event.getEventId(), finalEventKey, ex.getMessage(), ex
|
| 49 |
+
);
|
| 50 |
+
// TODO: Handle send failure (e.g., retry, DLQ, persistent store for later retry)
|
| 51 |
+
}
|
| 52 |
+
});
|
| 53 |
+
}
|
| 54 |
+
}
|
src/main/java/com/dalab/policyengine/kafka/producer/PolicyActionProducer.java
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.kafka.producer;
|
| 2 |
+
|
| 3 |
+
import java.util.Map;
|
| 4 |
+
|
| 5 |
+
import org.slf4j.Logger;
|
| 6 |
+
import org.slf4j.LoggerFactory;
|
| 7 |
+
import org.springframework.beans.factory.annotation.Autowired;
|
| 8 |
+
import org.springframework.beans.factory.annotation.Value;
|
| 9 |
+
import org.springframework.kafka.core.KafkaTemplate;
|
| 10 |
+
import org.springframework.stereotype.Service;
|
| 11 |
+
|
| 12 |
+
@Service
|
| 13 |
+
public class PolicyActionProducer {
|
| 14 |
+
|
| 15 |
+
private static final Logger log = LoggerFactory.getLogger(PolicyActionProducer.class);
|
| 16 |
+
|
| 17 |
+
@Value("${app.kafka.topic.policy-action-event:policy-action-events}")
|
| 18 |
+
private String policyActionEventTopic;
|
| 19 |
+
|
| 20 |
+
// Use generic KafkaTemplate since we're sending Map-based events for now
|
| 21 |
+
private final KafkaTemplate<String, Object> kafkaTemplate;
|
| 22 |
+
|
| 23 |
+
@Autowired
|
| 24 |
+
public PolicyActionProducer(KafkaTemplate<String, Object> kafkaTemplate) {
|
| 25 |
+
this.kafkaTemplate = kafkaTemplate;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
// Method to send policy action events as Map objects for now
|
| 29 |
+
public void sendPolicyActionEvent(Map<String, Object> event) {
|
| 30 |
+
try {
|
| 31 |
+
String assetId = (String) event.get("assetId");
|
| 32 |
+
String actionType = (String) event.get("actionType");
|
| 33 |
+
log.info("Sending PolicyActionEvent to topic '{}': AssetId={}, ActionType={}",
|
| 34 |
+
policyActionEventTopic, assetId, actionType);
|
| 35 |
+
// Use assetId as key for partitioning
|
| 36 |
+
kafkaTemplate.send(policyActionEventTopic, assetId, event);
|
| 37 |
+
} catch (Exception e) {
|
| 38 |
+
String assetId = event != null ? (String) event.get("assetId") : "unknown";
|
| 39 |
+
log.error("Error sending PolicyActionEvent to Kafka for assetId {}: {}", assetId, e.getMessage(), e);
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
}
|
src/main/java/com/dalab/policyengine/mapper/PolicyDraftMapper.java
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.mapper;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.time.temporal.ChronoUnit;
|
| 5 |
+
import java.util.ArrayList;
|
| 6 |
+
import java.util.Arrays;
|
| 7 |
+
import java.util.List;
|
| 8 |
+
|
| 9 |
+
import org.springframework.stereotype.Component;
|
| 10 |
+
|
| 11 |
+
import com.dalab.policyengine.dto.PolicyDraftInputDTO;
|
| 12 |
+
import com.dalab.policyengine.dto.PolicyDraftOutputDTO;
|
| 13 |
+
import com.dalab.policyengine.model.PolicyDraft;
|
| 14 |
+
import com.dalab.policyengine.model.PolicyDraftStatus;
|
| 15 |
+
|
| 16 |
+
/**
|
| 17 |
+
* Mapper for converting between PolicyDraft entities and DTOs.
|
| 18 |
+
* Handles workflow status calculation and available actions based on current status and user permissions.
|
| 19 |
+
*/
|
| 20 |
+
@Component
|
| 21 |
+
public class PolicyDraftMapper {
|
| 22 |
+
|
| 23 |
+
/**
|
| 24 |
+
* Convert PolicyDraft entity to output DTO with workflow information.
|
| 25 |
+
*/
|
| 26 |
+
public PolicyDraftOutputDTO toOutputDTO(PolicyDraft draft) {
|
| 27 |
+
if (draft == null) {
|
| 28 |
+
return null;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
PolicyDraftOutputDTO dto = new PolicyDraftOutputDTO();
|
| 32 |
+
|
| 33 |
+
// Basic information
|
| 34 |
+
dto.setId(draft.getId());
|
| 35 |
+
dto.setName(draft.getName());
|
| 36 |
+
dto.setDescription(draft.getDescription());
|
| 37 |
+
dto.setStatus(draft.getStatus().name());
|
| 38 |
+
dto.setVersion(draft.getVersion());
|
| 39 |
+
dto.setBasePolicyId(draft.getBasePolicyId());
|
| 40 |
+
dto.setConditionLogic(draft.getConditionLogic());
|
| 41 |
+
dto.setRulesDefinition(draft.getRulesDefinition());
|
| 42 |
+
dto.setActions(draft.getActions());
|
| 43 |
+
dto.setChangeSummary(draft.getChangeSummary());
|
| 44 |
+
dto.setJustification(draft.getJustification());
|
| 45 |
+
dto.setExpectedImpact(draft.getExpectedImpact());
|
| 46 |
+
dto.setTargetImplementationDate(draft.getTargetImplementationDate());
|
| 47 |
+
dto.setPriority(draft.getPriority());
|
| 48 |
+
dto.setCategory(draft.getCategory());
|
| 49 |
+
dto.setTags(draft.getTags());
|
| 50 |
+
dto.setStakeholders(draft.getStakeholders());
|
| 51 |
+
dto.setApprovalMetadata(draft.getApprovalMetadata());
|
| 52 |
+
dto.setReviewComments(draft.getReviewComments());
|
| 53 |
+
|
| 54 |
+
// Audit trail
|
| 55 |
+
dto.setCreatedAt(draft.getCreatedAt());
|
| 56 |
+
dto.setUpdatedAt(draft.getUpdatedAt());
|
| 57 |
+
dto.setCreatedByUserId(draft.getCreatedByUserId());
|
| 58 |
+
dto.setUpdatedByUserId(draft.getUpdatedByUserId());
|
| 59 |
+
dto.setSubmittedAt(draft.getSubmittedAt());
|
| 60 |
+
dto.setSubmittedByUserId(draft.getSubmittedByUserId());
|
| 61 |
+
dto.setApprovedAt(draft.getApprovedAt());
|
| 62 |
+
dto.setApprovedByUserId(draft.getApprovedByUserId());
|
| 63 |
+
dto.setRejectedAt(draft.getRejectedAt());
|
| 64 |
+
dto.setRejectedByUserId(draft.getRejectedByUserId());
|
| 65 |
+
dto.setPublishedAt(draft.getPublishedAt());
|
| 66 |
+
dto.setPublishedByUserId(draft.getPublishedByUserId());
|
| 67 |
+
|
| 68 |
+
// Enhanced workflow information
|
| 69 |
+
dto.setWorkflowStatus(createWorkflowStatus(draft));
|
| 70 |
+
dto.setAvailableActions(createAvailableActions(draft));
|
| 71 |
+
|
| 72 |
+
return dto;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
/**
|
| 76 |
+
* Convert input DTO to PolicyDraft entity.
|
| 77 |
+
*/
|
| 78 |
+
public PolicyDraft toEntity(PolicyDraftInputDTO inputDTO) {
|
| 79 |
+
if (inputDTO == null) {
|
| 80 |
+
return null;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
PolicyDraft draft = new PolicyDraft();
|
| 84 |
+
|
| 85 |
+
draft.setName(inputDTO.getName());
|
| 86 |
+
draft.setDescription(inputDTO.getDescription());
|
| 87 |
+
draft.setBasePolicyId(inputDTO.getBasePolicyId());
|
| 88 |
+
draft.setConditionLogic(inputDTO.getConditionLogic());
|
| 89 |
+
draft.setRulesDefinition(inputDTO.getRulesDefinition());
|
| 90 |
+
draft.setActions(inputDTO.getActions());
|
| 91 |
+
draft.setChangeSummary(inputDTO.getChangeSummary());
|
| 92 |
+
draft.setJustification(inputDTO.getJustification());
|
| 93 |
+
draft.setExpectedImpact(inputDTO.getExpectedImpact());
|
| 94 |
+
draft.setTargetImplementationDate(inputDTO.getTargetImplementationDate());
|
| 95 |
+
draft.setPriority(inputDTO.getPriority());
|
| 96 |
+
draft.setCategory(inputDTO.getCategory());
|
| 97 |
+
|
| 98 |
+
if (inputDTO.getTags() != null) {
|
| 99 |
+
draft.setTags(new ArrayList<>(inputDTO.getTags()));
|
| 100 |
+
}
|
| 101 |
+
if (inputDTO.getStakeholders() != null) {
|
| 102 |
+
draft.setStakeholders(new ArrayList<>(inputDTO.getStakeholders()));
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
return draft;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
/**
|
| 109 |
+
* Update entity from input DTO (for updates).
|
| 110 |
+
*/
|
| 111 |
+
public void updateEntity(PolicyDraft draft, PolicyDraftInputDTO inputDTO) {
|
| 112 |
+
if (draft == null || inputDTO == null) {
|
| 113 |
+
return;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
draft.setName(inputDTO.getName());
|
| 117 |
+
draft.setDescription(inputDTO.getDescription());
|
| 118 |
+
draft.setBasePolicyId(inputDTO.getBasePolicyId());
|
| 119 |
+
draft.setConditionLogic(inputDTO.getConditionLogic());
|
| 120 |
+
draft.setRulesDefinition(inputDTO.getRulesDefinition());
|
| 121 |
+
draft.setActions(inputDTO.getActions());
|
| 122 |
+
draft.setChangeSummary(inputDTO.getChangeSummary());
|
| 123 |
+
draft.setJustification(inputDTO.getJustification());
|
| 124 |
+
draft.setExpectedImpact(inputDTO.getExpectedImpact());
|
| 125 |
+
draft.setTargetImplementationDate(inputDTO.getTargetImplementationDate());
|
| 126 |
+
draft.setPriority(inputDTO.getPriority());
|
| 127 |
+
draft.setCategory(inputDTO.getCategory());
|
| 128 |
+
|
| 129 |
+
if (inputDTO.getTags() != null) {
|
| 130 |
+
draft.getTags().clear();
|
| 131 |
+
draft.getTags().addAll(inputDTO.getTags());
|
| 132 |
+
}
|
| 133 |
+
if (inputDTO.getStakeholders() != null) {
|
| 134 |
+
draft.getStakeholders().clear();
|
| 135 |
+
draft.getStakeholders().addAll(inputDTO.getStakeholders());
|
| 136 |
+
}
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
/**
|
| 140 |
+
* Create workflow status information for the draft.
|
| 141 |
+
*/
|
| 142 |
+
private PolicyDraftOutputDTO.WorkflowStatusDTO createWorkflowStatus(PolicyDraft draft) {
|
| 143 |
+
PolicyDraftOutputDTO.WorkflowStatusDTO status = new PolicyDraftOutputDTO.WorkflowStatusDTO();
|
| 144 |
+
|
| 145 |
+
PolicyDraftStatus currentStatus = draft.getStatus();
|
| 146 |
+
status.setCurrentStage(currentStatus.name());
|
| 147 |
+
status.setStatusDescription(getStatusDescription(currentStatus));
|
| 148 |
+
status.setNextPossibleStates(getNextPossibleStates(currentStatus));
|
| 149 |
+
status.setStageColor(getStageColor(currentStatus));
|
| 150 |
+
|
| 151 |
+
// Calculate days in current status
|
| 152 |
+
Instant statusChangeTime = getLastStatusChangeTime(draft, currentStatus);
|
| 153 |
+
if (statusChangeTime != null) {
|
| 154 |
+
long days = ChronoUnit.DAYS.between(statusChangeTime, Instant.now());
|
| 155 |
+
status.setDaysInCurrentStatus((int) days);
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
// Set permission flags (simplified - would integrate with security context in real implementation)
|
| 159 |
+
status.setCanEdit(canEdit(currentStatus));
|
| 160 |
+
status.setCanSubmit(canSubmit(currentStatus));
|
| 161 |
+
status.setCanApprove(canApprove(currentStatus));
|
| 162 |
+
status.setCanReject(canReject(currentStatus));
|
| 163 |
+
status.setCanPublish(canPublish(currentStatus));
|
| 164 |
+
|
| 165 |
+
return status;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
/**
|
| 169 |
+
* Create available workflow actions for the draft.
|
| 170 |
+
*/
|
| 171 |
+
private List<PolicyDraftOutputDTO.WorkflowActionDTO> createAvailableActions(PolicyDraft draft) {
|
| 172 |
+
List<PolicyDraftOutputDTO.WorkflowActionDTO> actions = new ArrayList<>();
|
| 173 |
+
PolicyDraftStatus status = draft.getStatus();
|
| 174 |
+
|
| 175 |
+
switch (status) {
|
| 176 |
+
case CREATED:
|
| 177 |
+
case REQUIRES_CHANGES:
|
| 178 |
+
actions.add(new PolicyDraftOutputDTO.WorkflowActionDTO("SUBMIT", "Submit for Review"));
|
| 179 |
+
actions.add(new PolicyDraftOutputDTO.WorkflowActionDTO("ARCHIVE", "Archive Draft"));
|
| 180 |
+
break;
|
| 181 |
+
case SUBMITTED:
|
| 182 |
+
case UNDER_REVIEW:
|
| 183 |
+
actions.add(new PolicyDraftOutputDTO.WorkflowActionDTO("APPROVE", "Approve Draft"));
|
| 184 |
+
actions.add(new PolicyDraftOutputDTO.WorkflowActionDTO("REJECT", "Reject Draft"));
|
| 185 |
+
actions.add(new PolicyDraftOutputDTO.WorkflowActionDTO("REQUEST_CHANGES", "Request Changes"));
|
| 186 |
+
break;
|
| 187 |
+
case APPROVED:
|
| 188 |
+
actions.add(new PolicyDraftOutputDTO.WorkflowActionDTO("PUBLISH", "Publish Policy"));
|
| 189 |
+
actions.add(new PolicyDraftOutputDTO.WorkflowActionDTO("REJECT", "Reject Draft"));
|
| 190 |
+
break;
|
| 191 |
+
default:
|
| 192 |
+
// No actions available for REJECTED, PUBLISHED, ARCHIVED
|
| 193 |
+
break;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
// Set action properties
|
| 197 |
+
for (PolicyDraftOutputDTO.WorkflowActionDTO action : actions) {
|
| 198 |
+
setActionProperties(action);
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
return actions;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
/**
|
| 205 |
+
* Get human-readable description for status.
|
| 206 |
+
*/
|
| 207 |
+
private String getStatusDescription(PolicyDraftStatus status) {
|
| 208 |
+
switch (status) {
|
| 209 |
+
case CREATED:
|
| 210 |
+
return "Draft has been created and is ready for editing";
|
| 211 |
+
case SUBMITTED:
|
| 212 |
+
return "Draft has been submitted and is awaiting review";
|
| 213 |
+
case UNDER_REVIEW:
|
| 214 |
+
return "Draft is currently being reviewed";
|
| 215 |
+
case REQUIRES_CHANGES:
|
| 216 |
+
return "Draft requires changes based on reviewer feedback";
|
| 217 |
+
case APPROVED:
|
| 218 |
+
return "Draft has been approved and is ready for publication";
|
| 219 |
+
case REJECTED:
|
| 220 |
+
return "Draft has been rejected and will not be published";
|
| 221 |
+
case PUBLISHED:
|
| 222 |
+
return "Draft has been published as an active policy";
|
| 223 |
+
case ARCHIVED:
|
| 224 |
+
return "Draft has been archived and is no longer active";
|
| 225 |
+
default:
|
| 226 |
+
return "Unknown status";
|
| 227 |
+
}
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
/**
|
| 231 |
+
* Get next possible states for workflow transitions.
|
| 232 |
+
*/
|
| 233 |
+
private List<String> getNextPossibleStates(PolicyDraftStatus status) {
|
| 234 |
+
switch (status) {
|
| 235 |
+
case CREATED:
|
| 236 |
+
case REQUIRES_CHANGES:
|
| 237 |
+
return Arrays.asList("SUBMITTED", "ARCHIVED");
|
| 238 |
+
case SUBMITTED:
|
| 239 |
+
return Arrays.asList("UNDER_REVIEW", "APPROVED", "REJECTED", "REQUIRES_CHANGES");
|
| 240 |
+
case UNDER_REVIEW:
|
| 241 |
+
return Arrays.asList("APPROVED", "REJECTED", "REQUIRES_CHANGES");
|
| 242 |
+
case APPROVED:
|
| 243 |
+
return Arrays.asList("PUBLISHED", "REJECTED");
|
| 244 |
+
default:
|
| 245 |
+
return new ArrayList<>(); // Terminal states
|
| 246 |
+
}
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
/**
|
| 250 |
+
* Get color for UI status indicators.
|
| 251 |
+
*/
|
| 252 |
+
private String getStageColor(PolicyDraftStatus status) {
|
| 253 |
+
switch (status) {
|
| 254 |
+
case CREATED:
|
| 255 |
+
return "blue";
|
| 256 |
+
case SUBMITTED:
|
| 257 |
+
case UNDER_REVIEW:
|
| 258 |
+
return "orange";
|
| 259 |
+
case REQUIRES_CHANGES:
|
| 260 |
+
return "yellow";
|
| 261 |
+
case APPROVED:
|
| 262 |
+
return "green";
|
| 263 |
+
case REJECTED:
|
| 264 |
+
return "red";
|
| 265 |
+
case PUBLISHED:
|
| 266 |
+
return "purple";
|
| 267 |
+
case ARCHIVED:
|
| 268 |
+
return "gray";
|
| 269 |
+
default:
|
| 270 |
+
return "gray";
|
| 271 |
+
}
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
/**
|
| 275 |
+
* Get the timestamp of last status change.
|
| 276 |
+
*/
|
| 277 |
+
private Instant getLastStatusChangeTime(PolicyDraft draft, PolicyDraftStatus currentStatus) {
|
| 278 |
+
switch (currentStatus) {
|
| 279 |
+
case SUBMITTED:
|
| 280 |
+
return draft.getSubmittedAt();
|
| 281 |
+
case APPROVED:
|
| 282 |
+
return draft.getApprovedAt();
|
| 283 |
+
case REJECTED:
|
| 284 |
+
return draft.getRejectedAt();
|
| 285 |
+
case PUBLISHED:
|
| 286 |
+
return draft.getPublishedAt();
|
| 287 |
+
default:
|
| 288 |
+
return draft.getUpdatedAt();
|
| 289 |
+
}
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
/**
|
| 293 |
+
* Check if draft can be edited in current status.
|
| 294 |
+
*/
|
| 295 |
+
private boolean canEdit(PolicyDraftStatus status) {
|
| 296 |
+
return status == PolicyDraftStatus.CREATED || status == PolicyDraftStatus.REQUIRES_CHANGES;
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
/**
|
| 300 |
+
* Check if draft can be submitted in current status.
|
| 301 |
+
*/
|
| 302 |
+
private boolean canSubmit(PolicyDraftStatus status) {
|
| 303 |
+
return status == PolicyDraftStatus.CREATED || status == PolicyDraftStatus.REQUIRES_CHANGES;
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
/**
|
| 307 |
+
* Check if draft can be approved in current status.
|
| 308 |
+
*/
|
| 309 |
+
private boolean canApprove(PolicyDraftStatus status) {
|
| 310 |
+
return status == PolicyDraftStatus.SUBMITTED || status == PolicyDraftStatus.UNDER_REVIEW;
|
| 311 |
+
}
|
| 312 |
+
|
| 313 |
+
/**
|
| 314 |
+
* Check if draft can be rejected in current status.
|
| 315 |
+
*/
|
| 316 |
+
private boolean canReject(PolicyDraftStatus status) {
|
| 317 |
+
return status == PolicyDraftStatus.SUBMITTED ||
|
| 318 |
+
status == PolicyDraftStatus.UNDER_REVIEW ||
|
| 319 |
+
status == PolicyDraftStatus.APPROVED;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
/**
|
| 323 |
+
* Check if draft can be published in current status.
|
| 324 |
+
*/
|
| 325 |
+
private boolean canPublish(PolicyDraftStatus status) {
|
| 326 |
+
return status == PolicyDraftStatus.APPROVED;
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
/**
|
| 330 |
+
* Set properties for workflow actions.
|
| 331 |
+
*/
|
| 332 |
+
private void setActionProperties(PolicyDraftOutputDTO.WorkflowActionDTO action) {
|
| 333 |
+
switch (action.getActionType()) {
|
| 334 |
+
case "SUBMIT":
|
| 335 |
+
action.setActionDescription("Submit the draft for review by approvers");
|
| 336 |
+
action.setRequiresComment(false);
|
| 337 |
+
action.setConfirmationMessage("Are you sure you want to submit this draft for review?");
|
| 338 |
+
action.setButtonStyle("primary");
|
| 339 |
+
break;
|
| 340 |
+
case "APPROVE":
|
| 341 |
+
action.setActionDescription("Approve the draft for publication");
|
| 342 |
+
action.setRequiresComment(false);
|
| 343 |
+
action.setConfirmationMessage("Are you sure you want to approve this draft?");
|
| 344 |
+
action.setButtonStyle("success");
|
| 345 |
+
break;
|
| 346 |
+
case "REJECT":
|
| 347 |
+
action.setActionDescription("Reject the draft and prevent publication");
|
| 348 |
+
action.setRequiresComment(true);
|
| 349 |
+
action.setConfirmationMessage("Are you sure you want to reject this draft? This action cannot be undone.");
|
| 350 |
+
action.setButtonStyle("danger");
|
| 351 |
+
break;
|
| 352 |
+
case "REQUEST_CHANGES":
|
| 353 |
+
action.setActionDescription("Request changes from the draft author");
|
| 354 |
+
action.setRequiresComment(true);
|
| 355 |
+
action.setConfirmationMessage("Please provide details about the required changes");
|
| 356 |
+
action.setButtonStyle("warning");
|
| 357 |
+
break;
|
| 358 |
+
case "PUBLISH":
|
| 359 |
+
action.setActionDescription("Publish the draft as an active policy");
|
| 360 |
+
action.setRequiresComment(false);
|
| 361 |
+
action.setConfirmationMessage("Are you sure you want to publish this draft as an active policy?");
|
| 362 |
+
action.setButtonStyle("success");
|
| 363 |
+
break;
|
| 364 |
+
case "ARCHIVE":
|
| 365 |
+
action.setActionDescription("Archive the draft");
|
| 366 |
+
action.setRequiresComment(false);
|
| 367 |
+
action.setConfirmationMessage("Are you sure you want to archive this draft?");
|
| 368 |
+
action.setButtonStyle("secondary");
|
| 369 |
+
break;
|
| 370 |
+
}
|
| 371 |
+
}
|
| 372 |
+
}
|
src/main/java/com/dalab/policyengine/mapper/PolicyMapper.java
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.mapper;
|
| 2 |
+
|
| 3 |
+
import java.util.Collections;
|
| 4 |
+
import java.util.UUID;
|
| 5 |
+
import java.util.stream.Collectors;
|
| 6 |
+
|
| 7 |
+
import org.springframework.stereotype.Component;
|
| 8 |
+
|
| 9 |
+
import com.dalab.policyengine.dto.PolicyEvaluationOutputDTO;
|
| 10 |
+
import com.dalab.policyengine.dto.PolicyEvaluationSummaryDTO;
|
| 11 |
+
// Add missing DTO imports
|
| 12 |
+
import com.dalab.policyengine.dto.PolicyInputDTO;
|
| 13 |
+
import com.dalab.policyengine.dto.PolicyOutputDTO;
|
| 14 |
+
import com.dalab.policyengine.dto.PolicyRuleDTO;
|
| 15 |
+
import com.dalab.policyengine.dto.PolicySummaryDTO;
|
| 16 |
+
// Add missing entity imports
|
| 17 |
+
import com.dalab.policyengine.model.Policy;
|
| 18 |
+
import com.dalab.policyengine.model.PolicyEvaluation;
|
| 19 |
+
import com.dalab.policyengine.model.PolicyEvaluationStatus;
|
| 20 |
+
import com.dalab.policyengine.model.PolicyRule;
|
| 21 |
+
|
| 22 |
+
@Component
|
| 23 |
+
public class PolicyMapper {
|
| 24 |
+
|
| 25 |
+
public PolicySummaryDTO toPolicySummaryDTO(Policy policy) {
|
| 26 |
+
if (policy == null) return null;
|
| 27 |
+
PolicySummaryDTO dto = new PolicySummaryDTO();
|
| 28 |
+
dto.setId(policy.getId());
|
| 29 |
+
dto.setName(policy.getName());
|
| 30 |
+
dto.setDescription(policy.getDescription());
|
| 31 |
+
dto.setStatus(policy.getStatus());
|
| 32 |
+
dto.setRuleCount(policy.getRules() != null ? policy.getRules().size() : 0);
|
| 33 |
+
dto.setCreatedAt(policy.getCreatedAt());
|
| 34 |
+
dto.setUpdatedAt(policy.getUpdatedAt());
|
| 35 |
+
return dto;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
public PolicyOutputDTO toPolicyOutputDTO(Policy policy) {
|
| 39 |
+
if (policy == null) return null;
|
| 40 |
+
PolicyOutputDTO dto = new PolicyOutputDTO();
|
| 41 |
+
dto.setId(policy.getId());
|
| 42 |
+
dto.setName(policy.getName());
|
| 43 |
+
dto.setDescription(policy.getDescription());
|
| 44 |
+
dto.setStatus(policy.getStatus());
|
| 45 |
+
dto.setConditionLogic(policy.getConditionLogic());
|
| 46 |
+
dto.setActions(policy.getActions());
|
| 47 |
+
dto.setRules(policy.getRules().stream().map(this::toPolicyRuleDTO).collect(Collectors.toList()));
|
| 48 |
+
dto.setCreatedAt(policy.getCreatedAt());
|
| 49 |
+
dto.setUpdatedAt(policy.getUpdatedAt());
|
| 50 |
+
dto.setCreatedByUserId(policy.getCreatedByUserId());
|
| 51 |
+
dto.setUpdatedByUserId(policy.getUpdatedByUserId());
|
| 52 |
+
return dto;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
public PolicyRuleDTO toPolicyRuleDTO(PolicyRule policyRule) {
|
| 56 |
+
if (policyRule == null) return null;
|
| 57 |
+
PolicyRuleDTO dto = new PolicyRuleDTO();
|
| 58 |
+
dto.setId(policyRule.getId() != null ? policyRule.getId().toString() : null);
|
| 59 |
+
dto.setName(policyRule.getName());
|
| 60 |
+
dto.setDescription(policyRule.getDescription());
|
| 61 |
+
dto.setCondition(policyRule.getCondition());
|
| 62 |
+
dto.setPriority(policyRule.getPriority());
|
| 63 |
+
dto.setActions(policyRule.getActions());
|
| 64 |
+
return dto;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
public Policy toPolicyEntity(PolicyInputDTO dto) {
|
| 68 |
+
if (dto == null) return null;
|
| 69 |
+
Policy policy = new Policy();
|
| 70 |
+
updatePolicyEntityFromInputDTO(policy, dto); // Reuse logic for update
|
| 71 |
+
return policy;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
public void updatePolicyEntityFromInputDTO(Policy policy, PolicyInputDTO dto) {
|
| 75 |
+
if (policy == null || dto == null) return;
|
| 76 |
+
|
| 77 |
+
policy.setName(dto.getName());
|
| 78 |
+
policy.setDescription(dto.getDescription());
|
| 79 |
+
policy.setStatus(dto.getStatus());
|
| 80 |
+
policy.setConditionLogic(dto.getConditionLogic());
|
| 81 |
+
policy.setActions(dto.getActions());
|
| 82 |
+
|
| 83 |
+
// Handle rules update carefully
|
| 84 |
+
if (dto.getRules() != null) {
|
| 85 |
+
// Simple strategy: remove all existing and add new ones based on DTO
|
| 86 |
+
// More sophisticated merging could be done (e.g. based on rule ID or name)
|
| 87 |
+
policy.getRules().clear();
|
| 88 |
+
dto.getRules().forEach(ruleDTO -> policy.addRule(toPolicyRuleEntity(ruleDTO)));
|
| 89 |
+
} else {
|
| 90 |
+
policy.setRules(Collections.emptyList());
|
| 91 |
+
}
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
public PolicyRule toPolicyRuleEntity(PolicyRuleDTO dto) {
|
| 95 |
+
if (dto == null) return null;
|
| 96 |
+
PolicyRule rule = new PolicyRule();
|
| 97 |
+
// ID is not set here for new rules, or could be used to fetch existing if updating
|
| 98 |
+
// For simplicity, if ID is present in DTO, we assume it might be used by service layer
|
| 99 |
+
// to find and update existing rule, but mapper focuses on new entity creation or field mapping.
|
| 100 |
+
if (dto.getId() != null) {
|
| 101 |
+
try {
|
| 102 |
+
rule.setId(UUID.fromString(dto.getId()));
|
| 103 |
+
} catch (IllegalArgumentException e) {
|
| 104 |
+
// Handle invalid UUID string if necessary, or let it be null for new entity
|
| 105 |
+
}
|
| 106 |
+
}
|
| 107 |
+
rule.setName(dto.getName());
|
| 108 |
+
rule.setDescription(dto.getDescription());
|
| 109 |
+
rule.setCondition(dto.getCondition());
|
| 110 |
+
rule.setPriority(dto.getPriority());
|
| 111 |
+
rule.setActions(dto.getActions());
|
| 112 |
+
return rule;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
public PolicyEvaluationOutputDTO toPolicyEvaluationOutputDTO(PolicyEvaluation evaluation, String policyName) {
|
| 116 |
+
if (evaluation == null) return null;
|
| 117 |
+
PolicyEvaluationOutputDTO dto = new PolicyEvaluationOutputDTO();
|
| 118 |
+
dto.setId(evaluation.getId());
|
| 119 |
+
dto.setPolicyId(evaluation.getPolicyId());
|
| 120 |
+
dto.setPolicyName(policyName); // Policy name fetched separately for convenience
|
| 121 |
+
dto.setTargetAssetId(evaluation.getTargetAssetId());
|
| 122 |
+
dto.setStatus(evaluation.getStatus());
|
| 123 |
+
dto.setEvaluationDetails(evaluation.getEvaluationDetails());
|
| 124 |
+
dto.setTriggeredActions(evaluation.getTriggeredActions());
|
| 125 |
+
dto.setEvaluatedAt(evaluation.getEvaluatedAt());
|
| 126 |
+
dto.setEvaluationTriggeredByUserId(evaluation.getEvaluationTriggeredByUserId());
|
| 127 |
+
return dto;
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
public PolicyEvaluationSummaryDTO toPolicyEvaluationSummaryDTO(PolicyEvaluation evaluation, String policyName) {
|
| 131 |
+
if (evaluation == null) return null;
|
| 132 |
+
PolicyEvaluationSummaryDTO dto = new PolicyEvaluationSummaryDTO();
|
| 133 |
+
dto.setId(evaluation.getId());
|
| 134 |
+
dto.setPolicyId(evaluation.getPolicyId());
|
| 135 |
+
dto.setPolicyName(policyName);
|
| 136 |
+
dto.setTargetAssetId(evaluation.getTargetAssetId());
|
| 137 |
+
dto.setStatus(evaluation.getStatus());
|
| 138 |
+
dto.setEvaluatedAt(evaluation.getEvaluatedAt());
|
| 139 |
+
return dto;
|
| 140 |
+
}
|
| 141 |
+
}
|
src/main/java/com/dalab/policyengine/model/EventRule.java
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
import java.util.UUID;
|
| 6 |
+
|
| 7 |
+
import org.hibernate.annotations.JdbcTypeCode;
|
| 8 |
+
import org.hibernate.type.SqlTypes;
|
| 9 |
+
|
| 10 |
+
import jakarta.persistence.Column;
|
| 11 |
+
import jakarta.persistence.Entity;
|
| 12 |
+
import jakarta.persistence.FetchType;
|
| 13 |
+
import jakarta.persistence.GeneratedValue;
|
| 14 |
+
import jakarta.persistence.GenerationType;
|
| 15 |
+
import jakarta.persistence.Id;
|
| 16 |
+
import jakarta.persistence.JoinColumn;
|
| 17 |
+
import jakarta.persistence.ManyToOne;
|
| 18 |
+
import jakarta.persistence.PrePersist;
|
| 19 |
+
import jakarta.persistence.PreUpdate;
|
| 20 |
+
import jakarta.persistence.Table;
|
| 21 |
+
import jakarta.validation.constraints.NotBlank;
|
| 22 |
+
import jakarta.validation.constraints.Size;
|
| 23 |
+
|
| 24 |
+
/**
|
| 25 |
+
* Entity representing a filtering rule for event subscriptions.
|
| 26 |
+
* Uses MVEL expressions to define conditions for event matching.
|
| 27 |
+
*/
|
| 28 |
+
@Entity
|
| 29 |
+
@Table(name = "event_rules")
|
| 30 |
+
public class EventRule {
|
| 31 |
+
|
| 32 |
+
@Id
|
| 33 |
+
@GeneratedValue(strategy = GenerationType.AUTO)
|
| 34 |
+
@Column(columnDefinition = "UUID")
|
| 35 |
+
private UUID id;
|
| 36 |
+
|
| 37 |
+
@NotBlank
|
| 38 |
+
@Size(max = 255)
|
| 39 |
+
@Column(nullable = false)
|
| 40 |
+
private String name;
|
| 41 |
+
|
| 42 |
+
@Size(max = 500)
|
| 43 |
+
private String description;
|
| 44 |
+
|
| 45 |
+
@ManyToOne(fetch = FetchType.LAZY)
|
| 46 |
+
@JoinColumn(name = "subscription_id", nullable = false)
|
| 47 |
+
private EventSubscription subscription;
|
| 48 |
+
|
| 49 |
+
/**
|
| 50 |
+
* MVEL expression for evaluating events
|
| 51 |
+
* Example: "eventType == 'POLICY_VIOLATION' && severity == 'HIGH' && assetId.startsWith('prod-')"
|
| 52 |
+
*/
|
| 53 |
+
@Column(columnDefinition = "TEXT", nullable = false)
|
| 54 |
+
private String condition;
|
| 55 |
+
|
| 56 |
+
/**
|
| 57 |
+
* Rule priority (lower number = higher priority)
|
| 58 |
+
*/
|
| 59 |
+
@Column(nullable = false)
|
| 60 |
+
private Integer priority = 1;
|
| 61 |
+
|
| 62 |
+
/**
|
| 63 |
+
* Whether this rule is enabled
|
| 64 |
+
*/
|
| 65 |
+
@Column(nullable = false)
|
| 66 |
+
private Boolean enabled = true;
|
| 67 |
+
|
| 68 |
+
/**
|
| 69 |
+
* Additional parameters for the rule
|
| 70 |
+
*/
|
| 71 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 72 |
+
@Column(columnDefinition = "jsonb")
|
| 73 |
+
private Map<String, Object> parameters;
|
| 74 |
+
|
| 75 |
+
@Column(nullable = false, updatable = false)
|
| 76 |
+
private Instant createdAt;
|
| 77 |
+
|
| 78 |
+
private Instant updatedAt;
|
| 79 |
+
|
| 80 |
+
@Column(columnDefinition = "UUID")
|
| 81 |
+
private UUID createdByUserId;
|
| 82 |
+
|
| 83 |
+
@Column(columnDefinition = "UUID")
|
| 84 |
+
private UUID updatedByUserId;
|
| 85 |
+
|
| 86 |
+
// Constructors
|
| 87 |
+
public EventRule() {}
|
| 88 |
+
|
| 89 |
+
public EventRule(String name, String condition) {
|
| 90 |
+
this.name = name;
|
| 91 |
+
this.condition = condition;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
// Getters and Setters
|
| 95 |
+
|
| 96 |
+
public UUID getId() {
|
| 97 |
+
return id;
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
public void setId(UUID id) {
|
| 101 |
+
this.id = id;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
public String getName() {
|
| 105 |
+
return name;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
public void setName(String name) {
|
| 109 |
+
this.name = name;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
public String getDescription() {
|
| 113 |
+
return description;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
public void setDescription(String description) {
|
| 117 |
+
this.description = description;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
public EventSubscription getSubscription() {
|
| 121 |
+
return subscription;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
public void setSubscription(EventSubscription subscription) {
|
| 125 |
+
this.subscription = subscription;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
public String getCondition() {
|
| 129 |
+
return condition;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
public void setCondition(String condition) {
|
| 133 |
+
this.condition = condition;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
public Integer getPriority() {
|
| 137 |
+
return priority;
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
public void setPriority(Integer priority) {
|
| 141 |
+
this.priority = priority;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
public Boolean getEnabled() {
|
| 145 |
+
return enabled;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
public void setEnabled(Boolean enabled) {
|
| 149 |
+
this.enabled = enabled;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
public Map<String, Object> getParameters() {
|
| 153 |
+
return parameters;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
public void setParameters(Map<String, Object> parameters) {
|
| 157 |
+
this.parameters = parameters;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
public Instant getCreatedAt() {
|
| 161 |
+
return createdAt;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
public void setCreatedAt(Instant createdAt) {
|
| 165 |
+
this.createdAt = createdAt;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
public Instant getUpdatedAt() {
|
| 169 |
+
return updatedAt;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 173 |
+
this.updatedAt = updatedAt;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
public UUID getCreatedByUserId() {
|
| 177 |
+
return createdByUserId;
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
public void setCreatedByUserId(UUID createdByUserId) {
|
| 181 |
+
this.createdByUserId = createdByUserId;
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
public UUID getUpdatedByUserId() {
|
| 185 |
+
return updatedByUserId;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
public void setUpdatedByUserId(UUID updatedByUserId) {
|
| 189 |
+
this.updatedByUserId = updatedByUserId;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
@PrePersist
|
| 193 |
+
protected void onCreate() {
|
| 194 |
+
createdAt = Instant.now();
|
| 195 |
+
updatedAt = Instant.now();
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
@PreUpdate
|
| 199 |
+
protected void onUpdate() {
|
| 200 |
+
updatedAt = Instant.now();
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
@Override
|
| 204 |
+
public boolean equals(Object o) {
|
| 205 |
+
if (this == o) return true;
|
| 206 |
+
if (!(o instanceof EventRule)) return false;
|
| 207 |
+
EventRule eventRule = (EventRule) o;
|
| 208 |
+
return id != null && id.equals(eventRule.getId());
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
@Override
|
| 212 |
+
public int hashCode() {
|
| 213 |
+
return getClass().hashCode();
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
@Override
|
| 217 |
+
public String toString() {
|
| 218 |
+
return "EventRule{" +
|
| 219 |
+
"id=" + id +
|
| 220 |
+
", name='" + name + '\'' +
|
| 221 |
+
", condition='" + condition + '\'' +
|
| 222 |
+
", priority=" + priority +
|
| 223 |
+
", enabled=" + enabled +
|
| 224 |
+
'}';
|
| 225 |
+
}
|
| 226 |
+
}
|
src/main/java/com/dalab/policyengine/model/EventSeverity.java
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Enumeration representing the severity levels of events in the DALab platform.
|
| 5 |
+
*/
|
| 6 |
+
public enum EventSeverity {
|
| 7 |
+
/**
|
| 8 |
+
* Critical severity - immediate attention required
|
| 9 |
+
*/
|
| 10 |
+
CRITICAL,
|
| 11 |
+
|
| 12 |
+
/**
|
| 13 |
+
* High severity - urgent attention required
|
| 14 |
+
*/
|
| 15 |
+
HIGH,
|
| 16 |
+
|
| 17 |
+
/**
|
| 18 |
+
* Medium severity - attention required
|
| 19 |
+
*/
|
| 20 |
+
MEDIUM,
|
| 21 |
+
|
| 22 |
+
/**
|
| 23 |
+
* Low severity - informational
|
| 24 |
+
*/
|
| 25 |
+
LOW,
|
| 26 |
+
|
| 27 |
+
/**
|
| 28 |
+
* Informational - for logging and tracking purposes
|
| 29 |
+
*/
|
| 30 |
+
INFO
|
| 31 |
+
}
|
src/main/java/com/dalab/policyengine/model/EventSubscription.java
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.ArrayList;
|
| 5 |
+
import java.util.List;
|
| 6 |
+
import java.util.Map;
|
| 7 |
+
import java.util.UUID;
|
| 8 |
+
|
| 9 |
+
import org.hibernate.annotations.JdbcTypeCode;
|
| 10 |
+
import org.hibernate.type.SqlTypes;
|
| 11 |
+
|
| 12 |
+
import jakarta.persistence.CascadeType;
|
| 13 |
+
import jakarta.persistence.CollectionTable;
|
| 14 |
+
import jakarta.persistence.Column;
|
| 15 |
+
import jakarta.persistence.ElementCollection;
|
| 16 |
+
import jakarta.persistence.Entity;
|
| 17 |
+
import jakarta.persistence.EnumType;
|
| 18 |
+
import jakarta.persistence.Enumerated;
|
| 19 |
+
import jakarta.persistence.FetchType;
|
| 20 |
+
import jakarta.persistence.GeneratedValue;
|
| 21 |
+
import jakarta.persistence.GenerationType;
|
| 22 |
+
import jakarta.persistence.Id;
|
| 23 |
+
import jakarta.persistence.JoinColumn;
|
| 24 |
+
import jakarta.persistence.OneToMany;
|
| 25 |
+
import jakarta.persistence.PrePersist;
|
| 26 |
+
import jakarta.persistence.PreUpdate;
|
| 27 |
+
import jakarta.persistence.Table;
|
| 28 |
+
import jakarta.validation.constraints.NotBlank;
|
| 29 |
+
import jakarta.validation.constraints.NotNull;
|
| 30 |
+
import jakarta.validation.constraints.Size;
|
| 31 |
+
|
| 32 |
+
/**
|
| 33 |
+
* Entity representing an event subscription configuration.
|
| 34 |
+
* Users can subscribe to specific types of events and configure
|
| 35 |
+
* notification preferences and action triggers.
|
| 36 |
+
*/
|
| 37 |
+
@Entity
|
| 38 |
+
@Table(name = "event_subscriptions")
|
| 39 |
+
public class EventSubscription {
|
| 40 |
+
|
| 41 |
+
@Id
|
| 42 |
+
@GeneratedValue(strategy = GenerationType.AUTO)
|
| 43 |
+
@Column(columnDefinition = "UUID")
|
| 44 |
+
private UUID id;
|
| 45 |
+
|
| 46 |
+
@NotBlank
|
| 47 |
+
@Size(max = 255)
|
| 48 |
+
@Column(nullable = false)
|
| 49 |
+
private String name;
|
| 50 |
+
|
| 51 |
+
@Size(max = 1000)
|
| 52 |
+
private String description;
|
| 53 |
+
|
| 54 |
+
@NotNull
|
| 55 |
+
@Column(columnDefinition = "UUID", nullable = false)
|
| 56 |
+
private UUID userId;
|
| 57 |
+
|
| 58 |
+
@Enumerated(EnumType.STRING)
|
| 59 |
+
@Column(nullable = false)
|
| 60 |
+
private EventSubscriptionStatus status = EventSubscriptionStatus.ACTIVE;
|
| 61 |
+
|
| 62 |
+
/**
|
| 63 |
+
* Event types to subscribe to (e.g., POLICY_VIOLATION, ASSET_DISCOVERED, COMPLIANCE_ISSUE)
|
| 64 |
+
*/
|
| 65 |
+
@ElementCollection(fetch = FetchType.EAGER)
|
| 66 |
+
@CollectionTable(name = "event_subscription_types", joinColumns = @JoinColumn(name = "subscription_id"))
|
| 67 |
+
@Enumerated(EnumType.STRING)
|
| 68 |
+
@Column(name = "event_type")
|
| 69 |
+
private List<EventType> eventTypes = new ArrayList<>();
|
| 70 |
+
|
| 71 |
+
/**
|
| 72 |
+
* Event severity levels to include (e.g., HIGH, MEDIUM, LOW)
|
| 73 |
+
*/
|
| 74 |
+
@ElementCollection(fetch = FetchType.EAGER)
|
| 75 |
+
@CollectionTable(name = "event_subscription_severities", joinColumns = @JoinColumn(name = "subscription_id"))
|
| 76 |
+
@Enumerated(EnumType.STRING)
|
| 77 |
+
@Column(name = "severity")
|
| 78 |
+
private List<EventSeverity> severities = new ArrayList<>();
|
| 79 |
+
|
| 80 |
+
/**
|
| 81 |
+
* Source services to monitor (e.g., da-catalog, da-discovery, da-compliance)
|
| 82 |
+
*/
|
| 83 |
+
@ElementCollection(fetch = FetchType.EAGER)
|
| 84 |
+
@CollectionTable(name = "event_subscription_sources", joinColumns = @JoinColumn(name = "subscription_id"))
|
| 85 |
+
@Column(name = "source_service")
|
| 86 |
+
private List<String> sourceServices = new ArrayList<>();
|
| 87 |
+
|
| 88 |
+
/**
|
| 89 |
+
* Filter conditions for events (MVEL expressions)
|
| 90 |
+
*/
|
| 91 |
+
@OneToMany(mappedBy = "subscription", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
|
| 92 |
+
private List<EventRule> rules = new ArrayList<>();
|
| 93 |
+
|
| 94 |
+
/**
|
| 95 |
+
* Notification preferences and action configurations
|
| 96 |
+
*/
|
| 97 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 98 |
+
@Column(columnDefinition = "jsonb")
|
| 99 |
+
private Map<String, Object> notificationConfig; // e.g., { "email": true, "slack": { "channel": "#alerts" } }
|
| 100 |
+
|
| 101 |
+
/**
|
| 102 |
+
* Action configurations to trigger when events match
|
| 103 |
+
*/
|
| 104 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 105 |
+
@Column(columnDefinition = "jsonb")
|
| 106 |
+
private Map<String, Object> actionConfig; // e.g., { "autoQuarantine": true, "escalateTo": "admin" }
|
| 107 |
+
|
| 108 |
+
@Column(nullable = false, updatable = false)
|
| 109 |
+
private Instant createdAt;
|
| 110 |
+
|
| 111 |
+
private Instant updatedAt;
|
| 112 |
+
|
| 113 |
+
@Column(columnDefinition = "UUID")
|
| 114 |
+
private UUID createdByUserId;
|
| 115 |
+
|
| 116 |
+
@Column(columnDefinition = "UUID")
|
| 117 |
+
private UUID updatedByUserId;
|
| 118 |
+
|
| 119 |
+
// Constructors
|
| 120 |
+
public EventSubscription() {}
|
| 121 |
+
|
| 122 |
+
public EventSubscription(String name, UUID userId) {
|
| 123 |
+
this.name = name;
|
| 124 |
+
this.userId = userId;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
// Getters and Setters
|
| 128 |
+
|
| 129 |
+
public UUID getId() {
|
| 130 |
+
return id;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
public void setId(UUID id) {
|
| 134 |
+
this.id = id;
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
public String getName() {
|
| 138 |
+
return name;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
public void setName(String name) {
|
| 142 |
+
this.name = name;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
public String getDescription() {
|
| 146 |
+
return description;
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
public void setDescription(String description) {
|
| 150 |
+
this.description = description;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
public UUID getUserId() {
|
| 154 |
+
return userId;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
public void setUserId(UUID userId) {
|
| 158 |
+
this.userId = userId;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
public EventSubscriptionStatus getStatus() {
|
| 162 |
+
return status;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
public void setStatus(EventSubscriptionStatus status) {
|
| 166 |
+
this.status = status;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
public List<EventType> getEventTypes() {
|
| 170 |
+
return eventTypes;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
public void setEventTypes(List<EventType> eventTypes) {
|
| 174 |
+
this.eventTypes = eventTypes != null ? eventTypes : new ArrayList<>();
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
public void addEventType(EventType eventType) {
|
| 178 |
+
if (this.eventTypes == null) {
|
| 179 |
+
this.eventTypes = new ArrayList<>();
|
| 180 |
+
}
|
| 181 |
+
this.eventTypes.add(eventType);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
public void removeEventType(EventType eventType) {
|
| 185 |
+
if (this.eventTypes != null) {
|
| 186 |
+
this.eventTypes.remove(eventType);
|
| 187 |
+
}
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
public List<EventSeverity> getSeverities() {
|
| 191 |
+
return severities;
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
public void setSeverities(List<EventSeverity> severities) {
|
| 195 |
+
this.severities = severities != null ? severities : new ArrayList<>();
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
public void addSeverity(EventSeverity severity) {
|
| 199 |
+
if (this.severities == null) {
|
| 200 |
+
this.severities = new ArrayList<>();
|
| 201 |
+
}
|
| 202 |
+
this.severities.add(severity);
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
public void removeSeverity(EventSeverity severity) {
|
| 206 |
+
if (this.severities != null) {
|
| 207 |
+
this.severities.remove(severity);
|
| 208 |
+
}
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
public List<String> getSourceServices() {
|
| 212 |
+
return sourceServices;
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
public void setSourceServices(List<String> sourceServices) {
|
| 216 |
+
this.sourceServices = sourceServices != null ? sourceServices : new ArrayList<>();
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
public void addSourceService(String sourceService) {
|
| 220 |
+
if (this.sourceServices == null) {
|
| 221 |
+
this.sourceServices = new ArrayList<>();
|
| 222 |
+
}
|
| 223 |
+
this.sourceServices.add(sourceService);
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
public void removeSourceService(String sourceService) {
|
| 227 |
+
if (this.sourceServices != null) {
|
| 228 |
+
this.sourceServices.remove(sourceService);
|
| 229 |
+
}
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
public List<EventRule> getRules() {
|
| 233 |
+
return rules;
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
public void setRules(List<EventRule> rules) {
|
| 237 |
+
this.rules = rules != null ? rules : new ArrayList<>();
|
| 238 |
+
this.rules.forEach(rule -> rule.setSubscription(this));
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
public void addRule(EventRule rule) {
|
| 242 |
+
if (this.rules == null) {
|
| 243 |
+
this.rules = new ArrayList<>();
|
| 244 |
+
}
|
| 245 |
+
this.rules.add(rule);
|
| 246 |
+
rule.setSubscription(this);
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
public void removeRule(EventRule rule) {
|
| 250 |
+
if (this.rules != null) {
|
| 251 |
+
this.rules.remove(rule);
|
| 252 |
+
rule.setSubscription(null);
|
| 253 |
+
}
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
public Map<String, Object> getNotificationConfig() {
|
| 257 |
+
return notificationConfig;
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
public void setNotificationConfig(Map<String, Object> notificationConfig) {
|
| 261 |
+
this.notificationConfig = notificationConfig;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
public Map<String, Object> getActionConfig() {
|
| 265 |
+
return actionConfig;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
public void setActionConfig(Map<String, Object> actionConfig) {
|
| 269 |
+
this.actionConfig = actionConfig;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
public Instant getCreatedAt() {
|
| 273 |
+
return createdAt;
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
public void setCreatedAt(Instant createdAt) {
|
| 277 |
+
this.createdAt = createdAt;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
public Instant getUpdatedAt() {
|
| 281 |
+
return updatedAt;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 285 |
+
this.updatedAt = updatedAt;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
public UUID getCreatedByUserId() {
|
| 289 |
+
return createdByUserId;
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
public void setCreatedByUserId(UUID createdByUserId) {
|
| 293 |
+
this.createdByUserId = createdByUserId;
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
public UUID getUpdatedByUserId() {
|
| 297 |
+
return updatedByUserId;
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
public void setUpdatedByUserId(UUID updatedByUserId) {
|
| 301 |
+
this.updatedByUserId = updatedByUserId;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
@PrePersist
|
| 305 |
+
protected void onCreate() {
|
| 306 |
+
createdAt = Instant.now();
|
| 307 |
+
updatedAt = Instant.now();
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
@PreUpdate
|
| 311 |
+
protected void onUpdate() {
|
| 312 |
+
updatedAt = Instant.now();
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
@Override
|
| 316 |
+
public boolean equals(Object o) {
|
| 317 |
+
if (this == o) return true;
|
| 318 |
+
if (!(o instanceof EventSubscription)) return false;
|
| 319 |
+
EventSubscription that = (EventSubscription) o;
|
| 320 |
+
return id != null && id.equals(that.getId());
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
@Override
|
| 324 |
+
public int hashCode() {
|
| 325 |
+
return getClass().hashCode();
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
@Override
|
| 329 |
+
public String toString() {
|
| 330 |
+
return "EventSubscription{" +
|
| 331 |
+
"id=" + id +
|
| 332 |
+
", name='" + name + '\'' +
|
| 333 |
+
", userId=" + userId +
|
| 334 |
+
", status=" + status +
|
| 335 |
+
", eventTypes=" + eventTypes +
|
| 336 |
+
", severities=" + severities +
|
| 337 |
+
'}';
|
| 338 |
+
}
|
| 339 |
+
}
|
src/main/java/com/dalab/policyengine/model/EventSubscriptionStatus.java
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Enumeration representing the status of an event subscription.
|
| 5 |
+
*/
|
| 6 |
+
public enum EventSubscriptionStatus {
|
| 7 |
+
/**
|
| 8 |
+
* Subscription is active and receiving events
|
| 9 |
+
*/
|
| 10 |
+
ACTIVE,
|
| 11 |
+
|
| 12 |
+
/**
|
| 13 |
+
* Subscription is temporarily paused
|
| 14 |
+
*/
|
| 15 |
+
PAUSED,
|
| 16 |
+
|
| 17 |
+
/**
|
| 18 |
+
* Subscription is disabled and not receiving events
|
| 19 |
+
*/
|
| 20 |
+
DISABLED,
|
| 21 |
+
|
| 22 |
+
/**
|
| 23 |
+
* Subscription has been archived
|
| 24 |
+
*/
|
| 25 |
+
ARCHIVED
|
| 26 |
+
}
|
src/main/java/com/dalab/policyengine/model/EventType.java
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Enumeration representing different types of events that can occur in the DALab platform.
|
| 5 |
+
*/
|
| 6 |
+
public enum EventType {
|
| 7 |
+
// Policy-related events
|
| 8 |
+
/**
|
| 9 |
+
* Policy violation detected
|
| 10 |
+
*/
|
| 11 |
+
POLICY_VIOLATION,
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Policy evaluation completed
|
| 15 |
+
*/
|
| 16 |
+
POLICY_EVALUATION_COMPLETED,
|
| 17 |
+
|
| 18 |
+
/**
|
| 19 |
+
* Policy applied to assets
|
| 20 |
+
*/
|
| 21 |
+
POLICY_APPLIED,
|
| 22 |
+
|
| 23 |
+
/**
|
| 24 |
+
* Policy rule triggered
|
| 25 |
+
*/
|
| 26 |
+
POLICY_RULE_TRIGGERED,
|
| 27 |
+
|
| 28 |
+
// Asset-related events
|
| 29 |
+
/**
|
| 30 |
+
* New asset discovered
|
| 31 |
+
*/
|
| 32 |
+
ASSET_DISCOVERED,
|
| 33 |
+
|
| 34 |
+
/**
|
| 35 |
+
* Asset metadata changed
|
| 36 |
+
*/
|
| 37 |
+
ASSET_METADATA_CHANGED,
|
| 38 |
+
|
| 39 |
+
/**
|
| 40 |
+
* Asset classification changed
|
| 41 |
+
*/
|
| 42 |
+
ASSET_CLASSIFICATION_CHANGED,
|
| 43 |
+
|
| 44 |
+
/**
|
| 45 |
+
* Asset access pattern detected
|
| 46 |
+
*/
|
| 47 |
+
ASSET_ACCESS_DETECTED,
|
| 48 |
+
|
| 49 |
+
// Compliance-related events
|
| 50 |
+
/**
|
| 51 |
+
* Compliance violation detected
|
| 52 |
+
*/
|
| 53 |
+
COMPLIANCE_VIOLATION,
|
| 54 |
+
|
| 55 |
+
/**
|
| 56 |
+
* Compliance scan completed
|
| 57 |
+
*/
|
| 58 |
+
COMPLIANCE_SCAN_COMPLETED,
|
| 59 |
+
|
| 60 |
+
/**
|
| 61 |
+
* Regulatory requirement changed
|
| 62 |
+
*/
|
| 63 |
+
REGULATORY_CHANGE,
|
| 64 |
+
|
| 65 |
+
// Data lifecycle events
|
| 66 |
+
/**
|
| 67 |
+
* Asset scheduled for archival
|
| 68 |
+
*/
|
| 69 |
+
ASSET_ARCHIVAL_SCHEDULED,
|
| 70 |
+
|
| 71 |
+
/**
|
| 72 |
+
* Asset archival completed
|
| 73 |
+
*/
|
| 74 |
+
ASSET_ARCHIVAL_COMPLETED,
|
| 75 |
+
|
| 76 |
+
/**
|
| 77 |
+
* Asset deletion scheduled
|
| 78 |
+
*/
|
| 79 |
+
ASSET_DELETION_SCHEDULED,
|
| 80 |
+
|
| 81 |
+
/**
|
| 82 |
+
* Asset deletion completed
|
| 83 |
+
*/
|
| 84 |
+
ASSET_DELETION_COMPLETED,
|
| 85 |
+
|
| 86 |
+
// System events
|
| 87 |
+
/**
|
| 88 |
+
* System alert generated
|
| 89 |
+
*/
|
| 90 |
+
SYSTEM_ALERT,
|
| 91 |
+
|
| 92 |
+
/**
|
| 93 |
+
* Service health check failed
|
| 94 |
+
*/
|
| 95 |
+
SERVICE_HEALTH_ISSUE,
|
| 96 |
+
|
| 97 |
+
/**
|
| 98 |
+
* Data quality issue detected
|
| 99 |
+
*/
|
| 100 |
+
DATA_QUALITY_ISSUE,
|
| 101 |
+
|
| 102 |
+
/**
|
| 103 |
+
* Security incident detected
|
| 104 |
+
*/
|
| 105 |
+
SECURITY_INCIDENT,
|
| 106 |
+
|
| 107 |
+
// User activity events
|
| 108 |
+
/**
|
| 109 |
+
* User access pattern anomaly
|
| 110 |
+
*/
|
| 111 |
+
USER_ACCESS_ANOMALY,
|
| 112 |
+
|
| 113 |
+
/**
|
| 114 |
+
* Unauthorized access attempt
|
| 115 |
+
*/
|
| 116 |
+
UNAUTHORIZED_ACCESS_ATTEMPT,
|
| 117 |
+
|
| 118 |
+
// Generic event type for custom events
|
| 119 |
+
/**
|
| 120 |
+
* Custom event type
|
| 121 |
+
*/
|
| 122 |
+
CUSTOM_EVENT
|
| 123 |
+
}
|
src/main/java/com/dalab/policyengine/model/Policy.java
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.ArrayList;
|
| 5 |
+
import java.util.List;
|
| 6 |
+
import java.util.Map;
|
| 7 |
+
import java.util.UUID;
|
| 8 |
+
|
| 9 |
+
import org.hibernate.annotations.JdbcTypeCode;
|
| 10 |
+
import org.hibernate.type.SqlTypes;
|
| 11 |
+
|
| 12 |
+
import jakarta.persistence.*;
|
| 13 |
+
import jakarta.validation.constraints.NotBlank;
|
| 14 |
+
import jakarta.validation.constraints.Size;
|
| 15 |
+
|
| 16 |
+
@Entity
|
| 17 |
+
@Table(name = "policies")
|
| 18 |
+
public class Policy {
|
| 19 |
+
|
| 20 |
+
@Id
|
| 21 |
+
@GeneratedValue(strategy = GenerationType.AUTO)
|
| 22 |
+
@Column(columnDefinition = "UUID")
|
| 23 |
+
private UUID id;
|
| 24 |
+
|
| 25 |
+
@NotBlank
|
| 26 |
+
@Size(max = 255)
|
| 27 |
+
@Column(nullable = false, unique = true)
|
| 28 |
+
private String name;
|
| 29 |
+
|
| 30 |
+
@Size(max = 1000)
|
| 31 |
+
private String description;
|
| 32 |
+
|
| 33 |
+
@Enumerated(EnumType.STRING)
|
| 34 |
+
@Column(nullable = false)
|
| 35 |
+
private PolicyStatus status = PolicyStatus.DISABLED;
|
| 36 |
+
|
| 37 |
+
// MVEL condition for the policy. If all rules pass, this condition is evaluated.
|
| 38 |
+
// Could be null if policy relies solely on its individual rules.
|
| 39 |
+
@Column(columnDefinition = "TEXT")
|
| 40 |
+
private String conditionLogic; // e.g., "rule1 && (rule2 || rule3)"
|
| 41 |
+
|
| 42 |
+
@OneToMany(mappedBy = "policy", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
|
| 43 |
+
private List<PolicyRule> rules = new ArrayList<>();
|
| 44 |
+
|
| 45 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 46 |
+
@Column(columnDefinition = "jsonb")
|
| 47 |
+
private Map<String, Object> actions; // e.g., { "notify": { "email": "admin@example.com" }, "addLabel": "Sensitive" }
|
| 48 |
+
|
| 49 |
+
@Column(nullable = false, updatable = false)
|
| 50 |
+
private Instant createdAt;
|
| 51 |
+
|
| 52 |
+
private Instant updatedAt;
|
| 53 |
+
|
| 54 |
+
@Column(columnDefinition = "UUID")
|
| 55 |
+
private UUID createdByUserId;
|
| 56 |
+
|
| 57 |
+
@Column(columnDefinition = "UUID")
|
| 58 |
+
private UUID updatedByUserId;
|
| 59 |
+
|
| 60 |
+
// Getters and Setters
|
| 61 |
+
|
| 62 |
+
public UUID getId() {
|
| 63 |
+
return id;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
public void setId(UUID id) {
|
| 67 |
+
this.id = id;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
public String getName() {
|
| 71 |
+
return name;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
public void setName(String name) {
|
| 75 |
+
this.name = name;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
public String getDescription() {
|
| 79 |
+
return description;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
public void setDescription(String description) {
|
| 83 |
+
this.description = description;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
public PolicyStatus getStatus() {
|
| 87 |
+
return status;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
public void setStatus(PolicyStatus status) {
|
| 91 |
+
this.status = status;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
public String getConditionLogic() {
|
| 95 |
+
return conditionLogic;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
public void setConditionLogic(String conditionLogic) {
|
| 99 |
+
this.conditionLogic = conditionLogic;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
public List<PolicyRule> getRules() {
|
| 103 |
+
return rules;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
public void setRules(List<PolicyRule> rules) {
|
| 107 |
+
this.rules = rules;
|
| 108 |
+
this.rules.forEach(rule -> rule.setPolicy(this));
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
public void addRule(PolicyRule rule) {
|
| 112 |
+
this.rules.add(rule);
|
| 113 |
+
rule.setPolicy(this);
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
public void removeRule(PolicyRule rule) {
|
| 117 |
+
this.rules.remove(rule);
|
| 118 |
+
rule.setPolicy(null);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
public Map<String, Object> getActions() {
|
| 122 |
+
return actions;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
public void setActions(Map<String, Object> actions) {
|
| 126 |
+
this.actions = actions;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
public Instant getCreatedAt() {
|
| 130 |
+
return createdAt;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
public void setCreatedAt(Instant createdAt) {
|
| 134 |
+
this.createdAt = createdAt;
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
public Instant getUpdatedAt() {
|
| 138 |
+
return updatedAt;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 142 |
+
this.updatedAt = updatedAt;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
public UUID getCreatedByUserId() {
|
| 146 |
+
return createdByUserId;
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
public void setCreatedByUserId(UUID createdByUserId) {
|
| 150 |
+
this.createdByUserId = createdByUserId;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
public UUID getUpdatedByUserId() {
|
| 154 |
+
return updatedByUserId;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
public void setUpdatedByUserId(UUID updatedByUserId) {
|
| 158 |
+
this.updatedByUserId = updatedByUserId;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
@PrePersist
|
| 162 |
+
protected void onCreate() {
|
| 163 |
+
createdAt = Instant.now();
|
| 164 |
+
updatedAt = Instant.now();
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
@PreUpdate
|
| 168 |
+
protected void onUpdate() {
|
| 169 |
+
updatedAt = Instant.now();
|
| 170 |
+
}
|
| 171 |
+
}
|
src/main/java/com/dalab/policyengine/model/PolicyDraft.java
ADDED
|
@@ -0,0 +1,495 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.ArrayList;
|
| 5 |
+
import java.util.List;
|
| 6 |
+
import java.util.Map;
|
| 7 |
+
import java.util.UUID;
|
| 8 |
+
|
| 9 |
+
import org.hibernate.annotations.JdbcTypeCode;
|
| 10 |
+
import org.hibernate.type.SqlTypes;
|
| 11 |
+
|
| 12 |
+
import jakarta.persistence.CollectionTable;
|
| 13 |
+
import jakarta.persistence.Column;
|
| 14 |
+
import jakarta.persistence.ElementCollection;
|
| 15 |
+
import jakarta.persistence.Entity;
|
| 16 |
+
import jakarta.persistence.EnumType;
|
| 17 |
+
import jakarta.persistence.Enumerated;
|
| 18 |
+
import jakarta.persistence.GeneratedValue;
|
| 19 |
+
import jakarta.persistence.GenerationType;
|
| 20 |
+
import jakarta.persistence.Id;
|
| 21 |
+
import jakarta.persistence.JoinColumn;
|
| 22 |
+
import jakarta.persistence.PrePersist;
|
| 23 |
+
import jakarta.persistence.PreUpdate;
|
| 24 |
+
import jakarta.persistence.Table;
|
| 25 |
+
import jakarta.validation.constraints.NotBlank;
|
| 26 |
+
import jakarta.validation.constraints.Size;
|
| 27 |
+
|
| 28 |
+
/**
|
| 29 |
+
* Entity representing a policy draft that goes through approval workflow.
|
| 30 |
+
* Supports versioning, collaboration, and audit trails.
|
| 31 |
+
*/
|
| 32 |
+
@Entity
|
| 33 |
+
@Table(name = "policy_drafts")
|
| 34 |
+
public class PolicyDraft {
|
| 35 |
+
|
| 36 |
+
@Id
|
| 37 |
+
@GeneratedValue(strategy = GenerationType.AUTO)
|
| 38 |
+
@Column(columnDefinition = "UUID")
|
| 39 |
+
private UUID id;
|
| 40 |
+
|
| 41 |
+
/**
|
| 42 |
+
* Name of the policy (must be unique when published).
|
| 43 |
+
*/
|
| 44 |
+
@NotBlank
|
| 45 |
+
@Size(max = 255)
|
| 46 |
+
@Column(nullable = false)
|
| 47 |
+
private String name;
|
| 48 |
+
|
| 49 |
+
/**
|
| 50 |
+
* Detailed description of the policy's purpose and scope.
|
| 51 |
+
*/
|
| 52 |
+
@Size(max = 2000)
|
| 53 |
+
@Column(columnDefinition = "TEXT")
|
| 54 |
+
private String description;
|
| 55 |
+
|
| 56 |
+
/**
|
| 57 |
+
* Current status in the approval workflow.
|
| 58 |
+
*/
|
| 59 |
+
@Enumerated(EnumType.STRING)
|
| 60 |
+
@Column(nullable = false)
|
| 61 |
+
private PolicyDraftStatus status = PolicyDraftStatus.CREATED;
|
| 62 |
+
|
| 63 |
+
/**
|
| 64 |
+
* Version number for this draft (incremented on each revision).
|
| 65 |
+
*/
|
| 66 |
+
@Column(nullable = false)
|
| 67 |
+
private Integer version = 1;
|
| 68 |
+
|
| 69 |
+
/**
|
| 70 |
+
* Reference to the published policy (if this is an update to existing policy).
|
| 71 |
+
*/
|
| 72 |
+
@Column(columnDefinition = "UUID")
|
| 73 |
+
private UUID basePolicyId;
|
| 74 |
+
|
| 75 |
+
/**
|
| 76 |
+
* MVEL condition logic for the policy evaluation.
|
| 77 |
+
*/
|
| 78 |
+
@Column(columnDefinition = "TEXT")
|
| 79 |
+
private String conditionLogic;
|
| 80 |
+
|
| 81 |
+
/**
|
| 82 |
+
* JSON representation of policy rules structure.
|
| 83 |
+
* Stored as JSON to support complex rule configurations.
|
| 84 |
+
*/
|
| 85 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 86 |
+
@Column(columnDefinition = "jsonb")
|
| 87 |
+
private List<Map<String, Object>> rulesDefinition;
|
| 88 |
+
|
| 89 |
+
/**
|
| 90 |
+
* JSON representation of actions to be taken when policy is triggered.
|
| 91 |
+
*/
|
| 92 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 93 |
+
@Column(columnDefinition = "jsonb")
|
| 94 |
+
private Map<String, Object> actions;
|
| 95 |
+
|
| 96 |
+
/**
|
| 97 |
+
* Change summary describing what was modified in this version.
|
| 98 |
+
*/
|
| 99 |
+
@Size(max = 1000)
|
| 100 |
+
@Column(columnDefinition = "TEXT")
|
| 101 |
+
private String changeSummary;
|
| 102 |
+
|
| 103 |
+
/**
|
| 104 |
+
* Justification for the policy changes or creation.
|
| 105 |
+
*/
|
| 106 |
+
@Size(max = 2000)
|
| 107 |
+
@Column(columnDefinition = "TEXT")
|
| 108 |
+
private String justification;
|
| 109 |
+
|
| 110 |
+
/**
|
| 111 |
+
* Expected impact of implementing this policy.
|
| 112 |
+
*/
|
| 113 |
+
@Size(max = 1000)
|
| 114 |
+
@Column(columnDefinition = "TEXT")
|
| 115 |
+
private String expectedImpact;
|
| 116 |
+
|
| 117 |
+
/**
|
| 118 |
+
* Target implementation date for the policy.
|
| 119 |
+
*/
|
| 120 |
+
private Instant targetImplementationDate;
|
| 121 |
+
|
| 122 |
+
/**
|
| 123 |
+
* Priority level for policy implementation (HIGH, MEDIUM, LOW).
|
| 124 |
+
*/
|
| 125 |
+
@Size(max = 50)
|
| 126 |
+
private String priority = "MEDIUM";
|
| 127 |
+
|
| 128 |
+
/**
|
| 129 |
+
* Business category or domain this policy applies to.
|
| 130 |
+
*/
|
| 131 |
+
@Size(max = 100)
|
| 132 |
+
private String category;
|
| 133 |
+
|
| 134 |
+
/**
|
| 135 |
+
* Tags for categorization and searchability.
|
| 136 |
+
*/
|
| 137 |
+
@ElementCollection
|
| 138 |
+
@CollectionTable(name = "policy_draft_tags", joinColumns = @JoinColumn(name = "draft_id"))
|
| 139 |
+
@Column(name = "tag")
|
| 140 |
+
private List<String> tags = new ArrayList<>();
|
| 141 |
+
|
| 142 |
+
/**
|
| 143 |
+
* Stakeholders who should be notified about this policy.
|
| 144 |
+
*/
|
| 145 |
+
@ElementCollection
|
| 146 |
+
@CollectionTable(name = "policy_draft_stakeholders", joinColumns = @JoinColumn(name = "draft_id"))
|
| 147 |
+
@Column(name = "stakeholder_id", columnDefinition = "UUID")
|
| 148 |
+
private List<UUID> stakeholders = new ArrayList<>();
|
| 149 |
+
|
| 150 |
+
/**
|
| 151 |
+
* Approval workflow metadata.
|
| 152 |
+
*/
|
| 153 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 154 |
+
@Column(columnDefinition = "jsonb")
|
| 155 |
+
private Map<String, Object> approvalMetadata;
|
| 156 |
+
|
| 157 |
+
/**
|
| 158 |
+
* Reviewer comments and feedback.
|
| 159 |
+
*/
|
| 160 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 161 |
+
@Column(columnDefinition = "jsonb")
|
| 162 |
+
private List<Map<String, Object>> reviewComments = new ArrayList<>();
|
| 163 |
+
|
| 164 |
+
// Audit fields
|
| 165 |
+
@Column(nullable = false, updatable = false)
|
| 166 |
+
private Instant createdAt;
|
| 167 |
+
|
| 168 |
+
private Instant updatedAt;
|
| 169 |
+
|
| 170 |
+
@Column(columnDefinition = "UUID", nullable = false)
|
| 171 |
+
private UUID createdByUserId;
|
| 172 |
+
|
| 173 |
+
@Column(columnDefinition = "UUID")
|
| 174 |
+
private UUID updatedByUserId;
|
| 175 |
+
|
| 176 |
+
private Instant submittedAt;
|
| 177 |
+
|
| 178 |
+
@Column(columnDefinition = "UUID")
|
| 179 |
+
private UUID submittedByUserId;
|
| 180 |
+
|
| 181 |
+
private Instant approvedAt;
|
| 182 |
+
|
| 183 |
+
@Column(columnDefinition = "UUID")
|
| 184 |
+
private UUID approvedByUserId;
|
| 185 |
+
|
| 186 |
+
private Instant rejectedAt;
|
| 187 |
+
|
| 188 |
+
@Column(columnDefinition = "UUID")
|
| 189 |
+
private UUID rejectedByUserId;
|
| 190 |
+
|
| 191 |
+
private Instant publishedAt;
|
| 192 |
+
|
| 193 |
+
@Column(columnDefinition = "UUID")
|
| 194 |
+
private UUID publishedByUserId;
|
| 195 |
+
|
| 196 |
+
// Constructors
|
| 197 |
+
public PolicyDraft() {}
|
| 198 |
+
|
| 199 |
+
public PolicyDraft(String name, String description, UUID createdByUserId) {
|
| 200 |
+
this.name = name;
|
| 201 |
+
this.description = description;
|
| 202 |
+
this.createdByUserId = createdByUserId;
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
// Getters and Setters
|
| 206 |
+
public UUID getId() {
|
| 207 |
+
return id;
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
public void setId(UUID id) {
|
| 211 |
+
this.id = id;
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
public String getName() {
|
| 215 |
+
return name;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
public void setName(String name) {
|
| 219 |
+
this.name = name;
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
public String getDescription() {
|
| 223 |
+
return description;
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
public void setDescription(String description) {
|
| 227 |
+
this.description = description;
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
public PolicyDraftStatus getStatus() {
|
| 231 |
+
return status;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
public void setStatus(PolicyDraftStatus status) {
|
| 235 |
+
this.status = status;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
public Integer getVersion() {
|
| 239 |
+
return version;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
public void setVersion(Integer version) {
|
| 243 |
+
this.version = version;
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
public UUID getBasePolicyId() {
|
| 247 |
+
return basePolicyId;
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
public void setBasePolicyId(UUID basePolicyId) {
|
| 251 |
+
this.basePolicyId = basePolicyId;
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
public String getConditionLogic() {
|
| 255 |
+
return conditionLogic;
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
public void setConditionLogic(String conditionLogic) {
|
| 259 |
+
this.conditionLogic = conditionLogic;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
public List<Map<String, Object>> getRulesDefinition() {
|
| 263 |
+
return rulesDefinition;
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
public void setRulesDefinition(List<Map<String, Object>> rulesDefinition) {
|
| 267 |
+
this.rulesDefinition = rulesDefinition;
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
public Map<String, Object> getActions() {
|
| 271 |
+
return actions;
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
public void setActions(Map<String, Object> actions) {
|
| 275 |
+
this.actions = actions;
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
public String getChangeSummary() {
|
| 279 |
+
return changeSummary;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
public void setChangeSummary(String changeSummary) {
|
| 283 |
+
this.changeSummary = changeSummary;
|
| 284 |
+
}
|
| 285 |
+
|
| 286 |
+
public String getJustification() {
|
| 287 |
+
return justification;
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
public void setJustification(String justification) {
|
| 291 |
+
this.justification = justification;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
public String getExpectedImpact() {
|
| 295 |
+
return expectedImpact;
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
public void setExpectedImpact(String expectedImpact) {
|
| 299 |
+
this.expectedImpact = expectedImpact;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
public Instant getTargetImplementationDate() {
|
| 303 |
+
return targetImplementationDate;
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
public void setTargetImplementationDate(Instant targetImplementationDate) {
|
| 307 |
+
this.targetImplementationDate = targetImplementationDate;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
public String getPriority() {
|
| 311 |
+
return priority;
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
public void setPriority(String priority) {
|
| 315 |
+
this.priority = priority;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
public String getCategory() {
|
| 319 |
+
return category;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
public void setCategory(String category) {
|
| 323 |
+
this.category = category;
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
public List<String> getTags() {
|
| 327 |
+
return tags;
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
public void setTags(List<String> tags) {
|
| 331 |
+
this.tags = tags;
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
public List<UUID> getStakeholders() {
|
| 335 |
+
return stakeholders;
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
public void setStakeholders(List<UUID> stakeholders) {
|
| 339 |
+
this.stakeholders = stakeholders;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
public Map<String, Object> getApprovalMetadata() {
|
| 343 |
+
return approvalMetadata;
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
public void setApprovalMetadata(Map<String, Object> approvalMetadata) {
|
| 347 |
+
this.approvalMetadata = approvalMetadata;
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
public List<Map<String, Object>> getReviewComments() {
|
| 351 |
+
return reviewComments;
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
public void setReviewComments(List<Map<String, Object>> reviewComments) {
|
| 355 |
+
this.reviewComments = reviewComments;
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
public Instant getCreatedAt() {
|
| 359 |
+
return createdAt;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
public void setCreatedAt(Instant createdAt) {
|
| 363 |
+
this.createdAt = createdAt;
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
public Instant getUpdatedAt() {
|
| 367 |
+
return updatedAt;
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 371 |
+
this.updatedAt = updatedAt;
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
public UUID getCreatedByUserId() {
|
| 375 |
+
return createdByUserId;
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
public void setCreatedByUserId(UUID createdByUserId) {
|
| 379 |
+
this.createdByUserId = createdByUserId;
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
public UUID getUpdatedByUserId() {
|
| 383 |
+
return updatedByUserId;
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
public void setUpdatedByUserId(UUID updatedByUserId) {
|
| 387 |
+
this.updatedByUserId = updatedByUserId;
|
| 388 |
+
}
|
| 389 |
+
|
| 390 |
+
public Instant getSubmittedAt() {
|
| 391 |
+
return submittedAt;
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
public void setSubmittedAt(Instant submittedAt) {
|
| 395 |
+
this.submittedAt = submittedAt;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
public UUID getSubmittedByUserId() {
|
| 399 |
+
return submittedByUserId;
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
public void setSubmittedByUserId(UUID submittedByUserId) {
|
| 403 |
+
this.submittedByUserId = submittedByUserId;
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
public Instant getApprovedAt() {
|
| 407 |
+
return approvedAt;
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
public void setApprovedAt(Instant approvedAt) {
|
| 411 |
+
this.approvedAt = approvedAt;
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
public UUID getApprovedByUserId() {
|
| 415 |
+
return approvedByUserId;
|
| 416 |
+
}
|
| 417 |
+
|
| 418 |
+
public void setApprovedByUserId(UUID approvedByUserId) {
|
| 419 |
+
this.approvedByUserId = approvedByUserId;
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
public Instant getRejectedAt() {
|
| 423 |
+
return rejectedAt;
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
public void setRejectedAt(Instant rejectedAt) {
|
| 427 |
+
this.rejectedAt = rejectedAt;
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
public UUID getRejectedByUserId() {
|
| 431 |
+
return rejectedByUserId;
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
public void setRejectedByUserId(UUID rejectedByUserId) {
|
| 435 |
+
this.rejectedByUserId = rejectedByUserId;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
public Instant getPublishedAt() {
|
| 439 |
+
return publishedAt;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
public void setPublishedAt(Instant publishedAt) {
|
| 443 |
+
this.publishedAt = publishedAt;
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
public UUID getPublishedByUserId() {
|
| 447 |
+
return publishedByUserId;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
public void setPublishedByUserId(UUID publishedByUserId) {
|
| 451 |
+
this.publishedByUserId = publishedByUserId;
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
/**
|
| 455 |
+
* Utility method to add a review comment.
|
| 456 |
+
*/
|
| 457 |
+
public void addReviewComment(String comment, UUID reviewerId, String reviewerRole) {
|
| 458 |
+
Map<String, Object> commentData = Map.of(
|
| 459 |
+
"comment", comment,
|
| 460 |
+
"reviewerId", reviewerId.toString(),
|
| 461 |
+
"reviewerRole", reviewerRole,
|
| 462 |
+
"timestamp", Instant.now().toString()
|
| 463 |
+
);
|
| 464 |
+
this.reviewComments.add(commentData);
|
| 465 |
+
}
|
| 466 |
+
|
| 467 |
+
/**
|
| 468 |
+
* Utility method to add a tag if not already present.
|
| 469 |
+
*/
|
| 470 |
+
public void addTag(String tag) {
|
| 471 |
+
if (!this.tags.contains(tag)) {
|
| 472 |
+
this.tags.add(tag);
|
| 473 |
+
}
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
/**
|
| 477 |
+
* Utility method to add a stakeholder if not already present.
|
| 478 |
+
*/
|
| 479 |
+
public void addStakeholder(UUID stakeholderId) {
|
| 480 |
+
if (!this.stakeholders.contains(stakeholderId)) {
|
| 481 |
+
this.stakeholders.add(stakeholderId);
|
| 482 |
+
}
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
@PrePersist
|
| 486 |
+
protected void onCreate() {
|
| 487 |
+
createdAt = Instant.now();
|
| 488 |
+
updatedAt = Instant.now();
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
@PreUpdate
|
| 492 |
+
protected void onUpdate() {
|
| 493 |
+
updatedAt = Instant.now();
|
| 494 |
+
}
|
| 495 |
+
}
|
src/main/java/com/dalab/policyengine/model/PolicyDraftStatus.java
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Status enumeration for policy drafts supporting complete workflow lifecycle.
|
| 5 |
+
* Tracks the draft from creation through approval and publication.
|
| 6 |
+
*/
|
| 7 |
+
public enum PolicyDraftStatus {
|
| 8 |
+
/**
|
| 9 |
+
* Draft has been created but not yet submitted for review.
|
| 10 |
+
*/
|
| 11 |
+
CREATED,
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Draft has been submitted and is awaiting review.
|
| 15 |
+
*/
|
| 16 |
+
SUBMITTED,
|
| 17 |
+
|
| 18 |
+
/**
|
| 19 |
+
* Draft is currently under review by approvers.
|
| 20 |
+
*/
|
| 21 |
+
UNDER_REVIEW,
|
| 22 |
+
|
| 23 |
+
/**
|
| 24 |
+
* Draft requires changes based on reviewer feedback.
|
| 25 |
+
*/
|
| 26 |
+
REQUIRES_CHANGES,
|
| 27 |
+
|
| 28 |
+
/**
|
| 29 |
+
* Draft has been approved and is ready for publication.
|
| 30 |
+
*/
|
| 31 |
+
APPROVED,
|
| 32 |
+
|
| 33 |
+
/**
|
| 34 |
+
* Draft has been rejected and will not be published.
|
| 35 |
+
*/
|
| 36 |
+
REJECTED,
|
| 37 |
+
|
| 38 |
+
/**
|
| 39 |
+
* Draft has been published as an active policy.
|
| 40 |
+
*/
|
| 41 |
+
PUBLISHED,
|
| 42 |
+
|
| 43 |
+
/**
|
| 44 |
+
* Draft has been archived (no longer active).
|
| 45 |
+
*/
|
| 46 |
+
ARCHIVED
|
| 47 |
+
}
|
src/main/java/com/dalab/policyengine/model/PolicyEvaluation.java
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
import java.util.UUID;
|
| 6 |
+
|
| 7 |
+
import org.hibernate.annotations.JdbcTypeCode;
|
| 8 |
+
import org.hibernate.type.SqlTypes;
|
| 9 |
+
|
| 10 |
+
import jakarta.persistence.*;
|
| 11 |
+
|
| 12 |
+
@Entity
|
| 13 |
+
@Table(name = "policy_evaluations")
|
| 14 |
+
public class PolicyEvaluation {
|
| 15 |
+
|
| 16 |
+
@Id
|
| 17 |
+
@GeneratedValue(strategy = GenerationType.AUTO)
|
| 18 |
+
@Column(columnDefinition = "UUID")
|
| 19 |
+
private UUID id;
|
| 20 |
+
|
| 21 |
+
@Column(nullable = false, columnDefinition = "UUID")
|
| 22 |
+
private UUID policyId;
|
| 23 |
+
|
| 24 |
+
@Column(nullable = false, length = 255) // External asset ID from da-catalog or other source
|
| 25 |
+
private String targetAssetId;
|
| 26 |
+
|
| 27 |
+
@Enumerated(EnumType.STRING)
|
| 28 |
+
@Column(nullable = false)
|
| 29 |
+
private PolicyEvaluationStatus status;
|
| 30 |
+
|
| 31 |
+
// Store details about the evaluation, e.g., which rules passed/failed, input facts snapshot
|
| 32 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 33 |
+
@Column(columnDefinition = "jsonb")
|
| 34 |
+
private Map<String, Object> evaluationDetails;
|
| 35 |
+
|
| 36 |
+
// Store actions that were triggered as a result of this evaluation
|
| 37 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 38 |
+
@Column(columnDefinition = "jsonb")
|
| 39 |
+
private Map<String, Object> triggeredActions;
|
| 40 |
+
|
| 41 |
+
@Column(nullable = false)
|
| 42 |
+
private Instant evaluatedAt;
|
| 43 |
+
|
| 44 |
+
@Column(columnDefinition = "UUID")
|
| 45 |
+
private UUID evaluationTriggeredByUserId; // Optional: if triggered by a user action
|
| 46 |
+
|
| 47 |
+
// Getters and Setters
|
| 48 |
+
|
| 49 |
+
public UUID getId() {
|
| 50 |
+
return id;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
public void setId(UUID id) {
|
| 54 |
+
this.id = id;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
public UUID getPolicyId() {
|
| 58 |
+
return policyId;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
public void setPolicyId(UUID policyId) {
|
| 62 |
+
this.policyId = policyId;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
public String getTargetAssetId() {
|
| 66 |
+
return targetAssetId;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
public void setTargetAssetId(String targetAssetId) {
|
| 70 |
+
this.targetAssetId = targetAssetId;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
public PolicyEvaluationStatus getStatus() {
|
| 74 |
+
return status;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
public void setStatus(PolicyEvaluationStatus status) {
|
| 78 |
+
this.status = status;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
public Map<String, Object> getEvaluationDetails() {
|
| 82 |
+
return evaluationDetails;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
public void setEvaluationDetails(Map<String, Object> evaluationDetails) {
|
| 86 |
+
this.evaluationDetails = evaluationDetails;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
public Map<String, Object> getTriggeredActions() {
|
| 90 |
+
return triggeredActions;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
public void setTriggeredActions(Map<String, Object> triggeredActions) {
|
| 94 |
+
this.triggeredActions = triggeredActions;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
public Instant getEvaluatedAt() {
|
| 98 |
+
return evaluatedAt;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
public void setEvaluatedAt(Instant evaluatedAt) {
|
| 102 |
+
this.evaluatedAt = evaluatedAt;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
public UUID getEvaluationTriggeredByUserId() {
|
| 106 |
+
return evaluationTriggeredByUserId;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
public void setEvaluationTriggeredByUserId(UUID evaluationTriggeredByUserId) {
|
| 110 |
+
this.evaluationTriggeredByUserId = evaluationTriggeredByUserId;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
@PrePersist
|
| 114 |
+
protected void onPersist() {
|
| 115 |
+
if (evaluatedAt == null) {
|
| 116 |
+
evaluatedAt = Instant.now();
|
| 117 |
+
}
|
| 118 |
+
}
|
| 119 |
+
}
|
src/main/java/com/dalab/policyengine/model/PolicyEvaluationStatus.java
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
public enum PolicyEvaluationStatus {
|
| 4 |
+
PASS, // Policy conditions met, actions may have been triggered
|
| 5 |
+
FAIL, // Policy conditions not met
|
| 6 |
+
ERROR, // Error during evaluation (e.g., bad rule syntax, fact unavailable)
|
| 7 |
+
PENDING, // Evaluation is queued or in progress
|
| 8 |
+
NOT_APPLICABLE // Policy was not applicable to the target asset
|
| 9 |
+
}
|
src/main/java/com/dalab/policyengine/model/PolicyRule.java
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
import java.util.UUID;
|
| 6 |
+
|
| 7 |
+
import org.hibernate.annotations.JdbcTypeCode;
|
| 8 |
+
import org.hibernate.type.SqlTypes;
|
| 9 |
+
|
| 10 |
+
import jakarta.persistence.*;
|
| 11 |
+
import jakarta.validation.constraints.NotBlank;
|
| 12 |
+
import jakarta.validation.constraints.Size;
|
| 13 |
+
|
| 14 |
+
@Entity
|
| 15 |
+
@Table(name = "policy_rules")
|
| 16 |
+
public class PolicyRule {
|
| 17 |
+
|
| 18 |
+
@Id
|
| 19 |
+
@GeneratedValue(strategy = GenerationType.AUTO)
|
| 20 |
+
@Column(columnDefinition = "UUID")
|
| 21 |
+
private UUID id;
|
| 22 |
+
|
| 23 |
+
@NotBlank
|
| 24 |
+
@Size(max = 255)
|
| 25 |
+
@Column(nullable = false)
|
| 26 |
+
private String name; // A unique name for the rule within the policy, e.g., "rule1", "checkPII"
|
| 27 |
+
|
| 28 |
+
@Size(max = 1000)
|
| 29 |
+
private String description;
|
| 30 |
+
|
| 31 |
+
@NotBlank
|
| 32 |
+
@Column(nullable = false, columnDefinition = "TEXT")
|
| 33 |
+
private String condition; // MVEL expression, e.g., "asset.assetType == 'S3_BUCKET' && asset.tags.contains('PII')"
|
| 34 |
+
|
| 35 |
+
// Rules with lower numbers have higher priority
|
| 36 |
+
@Column(nullable = false)
|
| 37 |
+
private int priority = 1;
|
| 38 |
+
|
| 39 |
+
// Optional: Actions specific to this rule, if different from policy-level actions or to augment them
|
| 40 |
+
@JdbcTypeCode(SqlTypes.JSON)
|
| 41 |
+
@Column(columnDefinition = "jsonb")
|
| 42 |
+
private Map<String, Object> actions;
|
| 43 |
+
|
| 44 |
+
@ManyToOne(fetch = FetchType.LAZY)
|
| 45 |
+
@JoinColumn(name = "policy_id", nullable = false)
|
| 46 |
+
private Policy policy;
|
| 47 |
+
|
| 48 |
+
@Column(nullable = false, updatable = false)
|
| 49 |
+
private Instant createdAt;
|
| 50 |
+
|
| 51 |
+
private Instant updatedAt;
|
| 52 |
+
|
| 53 |
+
// Getters and Setters
|
| 54 |
+
|
| 55 |
+
public UUID getId() {
|
| 56 |
+
return id;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
public void setId(UUID id) {
|
| 60 |
+
this.id = id;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
public String getName() {
|
| 64 |
+
return name;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
public void setName(String name) {
|
| 68 |
+
this.name = name;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
public String getDescription() {
|
| 72 |
+
return description;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
public void setDescription(String description) {
|
| 76 |
+
this.description = description;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
public String getCondition() {
|
| 80 |
+
return condition;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
public void setCondition(String condition) {
|
| 84 |
+
this.condition = condition;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
public int getPriority() {
|
| 88 |
+
return priority;
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
public void setPriority(int priority) {
|
| 92 |
+
this.priority = priority;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
public Map<String, Object> getActions() {
|
| 96 |
+
return actions;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
public void setActions(Map<String, Object> actions) {
|
| 100 |
+
this.actions = actions;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
public Policy getPolicy() {
|
| 104 |
+
return policy;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
public void setPolicy(Policy policy) {
|
| 108 |
+
this.policy = policy;
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
public Instant getCreatedAt() {
|
| 112 |
+
return createdAt;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
public void setCreatedAt(Instant createdAt) {
|
| 116 |
+
this.createdAt = createdAt;
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
public Instant getUpdatedAt() {
|
| 120 |
+
return updatedAt;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
public void setUpdatedAt(Instant updatedAt) {
|
| 124 |
+
this.updatedAt = updatedAt;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
@PrePersist
|
| 128 |
+
protected void onCreate() {
|
| 129 |
+
createdAt = Instant.now();
|
| 130 |
+
updatedAt = Instant.now();
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
@PreUpdate
|
| 134 |
+
protected void onUpdate() {
|
| 135 |
+
updatedAt = Instant.now();
|
| 136 |
+
}
|
| 137 |
+
}
|
src/main/java/com/dalab/policyengine/model/PolicyStatus.java
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.model;
|
| 2 |
+
|
| 3 |
+
public enum PolicyStatus {
|
| 4 |
+
ENABLED,
|
| 5 |
+
DISABLED
|
| 6 |
+
}
|
src/main/java/com/dalab/policyengine/repository/EventRuleRepository.java
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.repository;
|
| 2 |
+
|
| 3 |
+
import java.util.List;
|
| 4 |
+
import java.util.UUID;
|
| 5 |
+
|
| 6 |
+
import org.springframework.data.jpa.repository.JpaRepository;
|
| 7 |
+
import org.springframework.data.jpa.repository.Query;
|
| 8 |
+
import org.springframework.data.repository.query.Param;
|
| 9 |
+
import org.springframework.stereotype.Repository;
|
| 10 |
+
|
| 11 |
+
import com.dalab.policyengine.model.EventRule;
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Repository interface for EventRule entities.
|
| 15 |
+
* Provides data access methods for event rule management.
|
| 16 |
+
*/
|
| 17 |
+
@Repository
|
| 18 |
+
public interface EventRuleRepository extends JpaRepository<EventRule, UUID> {
|
| 19 |
+
|
| 20 |
+
/**
|
| 21 |
+
* Find all rules for a specific subscription
|
| 22 |
+
*/
|
| 23 |
+
List<EventRule> findBySubscriptionId(UUID subscriptionId);
|
| 24 |
+
|
| 25 |
+
/**
|
| 26 |
+
* Find enabled rules for a specific subscription ordered by priority
|
| 27 |
+
*/
|
| 28 |
+
List<EventRule> findBySubscriptionIdAndEnabledTrueOrderByPriorityAsc(UUID subscriptionId);
|
| 29 |
+
|
| 30 |
+
/**
|
| 31 |
+
* Find rules by name pattern
|
| 32 |
+
*/
|
| 33 |
+
List<EventRule> findByNameContainingIgnoreCase(String namePattern);
|
| 34 |
+
|
| 35 |
+
/**
|
| 36 |
+
* Find rules for a subscription by name pattern
|
| 37 |
+
*/
|
| 38 |
+
List<EventRule> findBySubscriptionIdAndNameContainingIgnoreCase(UUID subscriptionId, String namePattern);
|
| 39 |
+
|
| 40 |
+
/**
|
| 41 |
+
* Check if a rule with the given name already exists for a subscription
|
| 42 |
+
*/
|
| 43 |
+
boolean existsBySubscriptionIdAndName(UUID subscriptionId, String name);
|
| 44 |
+
|
| 45 |
+
/**
|
| 46 |
+
* Find rules by enabled status
|
| 47 |
+
*/
|
| 48 |
+
List<EventRule> findByEnabled(Boolean enabled);
|
| 49 |
+
|
| 50 |
+
/**
|
| 51 |
+
* Find rules with a specific priority
|
| 52 |
+
*/
|
| 53 |
+
List<EventRule> findByPriority(Integer priority);
|
| 54 |
+
|
| 55 |
+
/**
|
| 56 |
+
* Find rules created by a specific user
|
| 57 |
+
*/
|
| 58 |
+
List<EventRule> findByCreatedByUserId(UUID createdByUserId);
|
| 59 |
+
|
| 60 |
+
/**
|
| 61 |
+
* Count rules for a specific subscription
|
| 62 |
+
*/
|
| 63 |
+
long countBySubscriptionId(UUID subscriptionId);
|
| 64 |
+
|
| 65 |
+
/**
|
| 66 |
+
* Count enabled rules for a specific subscription
|
| 67 |
+
*/
|
| 68 |
+
long countBySubscriptionIdAndEnabledTrue(UUID subscriptionId);
|
| 69 |
+
|
| 70 |
+
/**
|
| 71 |
+
* Find rules that contain a specific condition pattern
|
| 72 |
+
*/
|
| 73 |
+
@Query("SELECT er FROM EventRule er WHERE er.condition LIKE %:conditionPattern%")
|
| 74 |
+
List<EventRule> findByConditionContaining(@Param("conditionPattern") String conditionPattern);
|
| 75 |
+
|
| 76 |
+
/**
|
| 77 |
+
* Find the highest priority rule for a subscription
|
| 78 |
+
*/
|
| 79 |
+
@Query("SELECT er FROM EventRule er WHERE er.subscription.id = :subscriptionId AND er.enabled = true ORDER BY er.priority ASC LIMIT 1")
|
| 80 |
+
EventRule findHighestPriorityEnabledRule(@Param("subscriptionId") UUID subscriptionId);
|
| 81 |
+
|
| 82 |
+
/**
|
| 83 |
+
* Find rules for a subscription ordered by priority
|
| 84 |
+
*/
|
| 85 |
+
List<EventRule> findBySubscriptionIdOrderByPriorityAsc(UUID subscriptionId);
|
| 86 |
+
}
|
src/main/java/com/dalab/policyengine/repository/EventSubscriptionRepository.java
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.repository;
|
| 2 |
+
|
| 3 |
+
import java.util.List;
|
| 4 |
+
import java.util.Optional;
|
| 5 |
+
import java.util.UUID;
|
| 6 |
+
|
| 7 |
+
import org.springframework.data.domain.Page;
|
| 8 |
+
import org.springframework.data.domain.Pageable;
|
| 9 |
+
import org.springframework.data.jpa.repository.JpaRepository;
|
| 10 |
+
import org.springframework.data.jpa.repository.Query;
|
| 11 |
+
import org.springframework.data.repository.query.Param;
|
| 12 |
+
import org.springframework.stereotype.Repository;
|
| 13 |
+
|
| 14 |
+
import com.dalab.policyengine.model.EventSubscription;
|
| 15 |
+
import com.dalab.policyengine.model.EventSubscriptionStatus;
|
| 16 |
+
import com.dalab.policyengine.model.EventType;
|
| 17 |
+
|
| 18 |
+
/**
|
| 19 |
+
* Repository interface for EventSubscription entities.
|
| 20 |
+
* Provides data access methods for event subscription management.
|
| 21 |
+
*/
|
| 22 |
+
@Repository
|
| 23 |
+
public interface EventSubscriptionRepository extends JpaRepository<EventSubscription, UUID> {
|
| 24 |
+
|
| 25 |
+
/**
|
| 26 |
+
* Find all event subscriptions for a specific user
|
| 27 |
+
*/
|
| 28 |
+
List<EventSubscription> findByUserId(UUID userId);
|
| 29 |
+
|
| 30 |
+
/**
|
| 31 |
+
* Find event subscriptions by user ID with pagination
|
| 32 |
+
*/
|
| 33 |
+
Page<EventSubscription> findByUserId(UUID userId, Pageable pageable);
|
| 34 |
+
|
| 35 |
+
/**
|
| 36 |
+
* Find event subscriptions by status
|
| 37 |
+
*/
|
| 38 |
+
List<EventSubscription> findByStatus(EventSubscriptionStatus status);
|
| 39 |
+
|
| 40 |
+
/**
|
| 41 |
+
* Find active event subscriptions for a specific user
|
| 42 |
+
*/
|
| 43 |
+
List<EventSubscription> findByUserIdAndStatus(UUID userId, EventSubscriptionStatus status);
|
| 44 |
+
|
| 45 |
+
/**
|
| 46 |
+
* Find event subscriptions that monitor a specific event type
|
| 47 |
+
*/
|
| 48 |
+
@Query("SELECT es FROM EventSubscription es JOIN es.eventTypes et WHERE et = :eventType AND es.status = 'ACTIVE'")
|
| 49 |
+
List<EventSubscription> findActiveSubscriptionsByEventType(@Param("eventType") EventType eventType);
|
| 50 |
+
|
| 51 |
+
/**
|
| 52 |
+
* Find event subscriptions that monitor a specific source service
|
| 53 |
+
*/
|
| 54 |
+
@Query("SELECT es FROM EventSubscription es JOIN es.sourceServices ss WHERE ss = :sourceService AND es.status = 'ACTIVE'")
|
| 55 |
+
List<EventSubscription> findActiveSubscriptionsBySourceService(@Param("sourceService") String sourceService);
|
| 56 |
+
|
| 57 |
+
/**
|
| 58 |
+
* Find event subscriptions by name pattern
|
| 59 |
+
*/
|
| 60 |
+
List<EventSubscription> findByNameContainingIgnoreCase(String namePattern);
|
| 61 |
+
|
| 62 |
+
/**
|
| 63 |
+
* Find event subscriptions for a user by name pattern
|
| 64 |
+
*/
|
| 65 |
+
List<EventSubscription> findByUserIdAndNameContainingIgnoreCase(UUID userId, String namePattern);
|
| 66 |
+
|
| 67 |
+
/**
|
| 68 |
+
* Check if a subscription with the given name already exists for a user
|
| 69 |
+
*/
|
| 70 |
+
boolean existsByUserIdAndName(UUID userId, String name);
|
| 71 |
+
|
| 72 |
+
/**
|
| 73 |
+
* Find active subscriptions that could match an event based on event type and source service
|
| 74 |
+
*/
|
| 75 |
+
@Query("SELECT DISTINCT es FROM EventSubscription es " +
|
| 76 |
+
"LEFT JOIN es.eventTypes et " +
|
| 77 |
+
"LEFT JOIN es.sourceServices ss " +
|
| 78 |
+
"WHERE es.status = 'ACTIVE' " +
|
| 79 |
+
"AND (et = :eventType OR es.eventTypes IS EMPTY) " +
|
| 80 |
+
"AND (ss = :sourceService OR es.sourceServices IS EMPTY)")
|
| 81 |
+
List<EventSubscription> findPotentialMatchingSubscriptions(
|
| 82 |
+
@Param("eventType") EventType eventType,
|
| 83 |
+
@Param("sourceService") String sourceService);
|
| 84 |
+
|
| 85 |
+
/**
|
| 86 |
+
* Count active subscriptions for a user
|
| 87 |
+
*/
|
| 88 |
+
long countByUserIdAndStatus(UUID userId, EventSubscriptionStatus status);
|
| 89 |
+
|
| 90 |
+
/**
|
| 91 |
+
* Find subscriptions created by a specific user
|
| 92 |
+
*/
|
| 93 |
+
List<EventSubscription> findByCreatedByUserId(UUID createdByUserId);
|
| 94 |
+
|
| 95 |
+
/**
|
| 96 |
+
* Find subscriptions with a specific notification type enabled
|
| 97 |
+
*/
|
| 98 |
+
@Query("SELECT es FROM EventSubscription es WHERE jsonb_extract_path_text(CAST(es.notificationConfig AS text), :notificationType) = 'true'")
|
| 99 |
+
List<EventSubscription> findSubscriptionsWithNotificationType(@Param("notificationType") String notificationType);
|
| 100 |
+
}
|
src/main/java/com/dalab/policyengine/repository/PolicyDraftRepository.java
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package com.dalab.policyengine.repository;
|
| 2 |
+
|
| 3 |
+
import java.time.Instant;
|
| 4 |
+
import java.util.List;
|
| 5 |
+
import java.util.UUID;
|
| 6 |
+
|
| 7 |
+
import org.springframework.data.domain.Page;
|
| 8 |
+
import org.springframework.data.domain.Pageable;
|
| 9 |
+
import org.springframework.data.jpa.repository.JpaRepository;
|
| 10 |
+
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
| 11 |
+
import org.springframework.data.jpa.repository.Query;
|
| 12 |
+
import org.springframework.data.repository.query.Param;
|
| 13 |
+
import org.springframework.stereotype.Repository;
|
| 14 |
+
|
| 15 |
+
import com.dalab.policyengine.model.PolicyDraft;
|
| 16 |
+
import com.dalab.policyengine.model.PolicyDraftStatus;
|
| 17 |
+
|
| 18 |
+
/**
|
| 19 |
+
* Repository interface for PolicyDraft entities.
|
| 20 |
+
* Provides comprehensive query methods for draft management and workflow operations.
|
| 21 |
+
*/
|
| 22 |
+
@Repository
|
| 23 |
+
public interface PolicyDraftRepository extends JpaRepository<PolicyDraft, UUID>, JpaSpecificationExecutor<PolicyDraft> {
|
| 24 |
+
|
| 25 |
+
/**
|
| 26 |
+
* Find all drafts by their current status.
|
| 27 |
+
*/
|
| 28 |
+
Page<PolicyDraft> findByStatus(PolicyDraftStatus status, Pageable pageable);
|
| 29 |
+
|
| 30 |
+
/**
|
| 31 |
+
* Find all drafts created by a specific user.
|
| 32 |
+
*/
|
| 33 |
+
Page<PolicyDraft> findByCreatedByUserId(UUID createdByUserId, Pageable pageable);
|
| 34 |
+
|
| 35 |
+
/**
|
| 36 |
+
* Find all drafts where the user is a stakeholder.
|
| 37 |
+
*/
|
| 38 |
+
@Query("SELECT pd FROM PolicyDraft pd WHERE :userId MEMBER OF pd.stakeholders")
|
| 39 |
+
Page<PolicyDraft> findByStakeholder(@Param("userId") UUID userId, Pageable pageable);
|
| 40 |
+
|
| 41 |
+
/**
|
| 42 |
+
* Find all drafts pending review (submitted or under review).
|
| 43 |
+
*/
|
| 44 |
+
@Query("SELECT pd FROM PolicyDraft pd WHERE pd.status IN ('SUBMITTED', 'UNDER_REVIEW')")
|
| 45 |
+
Page<PolicyDraft> findPendingReview(Pageable pageable);
|
| 46 |
+
|
| 47 |
+
/**
|
| 48 |
+
* Find all drafts that require attention from a specific user (created by them or they are stakeholder).
|
| 49 |
+
*/
|
| 50 |
+
@Query("SELECT DISTINCT pd FROM PolicyDraft pd WHERE pd.createdByUserId = :userId OR :userId MEMBER OF pd.stakeholders")
|
| 51 |
+
Page<PolicyDraft> findRequiringAttention(@Param("userId") UUID userId, Pageable pageable);
|
| 52 |
+
|
| 53 |
+
/**
|
| 54 |
+
* Find drafts by name containing specific text (case insensitive).
|
| 55 |
+
*/
|
| 56 |
+
Page<PolicyDraft> findByNameContainingIgnoreCase(String name, Pageable pageable);
|
| 57 |
+
|
| 58 |
+
/**
|
| 59 |
+
* Find drafts by category.
|
| 60 |
+
*/
|
| 61 |
+
Page<PolicyDraft> findByCategory(String category, Pageable pageable);
|
| 62 |
+
|
| 63 |
+
/**
|
| 64 |
+
* Find drafts by priority level.
|
| 65 |
+
*/
|
| 66 |
+
Page<PolicyDraft> findByPriority(String priority, Pageable pageable);
|
| 67 |
+
|
| 68 |
+
/**
|
| 69 |
+
* Find drafts that are based on a specific policy (updates to existing policies).
|
| 70 |
+
*/
|
| 71 |
+
List<PolicyDraft> findByBasePolicyId(UUID basePolicyId);
|
| 72 |
+
|
| 73 |
+
/**
|
| 74 |
+
* Find the latest version of drafts for a specific base policy.
|
| 75 |
+
*/
|
| 76 |
+
@Query("SELECT pd FROM PolicyDraft pd WHERE pd.basePolicyId = :basePolicyId ORDER BY pd.version DESC")
|
| 77 |
+
List<PolicyDraft> findLatestVersionByBasePolicyId(@Param("basePolicyId") UUID basePolicyId);
|
| 78 |
+
|
| 79 |
+
/**
|
| 80 |
+
* Find drafts with target implementation date before specified date.
|
| 81 |
+
*/
|
| 82 |
+
List<PolicyDraft> findByTargetImplementationDateBefore(Instant date);
|
| 83 |
+
|
| 84 |
+
/**
|
| 85 |
+
* Find drafts created within a specific time range.
|
| 86 |
+
*/
|
| 87 |
+
Page<PolicyDraft> findByCreatedAtBetween(Instant startDate, Instant endDate, Pageable pageable);
|
| 88 |
+
|
| 89 |
+
/**
|
| 90 |
+
* Find drafts that have been in a specific status for longer than specified time.
|
| 91 |
+
*/
|
| 92 |
+
@Query("SELECT pd FROM PolicyDraft pd WHERE pd.status = :status AND pd.updatedAt < :cutoffTime")
|
| 93 |
+
List<PolicyDraft> findStaleInStatus(@Param("status") PolicyDraftStatus status, @Param("cutoffTime") Instant cutoffTime);
|
| 94 |
+
|
| 95 |
+
/**
|
| 96 |
+
* Find drafts containing specific tags.
|
| 97 |
+
*/
|
| 98 |
+
@Query("SELECT pd FROM PolicyDraft pd WHERE :tag MEMBER OF pd.tags")
|
| 99 |
+
Page<PolicyDraft> findByTag(@Param("tag") String tag, Pageable pageable);
|
| 100 |
+
|
| 101 |
+
/**
|
| 102 |
+
* Find drafts by multiple criteria (complex search).
|
| 103 |
+
*/
|
| 104 |
+
@Query("SELECT pd FROM PolicyDraft pd WHERE " +
|
| 105 |
+
"(:status IS NULL OR pd.status = :status) AND " +
|
| 106 |
+
"(:category IS NULL OR pd.category = :category) AND " +
|
| 107 |
+
"(:priority IS NULL OR pd.priority = :priority) AND " +
|
| 108 |
+
"(:createdBy IS NULL OR pd.createdByUserId = :createdBy) AND " +
|
| 109 |
+
"(:nameFilter IS NULL OR LOWER(pd.name) LIKE LOWER(CONCAT('%', :nameFilter, '%')))")
|
| 110 |
+
Page<PolicyDraft> findByCriteria(
|
| 111 |
+
@Param("status") PolicyDraftStatus status,
|
| 112 |
+
@Param("category") String category,
|
| 113 |
+
@Param("priority") String priority,
|
| 114 |
+
@Param("createdBy") UUID createdBy,
|
| 115 |
+
@Param("nameFilter") String nameFilter,
|
| 116 |
+
Pageable pageable
|
| 117 |
+
);
|
| 118 |
+
|
| 119 |
+
/**
|
| 120 |
+
* Count drafts by status.
|
| 121 |
+
*/
|
| 122 |
+
long countByStatus(PolicyDraftStatus status);
|
| 123 |
+
|
| 124 |
+
/**
|
| 125 |
+
* Count drafts created by a specific user.
|
| 126 |
+
*/
|
| 127 |
+
long countByCreatedByUserId(UUID createdByUserId);
|
| 128 |
+
|
| 129 |
+
/**
|
| 130 |
+
* Check if a draft name already exists (for validation).
|
| 131 |
+
*/
|
| 132 |
+
boolean existsByName(String name);
|
| 133 |
+
|
| 134 |
+
/**
|
| 135 |
+
* Check if a draft name exists excluding a specific draft (for updates).
|
| 136 |
+
*/
|
| 137 |
+
@Query("SELECT CASE WHEN COUNT(pd) > 0 THEN true ELSE false END FROM PolicyDraft pd WHERE pd.name = :name AND pd.id != :excludeId")
|
| 138 |
+
boolean existsByNameExcludingId(@Param("name") String name, @Param("excludeId") UUID excludeId);
|
| 139 |
+
|
| 140 |
+
/**
|
| 141 |
+
* Find all distinct categories used in drafts.
|
| 142 |
+
*/
|
| 143 |
+
@Query("SELECT DISTINCT pd.category FROM PolicyDraft pd WHERE pd.category IS NOT NULL")
|
| 144 |
+
List<String> findAllCategories();
|
| 145 |
+
|
| 146 |
+
/**
|
| 147 |
+
* Find all distinct tags used in drafts.
|
| 148 |
+
*/
|
| 149 |
+
@Query("SELECT DISTINCT tag FROM PolicyDraft pd JOIN pd.tags tag")
|
| 150 |
+
List<String> findAllTags();
|
| 151 |
+
|
| 152 |
+
/**
|
| 153 |
+
* Get draft statistics for dashboard.
|
| 154 |
+
*/
|
| 155 |
+
@Query("SELECT pd.status, COUNT(pd) FROM PolicyDraft pd GROUP BY pd.status")
|
| 156 |
+
List<Object[]> getDraftStatisticsByStatus();
|
| 157 |
+
|
| 158 |
+
/**
|
| 159 |
+
* Get drafts summary by user.
|
| 160 |
+
*/
|
| 161 |
+
@Query("SELECT pd.createdByUserId, pd.status, COUNT(pd) FROM PolicyDraft pd GROUP BY pd.createdByUserId, pd.status")
|
| 162 |
+
List<Object[]> getDraftStatisticsByUser();
|
| 163 |
+
|
| 164 |
+
/**
|
| 165 |
+
* Find overdue drafts (target implementation date passed and still not published).
|
| 166 |
+
*/
|
| 167 |
+
@Query("SELECT pd FROM PolicyDraft pd WHERE pd.targetImplementationDate < :currentDate AND pd.status != 'PUBLISHED' AND pd.status != 'REJECTED' AND pd.status != 'ARCHIVED'")
|
| 168 |
+
List<PolicyDraft> findOverdueDrafts(@Param("currentDate") Instant currentDate);
|
| 169 |
+
}
|