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