View Javadoc
1   /**
2    * Copyright (C) 2014-2015 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;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  import java.util.concurrent.locks.ReadWriteLock;
22  import java.util.concurrent.locks.ReentrantReadWriteLock;
23  
24  import javax.annotation.Nonnull;
25  import javax.annotation.Nullable;
26  import javax.annotation.concurrent.ThreadSafe;
27  
28  import com.helger.commons.ValueEnforcer;
29  import com.helger.commons.annotation.Nonempty;
30  import com.helger.commons.annotation.PresentForCodeCoverage;
31  import com.helger.commons.annotation.ReturnsMutableCopy;
32  import com.helger.commons.collection.CollectionHelper;
33  import com.helger.commons.exception.InitializationException;
34  import com.helger.schematron.pure.binding.xpath.PSXPathQueryBinding;
35  
36  /**
37   * The registry class for all available query bindings. To register your own
38   * query binding, call {@link #registerQueryBinding(String, IPSQueryBinding)}.
39   *
40   * @author Philip Helger
41   */
42  @ThreadSafe
43  public final class PSQueryBindingRegistry
44  {
45    /**
46     * Name of the query binding for which the default binding is registered.
47     */
48    public static final String QUERY_BINDING_XSLT = "xslt";
49  
50    /**
51     * Name of the query binding for which the default binding is registered.
52     */
53    public static final String QUERY_BINDING_XSLT2 = "xslt2";
54  
55    /**
56     * The default XPath binding object to be used
57     */
58    public static final IPSQueryBinding DEFAULT_QUERY_BINDING = PSXPathQueryBinding.getInstance ();
59  
60    private static final ReadWriteLock s_aRWLock = new ReentrantReadWriteLock ();
61    private static final Map <String, IPSQueryBinding> s_aMap = new HashMap <String, IPSQueryBinding> ();
62  
63    static
64    {
65      try
66      {
67        registerQueryBinding (QUERY_BINDING_XSLT, DEFAULT_QUERY_BINDING);
68        registerQueryBinding (QUERY_BINDING_XSLT2, DEFAULT_QUERY_BINDING);
69      }
70      catch (final SchematronBindException ex)
71      {
72        throw new InitializationException (ex);
73      }
74    }
75  
76    @PresentForCodeCoverage
77    private static final PSQueryBindingRegistry s_aInstance = new PSQueryBindingRegistry ();
78  
79    private PSQueryBindingRegistry ()
80    {}
81  
82    public static void registerQueryBinding (@Nonnull @Nonempty final String sName,
83                                             @Nonnull final IPSQueryBinding aQueryBinding) throws SchematronBindException
84    {
85      ValueEnforcer.notEmpty (sName, "Name");
86      ValueEnforcer.notNull (aQueryBinding, "QueryBinding");
87  
88      s_aRWLock.writeLock ().lock ();
89      try
90      {
91        if (s_aMap.containsKey (sName))
92          throw new SchematronBindException ("A queryBinding with the name '" + sName + "' is already registered!");
93        s_aMap.put (sName, aQueryBinding);
94      }
95      finally
96      {
97        s_aRWLock.writeLock ().unlock ();
98      }
99    }
100 
101   /**
102    * Get the query binding with the specified name.
103    *
104    * @param sName
105    *        The name to the query binding to retrieve. May be <code>null</code>.
106    *        If it is <code>null</code> than the {@link #DEFAULT_QUERY_BINDING}
107    *        object is returned.
108    * @return <code>null</code> if no such query binding was found.
109    */
110   @Nullable
111   public static IPSQueryBinding getQueryBindingOfName (@Nullable final String sName)
112   {
113     if (sName == null)
114       return DEFAULT_QUERY_BINDING;
115 
116     s_aRWLock.readLock ().lock ();
117     try
118     {
119       return s_aMap.get (sName);
120     }
121     finally
122     {
123       s_aRWLock.readLock ().unlock ();
124     }
125   }
126 
127   /**
128    * Get the query binding with the specified name
129    *
130    * @param sName
131    *        The name of the query binding to look up. May be <code>null</code>.
132    * @return Never <code>null</code>.
133    * @throws SchematronBindException
134    *         In case the query binding could not be resolved!
135    */
136   @Nonnull
137   public static IPSQueryBinding getQueryBindingOfNameOrThrow (@Nullable final String sName) throws SchematronBindException
138   {
139     final IPSQueryBinding aQB = getQueryBindingOfName (sName);
140     if (aQB == null)
141       throw new SchematronBindException ("No query binding implementation present for query binding '" + sName + "'");
142     return aQB;
143   }
144 
145   /**
146    * @return A non-<code>null</code> map with all contained query bindings from
147    *         name to object.
148    */
149   @Nonnull
150   @ReturnsMutableCopy
151   public static Map <String, IPSQueryBinding> getAllRegisteredQueryBindings ()
152   {
153     s_aRWLock.readLock ().lock ();
154     try
155     {
156       return CollectionHelper.newMap (s_aMap);
157     }
158     finally
159     {
160       s_aRWLock.readLock ().unlock ();
161     }
162   }
163 }