Feat: Add id attribute (gav) support to Dependency, Exclusion, Mixin - #11904
Feat: Add id attribute (gav) support to Dependency, Exclusion, Mixin#11904rbygrave wants to merge 18 commits into
Conversation
Based on design discussion on Issue apache#11500, the proposal is to support `groupId:artifactId:version` format for Dependency, Exclusion and Mixin. This means that we can define dependencies in the form: ```xml <dependency id="groupId:artifactId:version" /> ``` Examples: ```xml <dependency id="org.slf4j:slf4j-api:2.0.17"/> ``` ```xml <dependency id="org.postgresql:postgresql:42.7.3"> <exclusions> <exclusion id="*:*"/> </exclusions> </dependency> ``` ```xml <mixin id="com.example.mixins:java-mixin:1.0.0" /> ```
Add more tests and make them more specific to the validation that is being tested by each test.
| <superClass>Parent</superClass> | ||
| <fields> | ||
| <field xml.attribute="true" xml.tagName="id"> | ||
| <name>gav</name> |
There was a problem hiding this comment.
Using field name gav with attribute name id ... in order to avoid the conflict with the existing Parent.getId()
gnodet
left a comment
There was a problem hiding this comment.
Claude Code on behalf of Guillaume Nodet
Overall a clean implementation. The strict validation, test coverage, and the Mixin gav field workaround are well thought out. A few issues to address:
-
Dependency management dependencies are not expanded --
mergeDuplicatesonly expandsidonmodel.getDependencies()but not onmodel.getDependencyManagement().getDependencies(), nor on profile-scoped dependencies/dependency-management. The validator correctly validates all of these (lines 536-596 of DefaultModelValidator), so managed deps withidwill pass validation but never get expanded. -
Normalization runs after raw validation --
validateRawModelruns indoReadRawModel()(line 1818) beforemergeDuplicates(line 1362 inreadInputModel). The validator's duplicate-detection key logic (usingdependency.getId()directly when set) handles this correctly, but it means the validator sees the unexpanded state. This is fine for the conflict checks but worth keeping in mind. -
Dependency.getId()naming clash -- TheDependencyclass now has a newidfield withgetId()/setId()via the model generator. ButParent(and thereforeMixin) has a computedgetId()method in a codeSegment that returnsgroupId:artifactId:pom:version. SinceMixin extends Parent, the new field was wisely renamed togav. However, does Dependency have a similar computedgetId()method anywhere? If so, the newidfield's generated getter could shadow or conflict with it. Worth verifying the generated code compiles cleanly. -
isBlankdoes not trim -- TheisBlankhelper in the normalizer only checks for null/empty, not for whitespace-only strings. The nameisBlankis misleading sinceString.isBlank()checks whitespace. Consider renaming toisNullOrEmptyor usingString.isBlank()which handles whitespace in coordinates (e.g.," ").
| } | ||
| return builder.build(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Nit: this method name is misleading -- String.isBlank() in Java checks for whitespace-only strings, but this only checks null/empty. Consider renaming to isNullOrEmpty to avoid confusion, or use s == null || s.isBlank() to also handle whitespace-only values in coordinates.
| private static boolean isNullOrEmpty(String s) { | |
| return s == null || s.isEmpty(); | |
| } |
| if (dependency.getId() != null && !dependency.getId().isEmpty()) { | ||
| key = dependency.getId(); | ||
| } else { | ||
| key = dependency.getManagementKey(); |
There was a problem hiding this comment.
Good approach using dependency.getId() as the dedup key when set, since normalization hasn't run yet at this point. However, two dependencies with the same id attribute but different scopes/classifiers would collide here (since the key is just the raw id string, not the management key). After normalization, they'd have distinct management keys (which includes type and classifier). Is this the intended behavior?
… profiles - Expand id attributes on dependencies in dependencyManagement, not just top-level dependencies - Expand id attributes on dependencies within profile sections (both regular dependencies and profile dependencyManagement) - Extract expandAndDeduplicateDependencies() and expandProfileDependencyIds() helper methods - Rename isBlank to isNullOrEmpty for clarity - Add tests for dependency management and profile id expansion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add compact `id` XML attribute to Dependency, Exclusion, and Mixin elements in the Maven model (4.2.0+). Supported formats: - Dependency: g:a:v, g:a:type:v, g:a:type:classifier:v - Exclusion: g:a - Mixin (as `gav`/`id`): g:a:v The normalizer expands `id` into individual fields and clears it so consumer POMs never contain the attribute. Uses forceCopy=true in builders to ensure `id(null)` actually clears the field. Includes comprehensive unit tests (normalizer, validator), consumer POM transformation tests, and integration test verifying no id attributes leak into deployed POMs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…attributes Add DependencyIdStrategy that migrates verbose dependency/exclusion child elements into compact `id` attributes when upgrading to model version 4.2.0 via mvnup. The strategy runs at @priority(25), after InferenceStrategy (30), so only dependencies that still have full explicit coordinates after inference are collapsed. Triggered by --model-version 4.2.0 or --all. Supported transformations: - <dependency> g:a:v / g:a:type:v / g:a:type:classifier:v - <exclusion> g:a - Processes all sections: dependencies, dependencyManagement, profiles, plugin dependencies Inferred ids (partial coordinates like `:a` or `g:a` without version) are intentionally not supported — the `id` attribute is a shorthand for explicit coordinates, not a replacement for Maven's inference mechanism. Dependencies with missing coordinates after inference are left in their expanded form. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ribute Add support for 2-part `g:a` format and trailing-colon formats (`g:a:`, `g:a:type:`, `g:a:type:classifier:`) for dependencies whose version is provided by dependencyManagement. The trailing colon convention signals that version is managed, not missing. Leave aside inferred ids (`:a:` with inferred groupId) for now. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extend the compact id attribute format from groupId:artifactId:version to groupId:artifactId:version[@scope][?], where @scope sets the dependency scope and trailing ? marks the dependency as optional. Examples: - org.junit:junit-jupiter-api:5.0@test - commons-io:commons-io:2.11.0? - org.apache.maven:maven-core:3.9.0@provided? Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ature/dependency-id-attribute Combines type/classifier/managed-version support with @scope/? optional markers in the dependency id attribute compact syntax. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Empty segments in the compact id attribute are now skipped rather than setting fields to empty strings, allowing groupId/version/type to be left unset for later inference from dependencyManagement. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The formal syntax incorrectly showed version before type. Maven consistently uses groupId:artifactId:type:classifier:version order (as in Artifact.key() and Dependency.getManagementKey()). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dator - Remove redundant model version guard in DependencyIdStrategy (the second check alone suffices) - Simplify redundant type removal branches in collapseDependency() - Remove redundant validateExclusionIdAttribute call from effective model validation (id is already cleared by normalizer before effective validation) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
Review of this large PR (3100+ lines, 42 files) adding compact id attribute syntax for Dependency, Exclusion, and Mixin elements in Maven 4.2.0.
Confirmed finding:
- CI broken — integration test compilation error (high):
MavenITgh11904DependencyIdAttributeTestat line 44 callssuper("[4.0.0-rc-3-SNAPSHOT,)")butAbstractMavenIntegrationTestCaseonly has a no-arg constructor. All 9 integration-test CI jobs fail with this compilation error. The fix is straightforward — use the no-arg super call. This is likely due to the PR branch being stale relative to recent changes in theAbstractMavenIntegrationTestCasebase class.
Previous review feedback addressed:
- dependencyManagement and profile dependencies are now expanded ✅
isBlankrenamed toisNullOrEmpty✅
Positive observations:
- Test coverage is strong: unit tests for the normalizer (577 lines), validator (~150 new lines with 26 validation XML files), consumer POM transformation test, integration test, StAX reader tests, and mvnup strategy tests (967 lines)
- The
forceCopy=trueparameter in builders is correctly used to ensureid(null)clears the field rather than being treated as "no change" - The PR is large but the scope is well-defined and cohesive — splitting would risk inconsistent intermediate states
- The core feature (compact
idattribute) is well-designed and consistent with XML attribute conventions
Findings dropped after verification (6 false positives):
- Scope/optional asymmetry in DependencyIdStrategy: intentional design, explicitly tested
- Dedup key format mismatch: validator prohibits mixing
idand expanded forms - Dead code in switch default: defensive coding practice
- Duplicate
isNullOrEmptyhelpers: trivially private, not worth extracting - Mixin
gav/idnaming: documented Modello convention - Invalid
idpersisting through normalization: intentional for validator to catch
The main blocker is the CI compilation error — once that's fixed, the PR looks ready for a closer look at merge readiness.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
gnodet
left a comment
There was a problem hiding this comment.
Well-structured PR adding compact id attribute support for Dependency, Exclusion, and Mixin. The normalizer, validator, and mvnup strategy changes are sound. However, the integration test has a compilation error that breaks all 9 CI integration-test jobs.
All findings independently verified (4/4 confirmed):
- IT compilation error (high) —
MavenITgh11904DependencyIdAttributeTestcallssuper("[4.0.0-rc-3-SNAPSHOT,)")butAbstractMavenIntegrationTestCaseonly has a no-arg constructor (theStringconstructor was removed in commitbe9541cb9d). CI logs confirm all 9 integration-test jobs fail. - Missing mixin validation tests (medium) — ~48 lines of mixin
id/gavvalidation logic (format check, child element conflicts) are added toDefaultModelValidatorbutDefaultModelValidatorTesthas no mixin-related test cases. The normalizer and parser tests cover expansion/parsing, but validator error paths are untested. - Dedup key inconsistency (medium, low impact) — With
idset, the dedup key includes version (g:a:1.0); withoutid, the key isgetManagementKey()(no version). Practical impact is low since the normalizer properly deduplicates after expansion. - Duplicate
isNullOrEmpty(low) — Identical private methods inDefaultModelNormalizerandDefaultModelValidator. Trivial; noted for completeness.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
| class MavenITgh11904DependencyIdAttributeTest extends AbstractMavenIntegrationTestCase { | ||
|
|
||
| MavenITgh11904DependencyIdAttributeTest() { | ||
| super("[4.0.0-rc-3-SNAPSHOT,)"); |
There was a problem hiding this comment.
AbstractMavenIntegrationTestCase only has a no-arg constructor (the super(String) pattern was removed in commit be9541cb9d). This causes a compilation error that breaks all 9 integration-test CI jobs.
| super("[4.0.0-rc-3-SNAPSHOT,)"); | |
| MavenITgh11904DependencyIdAttributeTest() {} |
- Resolve merge conflicts with latest master - Remove version-range constructor from IT (master uses no-arg) - Add dependency/exclusion id attribute expansion in consumer POM builder to ensure id attributes are expanded to individual GAV fields before writing, matching the normalization performed during model building
The expandAndDeduplicateDependencies method was incorrectly applied to dependencyManagement sections, causing a regression in MavenITmng4403LenientDependencyPomParsingTest. That test relies on Maven tolerating duplicate dependency declarations in dependencyManagement of dependency POMs (per MNG-4005 lenient parsing behavior). The deduplication of dependencies (for backward compat with Maven 2.x lenient parsing) only applies to model.getDependencies(), not to dependencyManagement. Extract a dedicated expandDependencyIds() method that only expands id attributes without deduplication, and use it for dependencyManagement and profile dependencyManagement sections.
gnodet
left a comment
There was a problem hiding this comment.
Fix pushed: commit 1cd2408a68 addresses the MavenITmng4403LenientDependencyPomParsingTest regression.
Root cause: expandAndDeduplicateDependencies was applied to dependencyManagement sections, inadvertently deduplicating them. The MNG-4403 test relies on Maven tolerating duplicate <dependency> declarations in dependencyManagement of dependency POMs (MNG-4005 lenient parsing). The deduplication of getDependencies() is a backward-compat behavior inherited from Maven 2.x, but it was never applied to dependencyManagement.
Fix: extracted a dedicated expandDependencyIds() method that only expands id attributes without deduplication, and uses it for dependencyManagement and profile dependencyManagement sections. The expandAndDeduplicateDependencies method is now only used for model.getDependencies() as before.
gnodet
left a comment
There was a problem hiding this comment.
Re-review after latest push (commits f585904284 and 1cd2408a68).
Previous findings status:
- ✅ IT compilation error — fixed (no-arg constructor in
f585904284) ⚠️ Missing mixin validation tests — still no test coverage for the ~48 lines of mixinid/gavvalidation inDefaultModelValidator(format check, child element conflicts at lines 376-428). Not a blocker but a gap.- ℹ️ Dedup key inconsistency — acknowledged, low impact
- ℹ️ Duplicate
isNullOrEmpty— now in 3 files (normalizer, validator, consumer POM builder)
New findings from latest push:
Confirmed (1/1):
- Type-check divergence between normalizer and consumer POM builder (medium) —
DefaultModelNormalizer.expandDependencyId()usesisNullOrEmptyOrDefault(d.getType())for the type field in 4-part and 5-part ids (treating"jar"as empty/default), but the duplicated code inDefaultConsumerPomBuilder.expandSingleDependencyId()uses plainisNullOrEmpty(d.getType()). This means the consumer POM builder won't set the type fromidif the dependency already hastype="jar"explicitly set — while the normalizer would. In practice this is likely harmless (jar is the default), but it's a subtle behavioral difference between two implementations that are supposed to mirror each other. Worth harmonizing.
Observation (not blocking):
The ~190 lines of id expansion logic in DefaultConsumerPomBuilder is a near-verbatim copy of the normalizer's code. This is intentional (the consumer POM builder operates on an already-built model and needs its own expansion path), but it creates a maintenance risk: any future change to the id syntax parsing needs to be applied in two places. A shared utility method or a static helper class could reduce this. Not blocking for this PR, but worth considering for follow-up.
Latest fix assessment:
Commit 1cd2408a68 correctly separates expandDependencyIds() (id expansion only) from expandAndDeduplicateDependencies() (id expansion + deduplication). The deduplication is a Maven 2.x compat behavior that only applies to model.getDependencies(), not to dependencyManagement. The fix is clean and well-scoped — the MavenITmng4403LenientDependencyPomParsingTest regression is addressed.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
| } | ||
| break; | ||
| case 4: | ||
| if (!parts[2].isEmpty() && isNullOrEmpty(d.getType())) { |
There was a problem hiding this comment.
This uses isNullOrEmpty(d.getType()) but the equivalent code in DefaultModelNormalizer (line 264) uses isNullOrEmptyOrDefault(d.getType()) — which also treats "jar" as empty/default. The normalizer version is more correct: if a dependency already has type="jar" set explicitly, the normalizer will still set the type from the id attribute, but this consumer POM builder code won't. Consider using isNullOrEmptyOrDefault here too for consistency, or better yet, extract the shared parsing logic.
There was a problem hiding this comment.
Fixed in 4632bb8c13: both case-4 and case-5 now use isNullOrEmptyOrDefault(d.getType()), and the missing isNullOrEmptyOrDefault helper is added to the consumer POM builder.
gnodet
left a comment
There was a problem hiding this comment.
Review of the latest state (commits 153b6c49e3 through 1cd2408a68) — signal PUSHED.
All PR-specific unit tests pass locally:
DefaultModelNormalizerTest: 37/37 ✅DefaultModelValidatorTest: 107/107 ✅MavenStaxReaderTest: 14/14 ✅ConsumerPomArtifactTransformerTest: 11/11 ✅DependencyIdStrategyTest: 35/35 ✅
Previous review findings resolved:
IT compilation error— Fixed: no-arg constructor ✅dependencyManagement deduplication— Fixed in1cd2408a68: extractedexpandDependencyIds()that only expandsidattributes without deduplication.expandAndDeduplicateDependenciesnow only applies tomodel.getDependencies()✅
Confirmed findings (1 medium, 2 low):
1. Type check inconsistency between normalizer and consumer POM builder (medium)
The normalizer's expandDependencyId uses isNullOrEmptyOrDefault(d.getType()) (accepts null, "", or "jar") when deciding whether to set the type from the id attribute. The consumer POM builder's expandSingleDependencyId uses isNullOrEmpty(d.getType()) instead — it won't overwrite a default "jar" type.
This means a dependency with <type>jar</type> as a child element and id="g:a:war:1.0" would be expanded differently by the normalizer vs the consumer POM builder. In practice, the validator catches conflicts before the consumer POM builder runs, so this is more of a consistency issue than a bug. But the consumer POM builder copy should use isNullOrEmptyOrDefault to match the normalizer, since the two are meant to implement the same expansion logic.
DefaultModelNormalizer.java line 264:
if (!parts[2].isEmpty() && isNullOrEmptyOrDefault(d.getType())) {DefaultConsumerPomBuilder.java line 937:
if (!parts[2].isEmpty() && isNullOrEmpty(d.getType())) {2. ~150 lines of duplicated expansion logic (low)
The expandSingleDependencyId, expandDependencyIdList, expandExclusionIdList, and isNullOrEmpty methods are nearly identical copy-paste between DefaultModelNormalizer and DefaultConsumerPomBuilder. This is a maintenance risk — the type check inconsistency above is a direct consequence of this duplication. Consider extracting to a shared utility class, or having the consumer POM builder delegate to the normalizer.
3. Missing mixin validation tests (low)
Still unfixed from the previous review. ~48 lines of mixin id/gav validation logic (format check + child element conflict) in DefaultModelValidator have no corresponding test cases in DefaultModelValidatorTest. The normalizer and parser tests cover expansion/parsing, but the validator error paths for malformed mixin id attributes remain untested.
Findings dropped after verification:
- Dedup key inconsistency in validator (noted in prior reviews, low impact, validator prevents the pathological case)
expandAndDeduplicateDependenciesnull return contract — the callers handle it correctly
Overall, the PR is in good shape. The dedup regression fix is clean and well-scoped. The main actionable item is the type check inconsistency (#1) which is a straightforward fix.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
The consumer POM builder's expandSingleDependencyId() used isNullOrEmpty() for the type field in 4-part and 5-part id attributes, while the normalizer uses isNullOrEmptyOrDefault() which also treats "jar" as empty/default. This caused a behavioral divergence: the normalizer would set the type from the id attribute even when a dependency had type="jar" explicitly, but the consumer POM builder would not. Harmonize by using isNullOrEmptyOrDefault() in both places.
|
Fix pushed in Also addresses the observation about duplicated |
All findings from this review have been addressed in subsequent commits. IT compilation error fixed, dependencyManagement dedup regression fixed, type-check inconsistency fixed.
gnodet
left a comment
There was a problem hiding this comment.
Re-review after commit 4632bb8c13 — signal PUSHED.
All PR-specific unit tests pass locally:
DefaultModelNormalizerTest+DefaultModelValidatorTest: ✅ConsumerPomArtifactTransformerTest: ✅DependencyIdStrategyTest: ✅MavenStaxReaderTest: ✅
Previous finding resolved:
Type check inconsistency between normalizer and consumer POM builder— Fixed in4632bb8c13: both now useisNullOrEmptyOrDefault(d.getType())for type fields in 4-part and 5-part ids. The expansion logic inDefaultConsumerPomBuilder.expandSingleDependencyId()andDefaultModelNormalizer.expandDependencyId()is now fully aligned. ✅
Remaining findings (2 low):
1. Missing mixin validation tests (low)
~48 lines of mixin id/gav validation logic in DefaultModelValidator (lines 378-424: format check requiring exactly 3 parts, and child element conflict checks for groupId, artifactId, version) have no corresponding test cases. The normalizer and StAX reader tests cover expansion/parsing, but the validator error paths for malformed mixin id attributes remain untested. Not a blocker, but a test coverage gap.
2. Duplicated expansion logic across normalizer and consumer POM builder (low)
~150 lines of id expansion logic (expandSingleDependencyId, expandDependencyIdList, expandExclusionIdList, isNullOrEmpty, isNullOrEmptyOrDefault) are near-verbatim duplicated between DefaultModelNormalizer and DefaultConsumerPomBuilder. The type-check inconsistency fixed in this commit was a direct consequence of this duplication. A shared utility class or static helper could prevent future drift. Not blocking for this PR, but worth a follow-up.
Branch status: 6 commits behind master, clean merge (no conflicts).
Overall the PR is in good shape — the main actionable finding from the previous review has been addressed. The remaining items are low-priority improvements.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review after commit 4632bb8c — the type-check inconsistency between normalizer and consumer POM builder is fixed.
Previous finding resolved:
Type check inconsistency— Bothcase 4andcase 5inDefaultConsumerPomBuilder.expandSingleDependencyId()now useisNullOrEmptyOrDefault(d.getType()), matchingDefaultModelNormalizer.expandDependencyId(). The missingisNullOrEmptyOrDefaulthelper is added. ✅
Remaining (low, not blocking):
- ~150 lines of duplicated expansion logic across normalizer and consumer POM builder — maintenance risk, but not blocking for this PR.
- ~48 lines of mixin
id/gavvalidation logic inDefaultModelValidatorhave no corresponding test cases — not blocking.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Each <dependency> and <exclusion> element in the validator test fixtures now has a comment directly above it describing the expected outcome, making it possible to understand the test intent without cross-referencing DefaultModelValidatorTest.java.
Based on design discussion on Issue #11500, the proposal is to support a compact
idattribute format for Dependency, Exclusion and Mixin elements.Dependency
idFormatThe
idattribute supports the following compact formats, using the standard Maven coordinate order (groupId:artifactId:type:classifier:version):groupId:artifactId<dependencyManagement>groupId:artifactId:versiongroupId:artifactId:type:versiongroupId:artifactId:type:classifier:versionFull syntax:
groupId:artifactId[[:type[:classifier]]:version][@scope][?]A trailing
:(empty version) indicates the version is managed (e.g.groupId:artifactId:type:).Any segment may be left empty to skip setting that field, leaving it for later inference (e.g. from
dependencyManagement). For example,:artifactIdleaves groupId unset, and:artifactId:versionleaves groupId unset with an explicit version.An optional
@scopesuffix sets the dependency scope (test,provided,runtime,compile,system,import). A trailing?marks the dependency as optional.Examples
Validation
idis used, child elementsgroupId,artifactId, andversionmust not be specified (even if the corresponding segment in the id is empty).typeconflict is only checked when theidhas 4+ parts (3+ colons, i.e. type is encoded).classifierconflict is only checked when theidhas 5 parts (4 colons, i.e. classifier is encoded).@scopeis present in theid, a<scope>child element must not be specified.?is present, an<optional>child element must not be specified.idattribute.Inference
Empty segments are skipped during normalization, leaving the corresponding field unset for later inference. This allows patterns like:
:artifactId— groupId and version left unset for inference fromdependencyManagement:artifactId:version— groupId left unsetgroupId:artifactId:type:— version left unset (managed), type explicitNotes
idbut usesgavunderneath as the Java field, to work around a name clash withgetId()from Parent.idinto component fields and clears theidattribute, so downstream code works with standard dependency fields.idattribute only fills in fields that are currently null/empty.Following this checklist to help us incorporate your
contribution quickly and easily:
Note that commits might be squashed by a maintainer on merge.
This may not always be possible but is a best-practice.
mvn verifyto make sure basic checks pass.A more thorough check will be performed on your pull request automatically.
If your pull request is about ~20 lines of code you don't need to sign an
Individual Contributor License Agreement if you are unsure
please ask on the developers list.
To make clear that you license your contribution under
the Apache License Version 2.0, January 2004
you have to acknowledge this by using the following check-box.