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.model;
18  
19  import java.util.LinkedHashMap;
20  import java.util.Map;
21  
22  import javax.annotation.Nonnull;
23  import javax.annotation.Nullable;
24  import javax.annotation.concurrent.NotThreadSafe;
25  
26  import com.helger.commons.ValueEnforcer;
27  import com.helger.commons.annotation.ReturnsMutableCopy;
28  import com.helger.commons.collection.CollectionHelper;
29  import com.helger.commons.microdom.IMicroElement;
30  import com.helger.commons.microdom.MicroElement;
31  import com.helger.commons.string.StringHelper;
32  import com.helger.commons.string.ToStringGenerator;
33  import com.helger.schematron.CSchematron;
34  import com.helger.schematron.CSchematronXML;
35  import com.helger.schematron.pure.errorhandler.IPSErrorHandler;
36  
37  /**
38   * A single Schematron value-of-element.<br>
39   * Finds or calculates values from the instance document to allow clearer
40   * assertions and diagnostics. The required select attribute is an expression
41   * evaluated in the current context that returns a string.<br>
42   * Variable references in the select attribute are resolved in the scope of the
43   * current schema, phase, pattern and rule.<br>
44   * An implementation which does not report natural-language assertions is not
45   * required to make use of this element.
46   *
47   * @author Philip Helger
48   */
49  @NotThreadSafe
50  public class PSValueOf implements IPSClonableElement <PSValueOf>, IPSHasForeignAttributes
51  {
52    private String m_sSelect;
53    private Map <String, String> m_aForeignAttrs;
54  
55    public PSValueOf ()
56    {}
57  
58    public boolean isValid (@Nonnull final IPSErrorHandler aErrorHandler)
59    {
60      if (StringHelper.hasNoText (m_sSelect))
61      {
62        aErrorHandler.error (this, "<value-of> has no 'select'");
63        return false;
64      }
65      return true;
66    }
67  
68    public void validateCompletely (@Nonnull final IPSErrorHandler aErrorHandler)
69    {
70      if (StringHelper.hasNoText (m_sSelect))
71        aErrorHandler.error (this, "<value-of> has no 'select'");
72    }
73  
74    public boolean isMinimal ()
75    {
76      return true;
77    }
78  
79    public void addForeignAttribute (@Nonnull final String sAttrName, @Nonnull final String sAttrValue)
80    {
81      ValueEnforcer.notNull (sAttrName, "AttrName");
82      ValueEnforcer.notNull (sAttrValue, "AttrValue");
83      if (m_aForeignAttrs == null)
84        m_aForeignAttrs = new LinkedHashMap <String, String> ();
85      m_aForeignAttrs.put (sAttrName, sAttrValue);
86    }
87  
88    public void addForeignAttributes (@Nonnull final Map <String, String> aForeignAttrs)
89    {
90      ValueEnforcer.notNull (aForeignAttrs, "ForeignAttrs");
91      for (final Map.Entry <String, String> aEntry : aForeignAttrs.entrySet ())
92        addForeignAttribute (aEntry.getKey (), aEntry.getValue ());
93    }
94  
95    public boolean hasForeignAttributes ()
96    {
97      return m_aForeignAttrs != null && !m_aForeignAttrs.isEmpty ();
98    }
99  
100   @Nonnull
101   @ReturnsMutableCopy
102   public Map <String, String> getAllForeignAttributes ()
103   {
104     return CollectionHelper.newOrderedMap (m_aForeignAttrs);
105   }
106 
107   /**
108    * Set the expression to retrieve the value of
109    *
110    * @param sSelect
111    *        The select expression string. May be <code>null</code>.
112    */
113   public void setSelect (@Nullable final String sSelect)
114   {
115     m_sSelect = sSelect;
116   }
117 
118   /**
119    * @return The select expression string. May be <code>null</code>.
120    */
121   @Nullable
122   public String getSelect ()
123   {
124     return m_sSelect;
125   }
126 
127   @Nonnull
128   public IMicroElement getAsMicroElement ()
129   {
130     final IMicroElement ret = new MicroElement (CSchematron.NAMESPACE_SCHEMATRON, CSchematronXML.ELEMENT_VALUE_OF);
131     ret.setAttribute (CSchematronXML.ATTR_SELECT, m_sSelect);
132     if (m_aForeignAttrs != null)
133       for (final Map.Entry <String, String> aEntry : m_aForeignAttrs.entrySet ())
134         ret.setAttribute (aEntry.getKey (), aEntry.getValue ());
135     return ret;
136   }
137 
138   @Nonnull
139   public PSValueOf getClone ()
140   {
141     final PSValueOf ret = new PSValueOf ();
142     ret.setSelect (m_sSelect);
143     if (hasForeignAttributes ())
144       ret.addForeignAttributes (m_aForeignAttrs);
145     return ret;
146   }
147 
148   @Override
149   public String toString ()
150   {
151     return new ToStringGenerator (this).appendIfNotNull ("select", m_sSelect)
152                                        .appendIfNotEmpty ("foreignAttrs", m_aForeignAttrs)
153                                        .toString ();
154   }
155 }