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.item.node.INodeItem;
30  import gov.nist.secauto.metaschema.core.model.constraint.IConstraint.Level;
31  import gov.nist.secauto.metaschema.core.model.validation.IValidationFinding;
32  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
33  
34  import java.net.URI;
35  import java.util.Collections;
36  import java.util.Comparator;
37  import java.util.List;
38  
39  import edu.umd.cs.findbugs.annotations.NonNull;
40  import edu.umd.cs.findbugs.annotations.Nullable;
41  
42  /**
43   * Represents an individual constraint validation issue.
44   */
45  public class ConstraintValidationFinding implements IValidationFinding { // NOPMD - intentional
46    @NonNull
47    private final List<? extends IConstraint> constraints;
48    @NonNull
49    private final CharSequence message;
50    @NonNull
51    private final INodeItem node;
52    @NonNull
53    private final List<? extends INodeItem> targets;
54    private final Throwable cause;
55    private final Level severity;
56  
57    private ConstraintValidationFinding(
58        @NonNull List<? extends IConstraint> constraints,
59        @NonNull INodeItem node,
60        @NonNull CharSequence message,
61        @NonNull List<? extends INodeItem> targets,
62        @NonNull Level severity,
63        @Nullable Throwable cause) {
64      this.constraints = constraints;
65      this.node = node;
66      this.message = message;
67      this.targets = targets;
68      this.severity = severity;
69      this.cause = cause;
70    }
71  
72    public List<? extends IConstraint> getConstraints() {
73      return constraints;
74    }
75  
76    @Override
77    public CharSequence getMessage() {
78      return message;
79    }
80  
81    public INodeItem getNode() {
82      return node;
83    }
84  
85    public List<? extends INodeItem> getTargets() {
86      return targets;
87    }
88  
89    @Override
90    public Throwable getCause() {
91      return cause;
92    }
93  
94    @SuppressWarnings("null")
95    @Override
96    public Level getSeverity() {
97      return severity;
98    }
99  
100   @SuppressWarnings("null")
101   @Override
102   public @NonNull URI getDocumentUri() {
103     return getNode().getBaseUri();
104   }
105 
106   @NonNull
107   public static Builder builder(@NonNull List<? extends IConstraint> constraints, @NonNull INodeItem node) {
108     return new Builder(constraints, node);
109   }
110 
111   @NonNull
112   public static Builder builder(@NonNull IConstraint constraint, @NonNull INodeItem node) {
113     return new Builder(CollectionUtil.singletonList(constraint), node);
114   }
115 
116   public static final class Builder {
117     @NonNull
118     private final List<? extends IConstraint> constraints;
119     @NonNull
120     private final INodeItem node;
121     private CharSequence message;
122     private List<? extends INodeItem> targets;
123     private Throwable cause;
124     private Level severity;
125 
126     private Builder(@NonNull List<? extends IConstraint> constraints, @NonNull INodeItem node) {
127       this.constraints = constraints;
128       this.node = node;
129     }
130 
131     @NonNull
132     public Builder message(@NonNull CharSequence message) {
133       this.message = message;
134       return this;
135     }
136 
137     @NonNull
138     public Builder target(@NonNull INodeItem target) {
139       this.targets = Collections.singletonList(target);
140       return this;
141     }
142 
143     @NonNull
144     public Builder targets(@NonNull List<? extends INodeItem> targets) {
145       this.targets = CollectionUtil.unmodifiableList(targets);
146       return this;
147     }
148 
149     @NonNull
150     public Builder cause(@NonNull Throwable cause) {
151       this.cause = cause;
152       return this;
153     }
154 
155     @NonNull
156     public Builder severity(@NonNull Level severity) {
157       this.severity = severity;
158       return this;
159     }
160 
161     @NonNull
162     public ConstraintValidationFinding build() {
163       if (message == null) {
164         throw new IllegalStateException("Missing message");
165       }
166 
167       Level severity = this.severity == null ? constraints.stream()
168           .map(IConstraint::getLevel)
169           .max(Comparator.comparing(Level::ordinal))
170           .get() : this.severity;
171 
172       List<? extends INodeItem> targets = this.targets == null ? CollectionUtil.emptyList() : this.targets;
173 
174       assert message != null;
175       assert targets != null;
176       assert severity != null;
177 
178       return new ConstraintValidationFinding(
179           constraints,
180           node,
181           message,
182           targets,
183           severity,
184           cause);
185     }
186   }
187 }