View Javadoc
1   /**
2    * Copyright (C) 2014-2018 Philip Helger (www.helger.com)
3    * philip[at]helger[dot]com
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *         http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package com.helger.schematron.pure.binding.xpath;
18  
19  import java.util.Map;
20  
21  import javax.annotation.Nonnull;
22  import javax.annotation.Nullable;
23  import javax.annotation.concurrent.NotThreadSafe;
24  
25  import com.helger.commons.ValueEnforcer;
26  import com.helger.commons.annotation.Nonempty;
27  import com.helger.commons.annotation.ReturnsMutableCopy;
28  import com.helger.commons.collection.impl.CommonsTreeMap;
29  import com.helger.commons.collection.impl.ICommonsNavigableMap;
30  import com.helger.commons.compare.IComparator;
31  import com.helger.commons.state.EChange;
32  import com.helger.commons.string.StringHelper;
33  import com.helger.commons.string.ToStringGenerator;
34  
35  /**
36   * This class manages all variables present in Schematron <let> elements.
37   *
38   * @author Philip Helger
39   */
40  @NotThreadSafe
41  public class PSXPathVariables implements IPSXPathVariables
42  {
43    @Nonnull
44    @ReturnsMutableCopy
45    private static ICommonsNavigableMap <String, String> _createMap ()
46    {
47      return new CommonsTreeMap <> (IComparator.getComparatorStringLongestFirst ());
48    }
49  
50    private final ICommonsNavigableMap <String, String> m_aMap;
51  
52    public PSXPathVariables ()
53    {
54      m_aMap = _createMap ();
55    }
56  
57    public PSXPathVariables (@Nonnull final IPSXPathVariables aOther)
58    {
59      m_aMap = aOther.getAll ();
60    }
61  
62    /**
63     * Add a new variable.
64     *
65     * @param aEntry
66     *        The entry to be added - key is the variable name and value is the
67     *        variable value. May not be <code>null</code>.
68     * @return {@link EChange#UNCHANGED} if a variable with the same name is
69     *         already present. Never <code>null</code>.
70     */
71    @Nonnull
72    public EChange add (@Nonnull final Map.Entry <String, String> aEntry)
73    {
74      return add (aEntry.getKey (), aEntry.getValue ());
75    }
76  
77    /**
78     * Add a new variable.
79     *
80     * @param sName
81     *        The name of the variable. May neither be <code>null</code> nor
82     *        empty.
83     * @param sValue
84     *        The value of the variable. May neither be <code>null</code> nor
85     *        empty.
86     * @return {@link EChange#UNCHANGED} if a variable with the same name is
87     *         already present. Never <code>null</code>.
88     */
89    @Nonnull
90    public EChange add (@Nonnull @Nonempty final String sName, @Nonnull @Nonempty final String sValue)
91    {
92      ValueEnforcer.notEmpty (sName, "Name");
93      ValueEnforcer.notEmpty (sValue, "Value");
94  
95      // Prepend the "$" prefix to the variable name
96      final String sRealName = PSXPathQueryBinding.PARAM_VARIABLE_PREFIX + sName;
97      if (m_aMap.containsKey (sRealName))
98        return EChange.UNCHANGED;
99  
100     // Apply all existing variables to this variable value!
101     // This ensures that all variables used in variables are resolved correctly
102     // as long as the order of declaration is correct.
103     // Additionally this means that the order of the variables in this class is
104     // irrelevant
105     final String sRealValue = getAppliedReplacement (sValue);
106     m_aMap.put (sRealName, sRealValue);
107     return EChange.CHANGED;
108   }
109 
110   @Nullable
111   public String getAppliedReplacement (@Nullable final String sText)
112   {
113     return PSXPathQueryBinding.getWithParamTextsReplacedStatic (sText, m_aMap);
114   }
115 
116   /**
117    * Remove the variable with the specified name
118    *
119    * @param sVarName
120    *        The name of the variable to be removed. May be <code>null</code>.
121    * @return {@link EChange#CHANGED} if the variable was removed successfully.
122    *         Never <code>null</code>.
123    */
124   @Nonnull
125   public EChange remove (@Nullable final String sVarName)
126   {
127     if (StringHelper.hasText (sVarName))
128       if (m_aMap.remove (PSXPathQueryBinding.PARAM_VARIABLE_PREFIX + sVarName) == null)
129         return EChange.CHANGED;
130     return EChange.UNCHANGED;
131   }
132 
133   /**
134    * Remove all variables with the specified names
135    *
136    * @param aVars
137    *        A list of variable names to be removed. May be <code>null</code>.
138    * @return {@link EChange#CHANGED} if at least one variable was removed
139    *         successfully. Never <code>null</code>.
140    */
141   @Nonnull
142   public EChange removeAll (@Nullable final Iterable <String> aVars)
143   {
144     EChange eChange = EChange.UNCHANGED;
145     if (aVars != null)
146       for (final String sName : aVars)
147         eChange = eChange.or (remove (sName));
148     return eChange;
149   }
150 
151   @Nonnull
152   @ReturnsMutableCopy
153   public ICommonsNavigableMap <String, String> getAll ()
154   {
155     return m_aMap.getClone ();
156   }
157 
158   public boolean contains (@Nullable final String sName)
159   {
160     if (StringHelper.hasNoText (sName))
161       return false;
162     return m_aMap.containsKey (sName);
163   }
164 
165   @Nullable
166   public String get (@Nullable final String sName)
167   {
168     if (StringHelper.hasNoText (sName))
169       return null;
170     return m_aMap.get (sName);
171   }
172 
173   @Nonnull
174   @ReturnsMutableCopy
175   public PSXPathVariables getClone ()
176   {
177     return new PSXPathVariables (this);
178   }
179 
180   @Override
181   public String toString ()
182   {
183     return new ToStringGenerator (this).append ("map", m_aMap).getToString ();
184   }
185 }