1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.model.constraint.impl;
7   
8   import java.util.List;
9   import java.util.Map;
10  import java.util.Set;
11  
12  import dev.metaschema.core.datatype.markup.MarkupLine;
13  import dev.metaschema.core.datatype.markup.MarkupMultiline;
14  import dev.metaschema.core.metapath.IMetapathExpression;
15  import dev.metaschema.core.model.IAttributable;
16  import dev.metaschema.core.model.ISource;
17  import dev.metaschema.core.model.constraint.ConstraintInitializationException;
18  import dev.metaschema.core.model.constraint.IConstraint;
19  import dev.metaschema.core.model.constraint.IKeyConstraint;
20  import dev.metaschema.core.model.constraint.IKeyField;
21  import edu.umd.cs.findbugs.annotations.NonNull;
22  import edu.umd.cs.findbugs.annotations.Nullable;
23  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
24  
25  abstract class AbstractKeyConstraint
26      extends AbstractConfigurableMessageConstraint
27      implements IKeyConstraint {
28    @NonNull
29    private final List<IKeyField> keyFields;
30  
31    /**
32     * Create a new key-based constraint, which uses a set of key fields to build a
33     * key.
34     *
35     * @param id
36     *          the optional identifier for the constraint
37     * @param formalName
38     *          the constraint's formal name or {@code null} if not provided
39     * @param description
40     *          the constraint's semantic description or {@code null} if not
41     *          provided
42     * @param source
43     *          information about the constraint source
44     * @param level
45     *          the significance of a violation of this constraint
46     * @param target
47     *          the Metapath expression identifying the nodes the constraint targets
48     * @param properties
49     *          a collection of associated properties
50     * @param keyFields
51     *          a list of key fields associated with the constraint
52     * @param message
53     *          an optional message to emit when the constraint is violated
54     * @param remarks
55     *          optional remarks describing the intent of the constraint
56     */
57    @SuppressFBWarnings("CT_CONSTRUCTOR_THROW")
58    protected AbstractKeyConstraint(
59        @Nullable String id,
60        @Nullable String formalName,
61        @Nullable MarkupLine description,
62        @NonNull ISource source,
63        @NonNull Level level,
64        @NonNull IMetapathExpression target,
65        @NonNull Map<IAttributable.Key, Set<String>> properties,
66        @NonNull List<IKeyField> keyFields,
67        @Nullable String message,
68        @Nullable MarkupMultiline remarks) {
69      super(id, formalName, description, source, level, target, properties, message, remarks);
70      if (keyFields.isEmpty()) {
71        throw new ConstraintInitializationException(
72            String.format("An empty list of key fields is not allowed in the constraint %s in '%s'.",
73                IConstraint.getConstraintIdentity(this),
74                source.getLocationHint()));
75      }
76      this.keyFields = keyFields;
77    }
78  
79    @Override
80    public List<IKeyField> getKeyFields() {
81      return keyFields;
82    }
83  }