View Javadoc
1   package org.opentrafficsim.base.parameters.constraint;
2   
3   import java.util.HashSet;
4   import java.util.Set;
5   
6   /**
7    * Constraint containing multiple constraints.
8    * <p>
9    * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
10   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
11   * <p>
12   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 11 sep. 2017 <br>
13   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
14   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
15   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
16   * @param <T> value type
17   */
18  public class MultiConstraint<T> implements Constraint<T>
19  {
20  
21      /** Set of constraints. */
22      private final Set<Constraint<T>> constraints;
23  
24      /** Message of the latest failed constrained. */
25      private String failedConstraintMessage = null;
26  
27      /** String representation. */
28      private final String stringRepresentation;
29  
30      /**
31       * Creates a {@code MultiConstraint} from given constraints.
32       * @param constraints constraints
33       * @param <T> value type
34       * @return {@code MultiConstraint}
35       */
36      @SafeVarargs
37      public static final <T> MultiConstraint<T> create(final Constraint<T>... constraints)
38      {
39          Set<Constraint<T>> set = new HashSet<>();
40          for (Constraint<T> constraint : constraints)
41          {
42              set.add(constraint);
43          }
44          return new MultiConstraint<>(set);
45      }
46  
47      /**
48       * Constructor.
49       * @param constraints constraints
50       */
51      public MultiConstraint(final Set<Constraint<T>> constraints)
52      {
53          this.constraints = constraints;
54          this.stringRepresentation = String.format("MultiConstraint [contains %d constraints]", this.constraints.size());
55      }
56  
57      /** {@inheritDoc} */
58      @Override
59      public boolean accept(final T value)
60      {
61          for (Constraint<T> constraint : this.constraints)
62          {
63              if (!constraint.accept(value))
64              {
65                  this.failedConstraintMessage = constraint.failMessage();
66                  return false;
67              }
68          }
69          return true;
70      }
71  
72      /** {@inheritDoc} */
73      @Override
74      public String failMessage()
75      {
76          if (this.failedConstraintMessage == null)
77          {
78              return "A constraint failed for parameter '%s'.";
79          }
80          // note that we do not synchronize, nor can't we be assured that after accept()=false, this method is (directly) invoked
81          return "A constraint failed, most likely: " + this.failedConstraintMessage;
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public String toString()
87      {
88          return this.stringRepresentation;
89      }
90  
91  }