View Javadoc
1   /*
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.metaschema.core.model.constraint;
28  
29  import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
30  import gov.nist.secauto.metaschema.core.metapath.ISequence;
31  import gov.nist.secauto.metaschema.core.metapath.MetapathException;
32  import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter;
33  import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
34  import gov.nist.secauto.metaschema.core.model.constraint.IConstraint.Level;
35  import gov.nist.secauto.metaschema.core.model.validation.IValidationResult;
36  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
37  
38  import java.util.LinkedList;
39  import java.util.List;
40  import java.util.Objects;
41  
42  import edu.umd.cs.findbugs.annotations.NonNull;
43  
44  public class FindingCollectingConstraintValidationHandler
45      extends AbstractConstraintValidationHandler
46      implements IValidationResult {
47    @NonNull
48    private final List<ConstraintValidationFinding> findings = new LinkedList<>();
49    @NonNull
50    private IPathFormatter pathFormatter = IPathFormatter.METAPATH_PATH_FORMATER;
51    @NonNull
52    private Level highestLevel = IConstraint.Level.INFORMATIONAL;
53  
54    @Override
55    @NonNull
56    public IPathFormatter getPathFormatter() {
57      return pathFormatter;
58    }
59  
60    public void setPathFormatter(@NonNull IPathFormatter pathFormatter) {
61      this.pathFormatter = Objects.requireNonNull(pathFormatter, "pathFormatter");
62    }
63  
64    @Override
65    @NonNull
66    public List<ConstraintValidationFinding> getFindings() {
67      return CollectionUtil.unmodifiableList(findings);
68    }
69  
70    @Override
71    @NonNull
72    public Level getHighestSeverity() {
73      return highestLevel;
74    }
75  
76    protected void addFinding(@NonNull ConstraintValidationFinding finding) {
77      findings.add(finding);
78  
79      Level severity = finding.getSeverity();
80      if (severity.ordinal() > highestLevel.ordinal()) {
81        highestLevel = severity;
82      }
83    }
84  
85    @Override
86    public void handleCardinalityMinimumViolation(
87        @NonNull ICardinalityConstraint constraint,
88        @NonNull INodeItem node,
89        @NonNull ISequence<? extends INodeItem> targets) {
90      addFinding(ConstraintValidationFinding.builder(constraint, node)
91          .targets(targets.asList())
92          .message(newCardinalityMinimumViolationMessage(constraint, node, targets))
93          .build());
94    }
95  
96    @Override
97    public void handleCardinalityMaximumViolation(
98        @NonNull ICardinalityConstraint constraint,
99        @NonNull INodeItem node,
100       @NonNull ISequence<? extends INodeItem> targets) {
101     addFinding(ConstraintValidationFinding.builder(constraint, node)
102         .targets(targets.asList())
103         .message(newCardinalityMaximumViolationMessage(constraint, node, targets))
104         .build());
105   }
106 
107   @Override
108   public void handleIndexDuplicateKeyViolation(
109       @NonNull IIndexConstraint constraint,
110       @NonNull INodeItem node,
111       @NonNull INodeItem oldItem,
112       @NonNull INodeItem target) {
113     addFinding(ConstraintValidationFinding.builder(constraint, node)
114         .target(target)
115         .message(newIndexDuplicateKeyViolationMessage(constraint, node, oldItem, target))
116         .build());
117   }
118 
119   @Override
120   public void handleUniqueKeyViolation(
121       @NonNull IUniqueConstraint constraint,
122       @NonNull INodeItem node,
123       @NonNull INodeItem oldItem,
124       @NonNull INodeItem target) {
125     addFinding(ConstraintValidationFinding.builder(constraint, node)
126         .target(target)
127         .message(newUniqueKeyViolationMessage(constraint, node, oldItem, target))
128         .build());
129   }
130 
131   @SuppressWarnings("null")
132   @Override
133   public void handleKeyMatchError(
134       @NonNull IKeyConstraint constraint,
135       @NonNull INodeItem node,
136       @NonNull INodeItem target,
137       @NonNull MetapathException cause) {
138     addFinding(ConstraintValidationFinding.builder(constraint, node)
139         .target(target)
140         .message(cause.getLocalizedMessage())
141         .cause(cause)
142         .build());
143   }
144 
145   @Override
146   public void handleMatchPatternViolation(
147       @NonNull IMatchesConstraint constraint,
148       @NonNull INodeItem node,
149       @NonNull INodeItem target,
150       @NonNull String value) {
151     addFinding(ConstraintValidationFinding.builder(constraint, node)
152         .target(target)
153         .message(newMatchPatternViolationMessage(constraint, node, target, value))
154         .build());
155   }
156 
157   @Override
158   public void handleMatchDatatypeViolation(
159       @NonNull IMatchesConstraint constraint,
160       @NonNull INodeItem node,
161       @NonNull INodeItem target,
162       @NonNull String value,
163       @NonNull IllegalArgumentException cause) {
164     addFinding(ConstraintValidationFinding.builder(constraint, node)
165         .target(target)
166         .message(newMatchDatatypeViolationMessage(constraint, node, target, value))
167         .cause(cause)
168         .build());
169   }
170 
171   @Override
172   public void handleExpectViolation(
173       @NonNull IExpectConstraint constraint,
174       @NonNull INodeItem node,
175       @NonNull INodeItem target,
176       @NonNull DynamicContext dynamicContext) {
177     addFinding(ConstraintValidationFinding.builder(constraint, node)
178         .target(target)
179         .message(newExpectViolationMessage(constraint, node, target, dynamicContext))
180         .build());
181   }
182 
183   @Override
184   public void handleAllowedValuesViolation(@NonNull List<IAllowedValuesConstraint> failedConstraints,
185       @NonNull INodeItem target) {
186     addFinding(ConstraintValidationFinding.builder(failedConstraints, target)
187         .target(target)
188         .message(newAllowedValuesViolationMessage(failedConstraints, target))
189         .build());
190   }
191 
192   @Override
193   public void handleIndexDuplicateViolation(IIndexConstraint constraint, INodeItem node) {
194     addFinding(ConstraintValidationFinding.builder(constraint, node)
195         .message(newIndexDuplicateViolationMessage(constraint, node))
196         .severity(Level.CRITICAL)
197         .build());
198   }
199 
200   @Override
201   public void handleIndexMiss(IIndexHasKeyConstraint constraint, INodeItem node, INodeItem target, List<String> key) {
202     addFinding(ConstraintValidationFinding.builder(constraint, node)
203         .message(newIndexMissMessage(constraint, node, target, key))
204         .build());
205   }
206 
207 }