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.model.ISource;
9   import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
10  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
11  
12  import java.util.LinkedHashMap;
13  import java.util.LinkedList;
14  import java.util.List;
15  import java.util.Map;
16  import java.util.concurrent.locks.Lock;
17  import java.util.concurrent.locks.ReadWriteLock;
18  import java.util.concurrent.locks.ReentrantReadWriteLock;
19  
20  import edu.umd.cs.findbugs.annotations.NonNull;
21  
22  /**
23   * A container of rules constraining the effective model of a Metaschema field
24   * or flag data instance.
25   */
26  public class ValueConstraintSet implements IValueConstrained {
27    @NonNull
28    private final ISource source;
29    @SuppressWarnings("PMD.UseConcurrentHashMap") // need ordering
30    @NonNull
31    private final Map<IEnhancedQName, ILet> lets = new LinkedHashMap<>();
32    @NonNull
33    protected final List<IConstraint> constraints = new LinkedList<>();
34    @NonNull
35    private final List<IAllowedValuesConstraint> allowedValuesConstraints = new LinkedList<>();
36    @NonNull
37    private final List<IMatchesConstraint> matchesConstraints = new LinkedList<>();
38    @NonNull
39    private final List<IIndexHasKeyConstraint> indexHasKeyConstraints = new LinkedList<>();
40    @NonNull
41    private final List<IExpectConstraint> expectConstraints = new LinkedList<>();
42    @NonNull
43    protected final ReadWriteLock instanceLock = new ReentrantReadWriteLock();
44  
45    public ValueConstraintSet(@NonNull ISource source) {
46      this.source = source;
47    }
48  
49    @NonNull
50    public ISource getSource() {
51      return source;
52    }
53  
54    @Override
55    public Map<IEnhancedQName, ILet> getLetExpressions() {
56      return lets;
57    }
58  
59    @Override
60    public ILet addLetExpression(ILet let) {
61      return lets.put(let.getName(), let);
62    }
63  
64    @Override
65    public List<IConstraint> getConstraints() {
66      Lock readLock = instanceLock.readLock();
67      readLock.lock();
68      try {
69        return CollectionUtil.unmodifiableList(constraints);
70      } finally {
71        readLock.unlock();
72      }
73    }
74  
75    @Override
76    public List<IAllowedValuesConstraint> getAllowedValuesConstraints() {
77      Lock readLock = instanceLock.readLock();
78      readLock.lock();
79      try {
80        return CollectionUtil.unmodifiableList(allowedValuesConstraints);
81      } finally {
82        readLock.unlock();
83      }
84    }
85  
86    @Override
87    public List<IMatchesConstraint> getMatchesConstraints() {
88      Lock readLock = instanceLock.readLock();
89      readLock.lock();
90      try {
91        return CollectionUtil.unmodifiableList(matchesConstraints);
92      } finally {
93        readLock.unlock();
94      }
95    }
96  
97    @Override
98    public List<IIndexHasKeyConstraint> getIndexHasKeyConstraints() {
99      Lock readLock = instanceLock.readLock();
100     readLock.lock();
101     try {
102       return CollectionUtil.unmodifiableList(indexHasKeyConstraints);
103     } finally {
104       readLock.unlock();
105     }
106   }
107 
108   @Override
109   public List<IExpectConstraint> getExpectConstraints() {
110     Lock readLock = instanceLock.readLock();
111     readLock.lock();
112     try {
113       return CollectionUtil.unmodifiableList(expectConstraints);
114     } finally {
115       readLock.unlock();
116     }
117   }
118 
119   @Override
120   public final void addConstraint(@NonNull IAllowedValuesConstraint constraint) {
121     Lock writeLock = instanceLock.writeLock();
122     writeLock.lock();
123     try {
124       constraints.add(constraint);
125       allowedValuesConstraints.add(constraint);
126     } finally {
127       writeLock.unlock();
128     }
129   }
130 
131   @Override
132   public final void addConstraint(@NonNull IMatchesConstraint constraint) {
133     Lock writeLock = instanceLock.writeLock();
134     writeLock.lock();
135     try {
136       constraints.add(constraint);
137       matchesConstraints.add(constraint);
138     } finally {
139       writeLock.unlock();
140     }
141   }
142 
143   @Override
144   public final void addConstraint(@NonNull IIndexHasKeyConstraint constraint) {
145     Lock writeLock = instanceLock.writeLock();
146     writeLock.lock();
147     try {
148       constraints.add(constraint);
149       indexHasKeyConstraints.add(constraint);
150     } finally {
151       writeLock.unlock();
152     }
153   }
154 
155   @Override
156   public final void addConstraint(@NonNull IExpectConstraint constraint) {
157     Lock writeLock = instanceLock.writeLock();
158     writeLock.lock();
159     try {
160       constraints.add(constraint);
161       expectConstraints.add(constraint);
162     } finally {
163       writeLock.unlock();
164     }
165   }
166 }