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.datatype.markup.MarkupLine;
30  import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
31  import gov.nist.secauto.metaschema.core.metapath.MetapathExpression;
32  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
33  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
34  
35  import java.util.LinkedHashMap;
36  import java.util.LinkedHashSet;
37  import java.util.Map;
38  import java.util.Objects;
39  import java.util.Set;
40  
41  import javax.xml.namespace.QName;
42  
43  import edu.umd.cs.findbugs.annotations.NonNull;
44  import edu.umd.cs.findbugs.annotations.Nullable;
45  
46  public abstract class AbstractConstraint implements IConstraint { // NOPMD - intentional data class
47    @Nullable
48    private final String id;
49    @Nullable
50    private final String formalName;
51    @Nullable
52    private final MarkupLine description;
53    @NonNull
54    private final ISource source;
55    @NonNull
56    private final Level level;
57    @NonNull
58    private final MetapathExpression target;
59    @Nullable
60    private final MarkupMultiline remarks;
61    @NonNull
62    private final Map<QName, Set<String>> properties;
63  
64    /**
65     * Construct a new Metaschema constraint.
66     *
67     * @param id
68     *          the optional identifier for the constraint
69     * @param formalName
70     *          the constraint's formal name or {@code null} if not provided
71     * @param description
72     *          the constraint's semantic description or {@code null} if not
73     *          provided
74     * @param source
75     *          information about the constraint source
76     * @param level
77     *          the significance of a violation of this constraint
78     * @param target
79     *          the Metapath expression identifying the nodes the constraint targets
80     * @param properties
81     *          a collection of associated properties
82     * @param remarks
83     *          optional remarks describing the intent of the constraint
84     */
85    protected AbstractConstraint(
86        @Nullable String id,
87        @Nullable String formalName,
88        @Nullable MarkupLine description,
89        @NonNull ISource source,
90        @NonNull Level level,
91        @NonNull MetapathExpression target,
92        @NonNull Map<QName, Set<String>> properties,
93        @Nullable MarkupMultiline remarks) {
94      Objects.requireNonNull(target);
95      this.id = id;
96      this.formalName = formalName;
97      this.description = description;
98      this.source = source;
99      this.level = ObjectUtils.requireNonNull(level, "level");
100     this.target = ObjectUtils.requireNonNull(target, "target");
101     this.properties = properties;
102     this.remarks = remarks;
103   }
104 
105   @Override
106   public String getId() {
107     return id;
108   }
109 
110   @Override
111   public MarkupLine getDescription() {
112     return description;
113   }
114 
115   @Override
116   public String getFormalName() {
117     return formalName;
118   }
119 
120   @Override
121   public ISource getSource() {
122     return source;
123   }
124 
125   @Override
126   @NonNull
127   public Level getLevel() {
128     return level;
129   }
130 
131   @Override
132   public MetapathExpression getTarget() {
133     return target;
134   }
135 
136   @Override
137   public Map<QName, Set<String>> getProperties() {
138     return CollectionUtil.unmodifiableMap(properties);
139   }
140 
141   @Override
142   public MarkupMultiline getRemarks() {
143     return remarks;
144   }
145 
146   public abstract static class AbstractConstraintBuilder<
147       T extends AbstractConstraintBuilder<T,
148           R>,
149       R extends AbstractConstraint> {
150     private String id;
151     private String formalName;
152     private MarkupLine description;
153     private ISource source;
154     @NonNull
155     private Level level = IConstraint.DEFAULT_LEVEL;
156     @NonNull
157     private MetapathExpression target = IConstraint.DEFAULT_TARGET;
158     @NonNull
159     private Map<QName, Set<String>> properties = new LinkedHashMap<>(); // NOPMD not thread safe
160     private MarkupMultiline remarks;
161 
162     protected abstract T getThis();
163 
164     public T identifier(@NonNull String id) {
165       this.id = id;
166       return getThis();
167     }
168 
169     public T formalName(@NonNull String name) {
170       this.formalName = name;
171       return getThis();
172     }
173 
174     public T description(@NonNull MarkupLine description) {
175       this.description = description;
176       return getThis();
177     }
178 
179     public T source(@NonNull ISource source) {
180       this.source = source;
181       return getThis();
182     }
183 
184     public T level(@NonNull Level level) {
185       this.level = level;
186       return getThis();
187     }
188 
189     public T target(@NonNull MetapathExpression target) {
190       this.target = target;
191       return getThis();
192     }
193 
194     public T properties(@NonNull Map<QName, Set<String>> properties) {
195       this.properties = properties;
196       return getThis();
197     }
198 
199     public T property(@NonNull QName name, @NonNull String value) {
200       return property(name, CollectionUtil.singleton(value));
201     }
202 
203     public T property(@NonNull QName name, @NonNull Set<String> newValues) {
204       Set<String> existingValues = properties.get(name);
205       if (existingValues == null) {
206         existingValues = new LinkedHashSet<>();
207         properties.put(name, existingValues);
208       }
209 
210       existingValues.addAll(newValues);
211       return getThis();
212     }
213 
214     public T remarks(@NonNull MarkupMultiline remarks) {
215       this.remarks = remarks;
216       return getThis();
217     }
218 
219     protected void validate() {
220       ObjectUtils.requireNonNull(getSource());
221     }
222 
223     @NonNull
224     protected abstract R newInstance();
225 
226     @NonNull
227     public R build() {
228       validate();
229       return newInstance();
230     }
231 
232     protected String getId() {
233       return id;
234     }
235 
236     protected String getFormalName() {
237       return formalName;
238     }
239 
240     protected MarkupLine getDescription() {
241       return description;
242     }
243 
244     protected ISource getSource() {
245       return source;
246     }
247 
248     @NonNull
249     protected Level getLevel() {
250       return level;
251     }
252 
253     @NonNull
254     protected MetapathExpression getTarget() {
255       return target;
256     }
257 
258     @NonNull
259     protected Map<QName, Set<String>> getProperties() {
260       return properties;
261     }
262 
263     protected MarkupMultiline getRemarks() {
264       return remarks;
265     }
266   }
267 }