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