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.Nonempty;
27  import com.helger.commons.annotation.ReturnsMutableCopy;
28  import com.helger.commons.collection.CollectionHelper;
29  import com.helger.commons.collection.ext.CommonsArrayList;
30  import com.helger.commons.collection.ext.CommonsLinkedHashMap;
31  import com.helger.commons.collection.ext.ICommonsList;
32  import com.helger.commons.collection.ext.ICommonsOrderedMap;
33  import com.helger.commons.id.IHasID;
34  import com.helger.commons.lang.EnumHelper;
35  import com.helger.commons.string.StringHelper;
36  import com.helger.commons.string.ToStringGenerator;
37  import com.helger.schematron.CSchematron;
38  import com.helger.schematron.CSchematronXML;
39  import com.helger.schematron.pure.errorhandler.IPSErrorHandler;
40  import com.helger.xml.microdom.IMicroElement;
41  import com.helger.xml.microdom.MicroElement;
42  
43  /**
44   * A single Schematron dir-element.<br>
45   * A section of natural-language text with a direction specified by the value
46   * attribute. The value ltr indicates left-to-right text; the value rtl
47   * indicates right-to-left text.<br>
48   * An implementation is not required to make use of this element.
49   *
50   * @author Philip Helger
51   */
52  @NotThreadSafe
53  public class PSDir implements IPSClonableElement <PSDir>, IPSOptionalElement, IPSHasForeignElements, IPSHasTexts
54  {
55    public static enum EDirValue implements IHasID <String>
56    {
57      LTR ("ltr"),
58      RTL ("rtl");
59  
60      private final String m_sID;
61  
62      private EDirValue (@Nonnull @Nonempty final String sID)
63      {
64        m_sID = sID;
65      }
66  
67      @Nonnull
68      @Nonempty
69      public String getID ()
70      {
71        return m_sID;
72      }
73  
74      @Nullable
75      public static EDirValue getFromIDOrNull (@Nullable final String sID)
76      {
77        return EnumHelper.getFromIDOrNull (EDirValue.class, sID);
78      }
79    }
80  
81    private EDirValue m_eValue;
82    private final ICommonsList <String> m_aContent = new CommonsArrayList <> ();
83    private ICommonsOrderedMap <String, String> m_aForeignAttrs;
84    private ICommonsList <IMicroElement> m_aForeignElements;
85  
86    public PSDir ()
87    {}
88  
89    public boolean isValid (@Nonnull final IPSErrorHandler aErrorHandler)
90    {
91      if (m_aContent.isEmpty ())
92      {
93        aErrorHandler.error (this, "<dir> has no content");
94        return false;
95      }
96      return true;
97    }
98  
99    public void validateCompletely (@Nonnull final IPSErrorHandler aErrorHandler)
100   {
101     if (m_aContent.isEmpty ())
102       aErrorHandler.error (this, "<dir> has no content");
103   }
104 
105   public boolean isMinimal ()
106   {
107     return true;
108   }
109 
110   public void addForeignElement (@Nonnull final IMicroElement aForeignElement)
111   {
112     ValueEnforcer.notNull (aForeignElement, "ForeignElement");
113     if (aForeignElement.hasParent ())
114       throw new IllegalArgumentException ("ForeignElement already has a parent!");
115     if (m_aForeignElements == null)
116       m_aForeignElements = new CommonsArrayList <> ();
117     m_aForeignElements.add (aForeignElement);
118   }
119 
120   public boolean hasForeignElements ()
121   {
122     return m_aForeignElements != null && m_aForeignElements.isNotEmpty ();
123   }
124 
125   @Nonnull
126   @ReturnsMutableCopy
127   public ICommonsList <IMicroElement> getAllForeignElements ()
128   {
129     return new CommonsArrayList <> (m_aForeignElements);
130   }
131 
132   public void addForeignAttribute (@Nonnull final String sAttrName, @Nonnull final String sAttrValue)
133   {
134     ValueEnforcer.notNull (sAttrName, "AttrName");
135     ValueEnforcer.notNull (sAttrValue, "AttrValue");
136     if (m_aForeignAttrs == null)
137       m_aForeignAttrs = new CommonsLinkedHashMap <> ();
138     m_aForeignAttrs.put (sAttrName, sAttrValue);
139   }
140 
141   public boolean hasForeignAttributes ()
142   {
143     return m_aForeignAttrs != null && m_aForeignAttrs.isNotEmpty ();
144   }
145 
146   @Nonnull
147   @ReturnsMutableCopy
148   public ICommonsOrderedMap <String, String> getAllForeignAttributes ()
149   {
150     return new CommonsLinkedHashMap <> (m_aForeignAttrs);
151   }
152 
153   public void setValue (@Nullable final EDirValue eValue)
154   {
155     m_eValue = eValue;
156   }
157 
158   @Nullable
159   public EDirValue getValue ()
160   {
161     return m_eValue;
162   }
163 
164   public void addText (@Nonnull @Nonempty final String sText)
165   {
166     ValueEnforcer.notEmpty (sText, "Text");
167     m_aContent.add (sText);
168   }
169 
170   public boolean hasAnyText ()
171   {
172     return m_aContent.isNotEmpty ();
173   }
174 
175   @Nonnull
176   @ReturnsMutableCopy
177   public ICommonsList <String> getAllTexts ()
178   {
179     return m_aContent.getClone ();
180   }
181 
182   @Nullable
183   public String getAsText ()
184   {
185     return StringHelper.getImploded (m_aContent);
186   }
187 
188   @Nonnull
189   public IMicroElement getAsMicroElement ()
190   {
191     final IMicroElement ret = new MicroElement (CSchematron.NAMESPACE_SCHEMATRON, CSchematronXML.ELEMENT_DIR);
192     if (m_eValue != null)
193       ret.setAttribute (CSchematronXML.ATTR_VALUE, m_eValue.getID ());
194     if (m_aForeignElements != null)
195       for (final IMicroElement aForeignElement : m_aForeignElements)
196         ret.appendChild (aForeignElement.getClone ());
197     for (final String sContent : m_aContent)
198       ret.appendText (sContent);
199     if (m_aForeignAttrs != null)
200       for (final Map.Entry <String, String> aEntry : m_aForeignAttrs.entrySet ())
201         ret.setAttribute (aEntry.getKey (), aEntry.getValue ());
202     return ret;
203   }
204 
205   @Nonnull
206   public PSDir getClone ()
207   {
208     final PSDir ret = new PSDir ();
209     ret.setValue (m_eValue);
210     for (final String sContent : m_aContent)
211       ret.addText (sContent);
212     if (hasForeignElements ())
213       ret.addForeignElements (m_aForeignElements);
214     if (hasForeignAttributes ())
215       ret.addForeignAttributes (m_aForeignAttrs);
216     return ret;
217   }
218 
219   @Override
220   public String toString ()
221   {
222     return new ToStringGenerator (this).appendIfNotNull ("value", m_eValue)
223                                        .appendIf ("content", m_aContent, CollectionHelper::isNotEmpty)
224                                        .appendIf ("foreignAttrs", m_aForeignAttrs, CollectionHelper::isNotEmpty)
225                                        .appendIf ("foreignElements", m_aForeignElements, CollectionHelper::isNotEmpty)
226                                        .getToString ();
227   }
228 }