<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>eu.exeris</groupId>
        <artifactId>exeris-sdk-parent</artifactId>
        <version>0.12.0</version>
        <relativePath>../exeris-sdk-parent</relativePath>
    </parent>

    <artifactId>exeris-sdk-source-model</artifactId>
    <packaging>jar</packaging>

    <name>Exeris SDK :: Source Model</name>
    <description>
        Canonical AST/metadata types describing an Exeris domain (entities, fields,
        actions, relationships, sagas, projections, graph, UI, system fields).
        This module is the single source of truth for domain shape and is consumed
        by both the annotation processor (build-time extraction) and the future
        source parser/writer used by Studio and IDE plugins for bidirectional sync.
    </description>

    <properties>
        <!-- The AST wire-format version stamped into META-INF/exeris/ast-schema.json, and
             the same number SchemaVersion.CURRENT returns. It lives here because the
             processor path needs it as a compiler argument and SchemaVersion.CURRENT is
             deliberately not a compile-time constant (it is initialized from a method so it
             does not inline into consumers), which puts it out of reach of both the POM and
             the declaration model. The duplication is guarded, not tolerated:
             AstSchemaContractTest fails if the two disagree. Bump both together. -->
        <ast.schema.version>0.12.0</ast.schema.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>eu.exeris</groupId>
            <artifactId>exeris-sdk-annotations</artifactId>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>tools.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- The AST JSON Schema is generated from THIS module's own sources, by a
                 processor on the javac processor path. That path is not this project's
                 dependency tree: the published jar stays free of the emitter and of
                 databind. (The enforcer rule below proves the JavaParser half of zero
                 coupling only — ADR-037; databind is held at test scope by its declaration
                 above, not by that rule.) -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <executions>
                    <execution>
                        <id>default-compile</id>
                        <configuration>
                            <annotationProcessorPaths>
                                <path>
                                    <groupId>eu.exeris</groupId>
                                    <artifactId>exeris-sdk-annotation-catalog</artifactId>
                                    <version>${project.version}</version>
                                </path>
                            </annotationProcessorPaths>
                            <annotationProcessors>
                                <processor>eu.exeris.sdk.catalog.AstSchemaProcessor</processor>
                            </annotationProcessors>
                            <compilerArgs>
                                <arg>-Aexeris.schema.sdkVersion=${project.version}</arg>
                                <arg>-Aexeris.schema.astVersion=${ast.schema.version}</arg>
                            </compilerArgs>
                        </configuration>
                    </execution>
                    <execution>
                        <id>default-testCompile</id>
                        <configuration>
                            <!-- The schema describes the published surface. Running the
                                 emitter again over the tests would reopen the same output
                                 file and fail, and a schema carrying test fixtures would be
                                 describing something nobody ships. -->
                            <proc>none</proc>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals><goal>jar-no-fork</goal></goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <goals><goal>jar</goal></goals>
                    </execution>
                </executions>
            </plugin>

            <!-- 85% instruction + line coverage gate. Source-model is the
                 module where coverage is meaningful (records + builders +
                 convenience logic). Fails the build on regression. -->
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>jacoco-check</id>
                        <phase>verify</phase>
                        <goals><goal>check</goal></goals>
                        <configuration>
                            <rules>
                                <rule>
                                    <element>BUNDLE</element>
                                    <limits>
                                        <limit>
                                            <counter>INSTRUCTION</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>${jacoco.instruction.coverage.minimum}</minimum>
                                        </limit>
                                        <limit>
                                            <counter>LINE</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>${jacoco.line.coverage.minimum}</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- ADR-037 zero-coupling guard: source-model is the module every
                 AST-record consumer depends on, so JavaParser must never reach
                 its dependency tree (it lives in exeris-sdk-source-model-io).
                 Enforced in CI; the review skill catches it pre-merge. -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <executions>
                    <execution>
                        <id>ban-javaparser-zero-coupling</id>
                        <phase>verify</phase>
                        <goals><goal>enforce</goal></goals>
                        <configuration>
                            <rules>
                                <bannedDependencies>
                                    <excludes>
                                        <exclude>com.github.javaparser</exclude>
                                    </excludes>
                                    <message>ADR-037: JavaParser must stay in exeris-sdk-source-model-io only — it must not appear on this module's dependency tree (zero runtime coupling).</message>
                                </bannedDependencies>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- Semver gate: the root pom's opt-in `semver` profile, strict here — no relaxation.
                 This module is the reason the gate exists: the AST records are the surface
                 MIGRATION-0.x-to-1.0.md §3 lets grow a trailing component in a 1.x minor.

                 CONSTRUCTOR_REMOVED stays a break here, because it is one: removing a public
                 constructor is a NoSuchMethodError for every class compiled against it
                 (JLS 13.4.12) and a compile error for every positional caller. So a record that
                 grows keeps its previous arity as a public constructor delegating with null for
                 the new trailing components, and growth emits only CONSTRUCTOR_ADDED and
                 METHOD_ADDED, which the plugin defaults accept. Removing, renaming or retyping a
                 component changes an accessor and breaks.

                 Two tests hold the stance in every build, with or without the profile:
                 RecordConstructorLedgerTest, which fails if a published arity loses its
                 constructor, and RecordComponentOrderTest, which pins the one change no signature
                 shows — a reorder of same-typed components. -->
        </plugins>
    </build>
</project>
