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.model;
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.ReturnsMutableCopy;
27  import com.helger.commons.collection.CollectionHelper;
28  import com.helger.commons.collection.ext.CommonsLinkedHashMap;
29  import com.helger.commons.collection.ext.ICommonsOrderedMap;
30  import com.helger.commons.string.StringHelper;
31  import com.helger.commons.string.ToStringGenerator;
32  import com.helger.schematron.CSchematron;
33  import com.helger.schematron.CSchematronXML;
34  import com.helger.schematron.pure.errorhandler.IPSErrorHandler;
35  import com.helger.xml.microdom.IMicroElement;
36  import com.helger.xml.microdom.MicroElement;
37  
38  /**
39   * A single Schematron ns-element.<br>
40   * Specification of a namespace prefix and URI. The required prefix attribute is
41   * an XML name with no colon character. The required uri attribute is a
42   * namespace URI.<br>
43   * NOTE: Because the characters allowed as names may change in versions of XML
44   * subsequent to W3C XML 1.0, the ISO/IEC 19757-2 (RELAX NG Compact Syntax)
45   * schema for Schematron does not constrain the prefix to particular characters.
46   * <br>
47   * In an ISO Schematron schema, namespace prefixes in context expressions,
48   * assertion tests and other query expressions should use the namespace bindings
49   * provided by this element. Namespace prefixes should not use the namespace
50   * bindings in scope for element and attribute names.
51   *
52   * @author Philip Helger
53   */
54  @NotThreadSafe
55  public class PSNS implements IPSClonableElement <PSNS>, IPSHasForeignAttributes
56  {
57    private String m_sUri;
58    private String m_sPrefix;
59    private ICommonsOrderedMap <String, String> m_aForeignAttrs;
60  
61    public PSNS ()
62    {}
63  
64    public boolean isValid (@Nonnull final IPSErrorHandler aErrorHandler)
65    {
66      if (StringHelper.hasNoText (m_sUri))
67      {
68        aErrorHandler.error (this, "<ns> has no 'uri'");
69        return false;
70      }
71      if (StringHelper.hasNoText (m_sPrefix))
72      {
73        aErrorHandler.error (this, "<ns> has no 'prefix'");
74        return false;
75      }
76      return true;
77    }
78  
79    public void validateCompletely (@Nonnull final IPSErrorHandler aErrorHandler)
80    {
81      if (StringHelper.hasNoText (m_sUri))
82        aErrorHandler.error (this, "<ns> has no 'uri'");
83      if (StringHelper.hasNoText (m_sPrefix))
84        aErrorHandler.error (this, "<ns> has no 'prefix'");
85    }
86  
87    public boolean isMinimal ()
88    {
89      return true;
90    }
91  
92    public void addForeignAttribute (@Nonnull final String sAttrName, @Nonnull final String sAttrValue)
93    {
94      ValueEnforcer.notNull (sAttrName, "AttrName");
95      ValueEnforcer.notNull (sAttrValue, "AttrValue");
96      if (m_aForeignAttrs == null)
97        m_aForeignAttrs = new CommonsLinkedHashMap <> ();
98      m_aForeignAttrs.put (sAttrName, sAttrValue);
99    }
100 
101   public boolean hasForeignAttributes ()
102   {
103     return m_aForeignAttrs != null && m_aForeignAttrs.isNotEmpty ();
104   }
105 
106   @Nonnull
107   @ReturnsMutableCopy
108   public ICommonsOrderedMap <String, String> getAllForeignAttributes ()
109   {
110     return new CommonsLinkedHashMap <> (m_aForeignAttrs);
111   }
112 
113   /**
114    * @param sUri
115    *        The namespace URI.
116    */
117   public void setUri (@Nullable final String sUri)
118   {
119     m_sUri = sUri;
120   }
121 
122   /**
123    * @return The namespace URI. May be <code>null</code>.
124    */
125   @Nullable
126   public String getUri ()
127   {
128     return m_sUri;
129   }
130 
131   /**
132    * @param sPrefix
133    *        The namespace prefix to use.
134    */
135   public void setPrefix (@Nullable final String sPrefix)
136   {
137     m_sPrefix = sPrefix;
138   }
139 
140   /**
141    * @return The namespace prefix. May be <code>null</code>.
142    */
143   @Nullable
144   public String getPrefix ()
145   {
146     return m_sPrefix;
147   }
148 
149   @Nonnull
150   public IMicroElement getAsMicroElement ()
151   {
152     final IMicroElement ret = new MicroElement (CSchematron.NAMESPACE_SCHEMATRON, CSchematronXML.ELEMENT_NS);
153     ret.setAttribute (CSchematronXML.ATTR_PREFIX, m_sPrefix);
154     ret.setAttribute (CSchematronXML.ATTR_URI, m_sUri);
155     if (m_aForeignAttrs != null)
156       for (final Map.Entry <String, String> aEntry : m_aForeignAttrs.entrySet ())
157         ret.setAttribute (aEntry.getKey (), aEntry.getValue ());
158     return ret;
159   }
160 
161   @Nonnull
162   public PSNS getClone ()
163   {
164     final PSNS ret = new PSNS ();
165     ret.setUri (m_sUri);
166     ret.setPrefix (m_sPrefix);
167     if (hasForeignAttributes ())
168       ret.addForeignAttributes (m_aForeignAttrs);
169     return ret;
170   }
171 
172   @Override
173   public String toString ()
174   {
175     return new ToStringGenerator (this).appendIfNotNull ("uri", m_sUri)
176                                        .appendIfNotNull ("prefix", m_sPrefix)
177                                        .appendIf ("foreignAttrs", m_aForeignAttrs, CollectionHelper::isNotEmpty)
178                                        .getToString ();
179   }
180 }