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.ObjectUtils;
33  
34  import java.util.Map;
35  import java.util.Set;
36  
37  import javax.xml.namespace.QName;
38  
39  import edu.umd.cs.findbugs.annotations.NonNull;
40  import edu.umd.cs.findbugs.annotations.Nullable;
41  
42  public final class DefaultCardinalityConstraint
43      extends AbstractConstraint
44      implements ICardinalityConstraint {
45    @Nullable
46    private final Integer minOccurs;
47    @Nullable
48    private final Integer maxOccurs;
49  
50    /**
51     * Construct a new cardinality constraint which enforces that the number of
52     * items matching the target fall within the inclusive range described by the
53     * {@code minOccurs} or {@code maxOccurs} values.
54     *
55     * @param id
56     *          the optional identifier for the constraint
57     * @param formalName
58     *          the constraint's formal name or {@code null} if not provided
59     * @param description
60     *          the constraint's semantic description or {@code null} if not
61     *          provided
62     * @param source
63     *          information about the constraint source
64     * @param level
65     *          the significance of a violation of this constraint
66     * @param target
67     *          the Metapath expression identifying the nodes the constraint targets
68     * @param properties
69     *          a collection of associated properties
70     * @param minOccurs
71     *          if provided, the constraint ensures that the count of targets is at
72     *          least this value
73     * @param maxOccurs
74     *          if provided, the constraint ensures that the count of targets is at
75     *          most this value
76     * @param remarks
77     *          optional remarks describing the intent of the constraint
78     */
79    private DefaultCardinalityConstraint(
80        @Nullable String id,
81        @Nullable String formalName,
82        @Nullable MarkupLine description,
83        @NonNull ISource source,
84        @NonNull Level level,
85        @NonNull MetapathExpression target,
86        @NonNull Map<QName, Set<String>> properties,
87        @Nullable Integer minOccurs,
88        @Nullable Integer maxOccurs,
89        MarkupMultiline remarks) {
90      super(id, formalName, description, source, level, target, properties, remarks);
91      if (minOccurs == null && maxOccurs == null) {
92        throw new IllegalArgumentException("at least one of minOccurs or maxOccurs must be provided");
93      }
94      this.minOccurs = minOccurs;
95      this.maxOccurs = maxOccurs;
96    }
97  
98    @Override
99    public Integer getMinOccurs() {
100     return minOccurs;
101   }
102 
103   @Override
104   public Integer getMaxOccurs() {
105     return maxOccurs;
106   }
107 
108   @Override
109   public <T, R> R accept(IConstraintVisitor<T, R> visitor, T state) {
110     return visitor.visitCardinalityConstraint(this, state);
111   }
112 
113   @NonNull
114   public static Builder builder() {
115     return new Builder();
116   }
117 
118   public static final class Builder
119       extends AbstractConstraintBuilder<Builder, DefaultCardinalityConstraint> {
120     private Integer minOccurs;
121     private Integer maxOccurs;
122 
123     private Builder() {
124       // disable construction
125     }
126 
127     public Builder minOccurs(int value) {
128       this.minOccurs = value;
129       return this;
130     }
131 
132     public Builder maxOccurs(int value) {
133       this.maxOccurs = value;
134       return this;
135     }
136 
137     @Override
138     protected Builder getThis() {
139       return this;
140     }
141 
142     @Override
143     protected void validate() {
144       super.validate();
145 
146       if (getMinOccurs() == null && getMaxOccurs() == null) {
147         throw new IllegalStateException("At least one of minOccurs or maxOccurs must be provided.");
148       }
149     }
150 
151     protected Integer getMinOccurs() {
152       return minOccurs;
153     }
154 
155     protected Integer getMaxOccurs() {
156       return maxOccurs;
157     }
158 
159     @Override
160     protected DefaultCardinalityConstraint newInstance() {
161       return new DefaultCardinalityConstraint(
162           getId(),
163           getFormalName(),
164           getDescription(),
165           ObjectUtils.notNull(getSource()),
166           getLevel(),
167           getTarget(),
168           getProperties(),
169           getMinOccurs(),
170           getMaxOccurs(),
171           getRemarks());
172     }
173   }
174 }