1 /*
2 * SPDX-FileCopyrightText: none
3 * SPDX-License-Identifier: CC0-1.0
4 */
5
6 package gov.nist.secauto.metaschema.core.model.constraint;
7
8 import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
9 import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
10 import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
11 import gov.nist.secauto.metaschema.core.metapath.MetapathException;
12 import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
13 import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem;
14 import gov.nist.secauto.metaschema.core.model.IAttributable;
15 import gov.nist.secauto.metaschema.core.model.IDescribable;
16 import gov.nist.secauto.metaschema.core.model.ISource;
17 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
18
19 import edu.umd.cs.findbugs.annotations.NonNull;
20 import edu.umd.cs.findbugs.annotations.Nullable;
21
22 /**
23 * Represents a rule constraining the model of a Metaschema assembly, field or
24 * flag. Provides a common interface for all constraint definitions.
25 */
26 public interface IConstraint extends IAttributable, IDescribable {
27 /**
28 * The type of constraint.
29 */
30 enum Type {
31 /** Constraint restricting the set of allowed values. */
32 ALLOWED_VALUES("allowed-values"),
33 /** Constraint specifying occurrence requirements. */
34 CARDINALITY("cardinality"),
35 /** Constraint expressing an expected condition. */
36 EXPECT("expect"),
37 /** Constraint creating an index over items. */
38 INDEX("index"),
39 /** Constraint requiring uniqueness across items. */
40 UNIQUE("unique"),
41 /** Constraint verifying index key references. */
42 INDEX_HAS_KEY("index-has-key"),
43 /** Constraint validating pattern matching. */
44 MATCHES("matches");
45
46 @NonNull
47 private final String name;
48
49 Type(@NonNull String name) {
50 this.name = name;
51 }
52
53 /**
54 * Get the name identifier for this constraint type.
55 *
56 * @return the name
57 */
58 @NonNull
59 public String getName() {
60 return name;
61 }
62 }
63
64 /**
65 * The degree to which a constraint violation is significant.
66 * <p>
67 * These values are ordered from least significant to most significant.
68 */
69 enum Level {
70 /**
71 * No violation.
72 */
73 NONE,
74 /**
75 * A violation of the constraint represents a point of interest.
76 */
77 INFORMATIONAL,
78 /**
79 * A violation of the constraint represents a fault in the content that may
80 * warrant review by a developer when performing model or tool development.
81 */
82 DEBUG,
83 /**
84 * A violation of the constraint represents a potential issue with the content.
85 */
86 WARNING,
87 /**
88 * A violation of the constraint represents a fault in the content. This may
89 * include issues around compatibility, integrity, consistency, etc.
90 */
91 ERROR,
92 /**
93 * A violation of the constraint represents a serious fault in the content that
94 * will prevent typical use of the content.
95 */
96 CRITICAL;
97 }
98
99 /**
100 * Get the default level to use if no level is provided.
101 *
102 * @return the default level
103 */
104 @NonNull
105 static Level defaultLevel() {
106 return Level.ERROR;
107 }
108
109 /**
110 * Get the Metapath to use if no target is provided.
111 *
112 * @return the expression
113 */
114 @NonNull
115 static IMetapathExpression defaultTarget() {
116 return IMetapathExpression.contextNode();
117 }
118
119 /**
120 * Get a string that identifies the provided constraint using the most specific
121 * information available.
122 *
123 * @param constraint
124 * the constraint to identify
125 * @return the constraint identification statement
126 */
127 @NonNull
128 static String getConstraintIdentity(@NonNull IConstraint constraint) {
129 String identity;
130 if (constraint.getId() != null) {
131 identity = String.format("with id '%s'", constraint.getId());
132 } else if (constraint.getFormalName() != null) {
133 identity = String.format("with the formal name '%s'", constraint.getFormalName());
134 } else {
135 identity = String.format("targeting '%s'", constraint.getTarget().getPath());
136 }
137 return ObjectUtils.notNull(identity);
138 }
139
140 /**
141 * Get the constraint type.
142 *
143 * @return the constraint type
144 */
145 @NonNull
146 Type getType();
147
148 /**
149 * Retrieve the unique identifier for the constraint.
150 *
151 * @return the identifier or {@code null} if no identifier is defined
152 */
153 @Nullable
154 String getId();
155
156 /**
157 * Get information about the source of the constraint.
158 *
159 * @return the source information
160 */
161 @NonNull
162 ISource getSource();
163
164 /**
165 * The significance of a violation of this constraint.
166 *
167 * @return the level
168 */
169 @NonNull
170 Level getLevel();
171
172 /**
173 * Retrieve the Metapath expression to use to query the targets of the
174 * constraint.
175 *
176 * @return a Metapath expression
177 */
178 @NonNull
179 IMetapathExpression getTarget();
180
181 /**
182 * Based on the provided {@code contextNodeItem}, find all nodes matching the
183 * target expression.
184 *
185 * @param item
186 * the node item to evaluate the target expression against
187 * @param dynamicContext
188 * the Metapath evaluation context to use
189 * @return the matching nodes as a sequence
190 * @throws MetapathException
191 * if an error occurred during evaluation
192 * @see #getTarget()
193 */
194 @NonNull
195 ISequence<? extends IDefinitionNodeItem<?, ?>> matchTargets(
196 @NonNull IDefinitionNodeItem<?, ?> item,
197 @NonNull DynamicContext dynamicContext);
198
199 /**
200 * Retrieve the remarks associated with the constraint.
201 *
202 * @return the remarks or {@code null} if no remarks are defined
203 */
204 MarkupMultiline getRemarks();
205
206 /**
207 * Used for double dispatch supporting the visitor pattern provided by
208 * implementations of {@link IConstraintVisitor}.
209 *
210 * @param <T>
211 * the Java type of a state object passed to the visitor
212 * @param <R>
213 * the Java type of the result returned by the visitor methods
214 * @param visitor
215 * the visitor implementation
216 * @param state
217 * the state object passed to the visitor
218 * @return the visitation result
219 * @see IConstraintVisitor
220 */
221 <T, R> R accept(@NonNull IConstraintVisitor<T, R> visitor, T state);
222 }