|
1 | 1 | package life.qbic.compass.spi; |
2 | 2 |
|
3 | | -import java.util.Arrays; |
| 3 | +import java.util.BitSet; |
4 | 4 | import java.util.List; |
5 | 5 | import java.util.Objects; |
6 | 6 | import life.qbic.linksmith.model.WebLink; |
|
10 | 10 | * Contract for validating {@link WebLink} objects at the <em>model level</em>. |
11 | 11 | * |
12 | 12 | * <p><strong>Audience:</strong> Maintainers of the Compass library. |
13 | | - * This interface is internal to the validation layer and is not intended as a public extension |
| 13 | + * This interface is part of the internal validation layer and is not intended as a public extension |
14 | 14 | * point for end users.</p> |
15 | 15 | * |
16 | 16 | * <h2>Purpose</h2> |
|
36 | 36 | * </p> |
37 | 37 | * <ul> |
38 | 38 | * <li>Parsers produce {@link WebLink} instances (possibly permissive).</li> |
39 | | - * <li>{@code WebLinkModelValidator}s ensure the model obeys core Web Linking rules |
40 | | - * (e.g. RFC 8288 invariants).</li> |
| 39 | + * <li>{@code WebLinkModelValidator}s ensure the model obeys core Web Linking |
| 40 | + * invariants (e.g. RFC 8288 constraints).</li> |
41 | 41 | * <li>Signposting validators operate on a trusted model to apply FAIR-specific semantics.</li> |
42 | 42 | * </ul> |
43 | 43 | * |
@@ -84,45 +84,58 @@ public interface WebLinkModelValidator { |
84 | 84 | * |
85 | 85 | * <p> |
86 | 86 | * Implementations must inspect each element independently and accumulate all detected issues into |
87 | | - * the returned {@link IssueReport}. Validation must not stop after the first failure. |
| 87 | + * the returned {@link ModelValidationResult}. Validation must not stop after the first failure. |
88 | 88 | * </p> |
89 | 89 | * |
90 | 90 | * @param webLinks the list of {@link WebLink} instances to validate (must not be {@code null}) |
91 | | - * @return an {@link ModelValidationResult} containing all detected issues and the indices of |
92 | | - * weblinks with recorded ERROR |
| 91 | + * @return a {@link ModelValidationResult} containing all detected issues and information about |
| 92 | + * which input elements are considered blocking |
93 | 93 | * @throws NullPointerException if {@code webLinks} is {@code null} |
94 | 94 | */ |
95 | 95 | ModelValidationResult validate(List<WebLink> webLinks); |
96 | 96 |
|
97 | | - |
98 | | - record ModelValidationResult(IssueReport issueReport, boolean[] blockingLinkByIndex) { |
| 97 | + /** |
| 98 | + * Result object returned by {@link WebLinkModelValidator} implementations. |
| 99 | + * |
| 100 | + * <p> |
| 101 | + * The result consists of: |
| 102 | + * </p> |
| 103 | + * <ul> |
| 104 | + * <li>an {@link IssueReport} containing all detected validation issues, and</li> |
| 105 | + * <li>a {@link BitSet} indicating which input indices correspond to |
| 106 | + * <em>blocking</em> model violations.</li> |
| 107 | + * </ul> |
| 108 | + * |
| 109 | + * <p> |
| 110 | + * A blocking index represents a {@link WebLink} that must not be used for |
| 111 | + * downstream semantic processing (e.g. Signposting validation). |
| 112 | + * </p> |
| 113 | + * |
| 114 | + * <p> |
| 115 | + * This record is <strong>immutable</strong>: |
| 116 | + * </p> |
| 117 | + * <ul> |
| 118 | + * <li>The contained {@link IssueReport} is defensively copied.</li> |
| 119 | + * <li>The {@link BitSet} is defensively copied using {@link BitSet#clone()}.</li> |
| 120 | + * </ul> |
| 121 | + * |
| 122 | + * <p> |
| 123 | + * Modifying the original {@link IssueReport} or {@link BitSet} passed to the |
| 124 | + * constructor has no effect on the created result instance. |
| 125 | + * </p> |
| 126 | + * |
| 127 | + * @param issueReport all detected validation issues |
| 128 | + * @param blockingIndices bit set marking indices of blocking WebLinks |
| 129 | + * @since 1.0.0 |
| 130 | + */ |
| 131 | + record ModelValidationResult(IssueReport issueReport, BitSet blockingIndices) { |
99 | 132 |
|
100 | 133 | public ModelValidationResult { |
101 | | - issueReport = new IssueReport(List.copyOf(issueReport.issues())); |
102 | | - blockingLinkByIndex = Arrays.copyOf(blockingLinkByIndex, blockingLinkByIndex.length); |
103 | | - } |
| 134 | + Objects.requireNonNull(issueReport, "issueReport"); |
| 135 | + Objects.requireNonNull(blockingIndices, "blockingIndices"); |
104 | 136 |
|
105 | | - @Override |
106 | | - public boolean equals(Object o) { |
107 | | - if (o == null || getClass() != o.getClass()) { |
108 | | - return false; |
109 | | - } |
110 | | - ModelValidationResult that = (ModelValidationResult) o; |
111 | | - return Objects.equals(issueReport, that.issueReport) && Objects.deepEquals( |
112 | | - blockingLinkByIndex, that.blockingLinkByIndex); |
113 | | - } |
114 | | - |
115 | | - @Override |
116 | | - public int hashCode() { |
117 | | - return Objects.hash(issueReport, Arrays.hashCode(blockingLinkByIndex)); |
118 | | - } |
119 | | - |
120 | | - @Override |
121 | | - public String toString() { |
122 | | - return "ModelValidationResult{" + |
123 | | - "issueReport=" + issueReport + |
124 | | - ", blockingLinkByIndex=" + Arrays.toString(blockingLinkByIndex) + |
125 | | - '}'; |
| 137 | + issueReport = new IssueReport(List.copyOf(issueReport.issues())); |
| 138 | + blockingIndices = (BitSet) blockingIndices.clone(); |
126 | 139 | } |
127 | 140 | } |
128 | 141 | } |
0 commit comments