001/* 002 * Portions of this software was developed by employees of the National Institute 003 * of Standards and Technology (NIST), an agency of the Federal Government and is 004 * being made available as a public service. Pursuant to title 17 United States 005 * Code Section 105, works of NIST employees are not subject to copyright 006 * protection in the United States. This software may be subject to foreign 007 * copyright. Permission in the United States and in foreign countries, to the 008 * extent that NIST may hold copyright, to use, copy, modify, create derivative 009 * works, and distribute this software and its documentation without fee is hereby 010 * granted on a non-exclusive basis, provided that this notice and disclaimer 011 * of warranty appears in all copies. 012 * 013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER 014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY 015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF 016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM 017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE 018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT 019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, 020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, 021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, 022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR 023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT 024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. 025 */ 026 027package gov.nist.secauto.metaschema.core.model.constraint; 028 029import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; 030import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; 031import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; 032import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; 033import gov.nist.secauto.metaschema.core.util.ObjectUtils; 034 035import java.util.LinkedHashMap; 036import java.util.Map; 037import java.util.Set; 038 039import javax.xml.namespace.QName; 040 041import edu.umd.cs.findbugs.annotations.NonNull; 042import edu.umd.cs.findbugs.annotations.Nullable; 043 044public final class DefaultAllowedValuesConstraint 045 extends AbstractConstraint 046 implements IAllowedValuesConstraint { 047 private final boolean allowedOther; 048 @NonNull 049 private final Extensible extensible; 050 @NonNull 051 private final Map<String, DefaultAllowedValue> allowedValues; 052 053 /** 054 * Construct a new allowed values constraint which ensures that a target 055 * instance's value match one of the allowed values. This match is required if 056 * {@link #isAllowedOther()} is {@code false}, otherwise the constraint will 057 * generate a validation warning message if the target instance's value does not 058 * match any of the associated allowed value constraints targeting it. 059 * 060 * the associated test evaluates to {@link IBooleanItem#TRUE} against the 061 * target. 062 * 063 * @param id 064 * the optional identifier for the constraint 065 * @param formalName 066 * the constraint's formal name or {@code null} if not provided 067 * @param description 068 * the constraint's semantic description or {@code null} if not 069 * provided 070 * @param source 071 * information about the constraint source 072 * @param level 073 * the significance of a violation of this constraint 074 * @param target 075 * the Metapath expression identifying the nodes the constraint targets 076 * @param properties 077 * a collection of associated properties 078 * @param allowedValues 079 * the list of allowed values for this constraint 080 * @param allowedOther 081 * when {@code true} values other than the values specified by 082 * {@code allowedValues} are allowed, or disallowed if {@code false} 083 * @param extensible 084 * indicates the degree to which extended values should be allowed 085 * @param remarks 086 * optional remarks describing the intent of the constraint 087 */ 088 private DefaultAllowedValuesConstraint( // NOPMD necessary 089 @Nullable String id, 090 @Nullable String formalName, 091 @Nullable MarkupLine description, 092 @NonNull ISource source, 093 @NonNull Level level, 094 @NonNull MetapathExpression target, 095 @NonNull Map<QName, Set<String>> properties, 096 @NonNull Map<String, DefaultAllowedValue> allowedValues, 097 boolean allowedOther, 098 @NonNull Extensible extensible, 099 @Nullable MarkupMultiline remarks) { 100 super(id, formalName, description, source, level, target, properties, remarks); 101 this.allowedValues = allowedValues; 102 this.allowedOther = allowedOther; 103 this.extensible = extensible; 104 } 105 106 @Override 107 public Map<String, DefaultAllowedValue> getAllowedValues() { 108 return allowedValues; 109 } 110 111 @Override 112 public boolean isAllowedOther() { 113 return allowedOther; 114 } 115 116 @Override 117 public Extensible getExtensible() { 118 return extensible; 119 } 120 121 @Override 122 public <T, R> R accept(IConstraintVisitor<T, R> visitor, T state) { 123 return visitor.visitAllowedValues(this, state); 124 } 125 126 @NonNull 127 public static Builder builder() { 128 return new Builder(); 129 } 130 131 public static final class Builder 132 extends AbstractConstraintBuilder<Builder, DefaultAllowedValuesConstraint> { 133 @NonNull 134 private final Map<String, DefaultAllowedValue> allowedValues = new LinkedHashMap<>(); // NOPMD not thread safe 135 private boolean allowedOther = IAllowedValuesConstraint.DEFAULT_ALLOW_OTHER; 136 @NonNull 137 private Extensible extensible = IAllowedValuesConstraint.DEFAULT_EXTENSIBLE; 138 139 private Builder() { 140 // disable construction 141 } 142 143 public Builder allowedValue(@NonNull DefaultAllowedValue allowedValue) { 144 this.allowedValues.put(allowedValue.getValue(), allowedValue); 145 return this; 146 } 147 148 public Builder allowedValues(@NonNull Map<String, DefaultAllowedValue> allowedValues) { 149 this.allowedValues.putAll(allowedValues); 150 return this; 151 } 152 153 public Builder allowedOther(boolean bool) { 154 this.allowedOther = bool; 155 return this; 156 } 157 158 public Builder extensible(@NonNull Extensible extensible) { 159 this.extensible = extensible; 160 return this; 161 } 162 163 @Override 164 protected Builder getThis() { 165 return this; 166 } 167 168 @NonNull 169 protected Map<String, DefaultAllowedValue> getAllowedValues() { 170 return allowedValues; 171 } 172 173 protected boolean isAllowedOther() { 174 return allowedOther; 175 } 176 177 @NonNull 178 protected Extensible getExtensible() { 179 return extensible; 180 } 181 182 @Override 183 protected DefaultAllowedValuesConstraint newInstance() { 184 return new DefaultAllowedValuesConstraint( 185 getId(), 186 getFormalName(), 187 getDescription(), 188 ObjectUtils.notNull(getSource()), 189 getLevel(), 190 getTarget(), 191 getProperties(), 192 getAllowedValues(), 193 isAllowedOther(), 194 getExtensible(), 195 getRemarks()); 196 } 197 } 198}