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      ALLOWED_VALUES("allowed-values"),
32      CARDINALITY("cardinality"),
33      EXPECT("expect"),
34      INDEX("index"),
35      UNIQUE("unique"),
36      INDEX_HAS_KEY("index-has-key"),
37      MATCHES("matches");
38  
39      @NonNull
40      private final String name;
41  
42      Type(@NonNull String name) {
43        this.name = name;
44      }
45  
46      @NonNull
47      public String getName() {
48        return name;
49      }
50    }
51  
52    /**
53     * The degree to which a constraint violation is significant.
54     * <p>
55     * These values are ordered from least significant to most significant.
56     */
57    enum Level {
58      /**
59       * No violation.
60       */
61      NONE,
62      /**
63       * A violation of the constraint represents a point of interest.
64       */
65      INFORMATIONAL,
66      /**
67       * A violation of the constraint represents a fault in the content that may
68       * warrant review by a developer when performing model or tool development.
69       */
70      DEBUG,
71      /**
72       * A violation of the constraint represents a potential issue with the content.
73       */
74      WARNING,
75      /**
76       * A violation of the constraint represents a fault in the content. This may
77       * include issues around compatibility, integrity, consistency, etc.
78       */
79      ERROR,
80      /**
81       * A violation of the constraint represents a serious fault in the content that
82       * will prevent typical use of the content.
83       */
84      CRITICAL;
85    }
86  
87    /**
88     * Get the default level to use if no level is provided.
89     *
90     * @return the default level
91     */
92    @NonNull
93    static Level defaultLevel() {
94      return Level.ERROR;
95    }
96  
97    /**
98     * Get the Metapath to use if no target is provided.
99     *
100    * @return the expression
101    */
102   @NonNull
103   static IMetapathExpression defaultTarget() {
104     return IMetapathExpression.contextNode();
105   }
106 
107   /**
108    * Get a string that identifies the provided constraint using the most specific
109    * information available.
110    *
111    * @param constraint
112    *          the constraint to identify
113    * @return the constraint identification statement
114    */
115   @NonNull
116   static String getConstraintIdentity(@NonNull IConstraint constraint) {
117     String identity;
118     if (constraint.getId() != null) {
119       identity = String.format("with id '%s'", constraint.getId());
120     } else if (constraint.getFormalName() != null) {
121       identity = String.format("with the formal name '%s'", constraint.getFormalName());
122     } else {
123       identity = String.format("targeting '%s'", constraint.getTarget().getPath());
124     }
125     return ObjectUtils.notNull(identity);
126   }
127 
128   /**
129    * Get the constraint type.
130    *
131    * @return the constraint type
132    */
133   @NonNull
134   Type getType();
135 
136   /**
137    * Retrieve the unique identifier for the constraint.
138    *
139    * @return the identifier or {@code null} if no identifier is defined
140    */
141   @Nullable
142   String getId();
143 
144   /**
145    * Get information about the source of the constraint.
146    *
147    * @return the source information
148    */
149   @NonNull
150   ISource getSource();
151 
152   /**
153    * The significance of a violation of this constraint.
154    *
155    * @return the level
156    */
157   @NonNull
158   Level getLevel();
159 
160   /**
161    * Retrieve the Metapath expression to use to query the targets of the
162    * constraint.
163    *
164    * @return a Metapath expression
165    */
166   @NonNull
167   IMetapathExpression getTarget();
168 
169   /**
170    * Based on the provided {@code contextNodeItem}, find all nodes matching the
171    * target expression.
172    *
173    * @param item
174    *          the node item to evaluate the target expression against
175    * @param dynamicContext
176    *          the Metapath evaluation context to use
177    * @return the matching nodes as a sequence
178    * @throws MetapathException
179    *           if an error occurred during evaluation
180    * @see #getTarget()
181    */
182   @NonNull
183   ISequence<? extends IDefinitionNodeItem<?, ?>> matchTargets(
184       @NonNull IDefinitionNodeItem<?, ?> item,
185       @NonNull DynamicContext dynamicContext);
186 
187   /**
188    * Retrieve the remarks associated with the constraint.
189    *
190    * @return the remarks or {@code null} if no remarks are defined
191    */
192   MarkupMultiline getRemarks();
193 
194   /**
195    * Used for double dispatch supporting the visitor pattern provided by
196    * implementations of {@link IConstraintVisitor}.
197    *
198    * @param <T>
199    *          the Java type of a state object passed to the visitor
200    * @param <R>
201    *          the Java type of the result returned by the visitor methods
202    * @param visitor
203    *          the visitor implementation
204    * @param state
205    *          the state object passed to the visitor
206    * @return the visitation result
207    * @see IConstraintVisitor
208    */
209   <T, R> R accept(@NonNull IConstraintVisitor<T, R> visitor, T state);
210 }