1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.string.StringHelper;
34 import com.helger.commons.string.ToStringGenerator;
35 import com.helger.schematron.CSchematron;
36 import com.helger.schematron.CSchematronXML;
37 import com.helger.schematron.pure.errorhandler.IPSErrorHandler;
38 import com.helger.xml.microdom.IMicroElement;
39 import com.helger.xml.microdom.MicroElement;
40
41
42
43
44
45
46
47
48
49 @NotThreadSafe
50 public class PSActive implements IPSClonableElement <PSActive>, IPSHasForeignElements, IPSHasMixedContent
51 {
52 private String m_sPattern;
53 private final ICommonsList <Object> m_aContent = new CommonsArrayList <> ();
54 private ICommonsOrderedMap <String, String> m_aForeignAttrs;
55 private ICommonsList <IMicroElement> m_aForeignElements;
56
57 public PSActive ()
58 {}
59
60 public boolean isValid (@Nonnull final IPSErrorHandler aErrorHandler)
61 {
62 for (final Object aContent : m_aContent)
63 if (aContent instanceof IPSElement)
64 if (!((IPSElement) aContent).isValid (aErrorHandler))
65 return false;
66 if (StringHelper.hasNoText (m_sPattern))
67 {
68 aErrorHandler.error (this, "<active> has no 'pattern'");
69 return false;
70 }
71 return true;
72 }
73
74 public void validateCompletely (@Nonnull final IPSErrorHandler aErrorHandler)
75 {
76 for (final Object aContent : m_aContent)
77 if (aContent instanceof IPSElement)
78 ((IPSElement) aContent).validateCompletely (aErrorHandler);
79 if (StringHelper.hasNoText (m_sPattern))
80 aErrorHandler.error (this, "<active> has no 'pattern'");
81 }
82
83 public boolean isMinimal ()
84 {
85 for (final Object aContent : m_aContent)
86 if (aContent instanceof IPSElement)
87 if (!((IPSElement) aContent).isMinimal ())
88 return false;
89 return true;
90 }
91
92 public void addForeignElement (@Nonnull final IMicroElement aForeignElement)
93 {
94 ValueEnforcer.notNull (aForeignElement, "ForeignElement");
95 if (aForeignElement.hasParent ())
96 throw new IllegalArgumentException ("ForeignElement already has a parent!");
97 if (m_aForeignElements == null)
98 m_aForeignElements = new CommonsArrayList <> ();
99 m_aForeignElements.add (aForeignElement);
100 }
101
102 public boolean hasForeignElements ()
103 {
104 return m_aForeignElements != null && m_aForeignElements.isNotEmpty ();
105 }
106
107 @Nonnull
108 @ReturnsMutableCopy
109 public ICommonsList <IMicroElement> getAllForeignElements ()
110 {
111 return new CommonsArrayList <> (m_aForeignElements);
112 }
113
114 public void addForeignAttribute (@Nonnull final String sAttrName, @Nonnull final String sAttrValue)
115 {
116 ValueEnforcer.notNull (sAttrName, "AttrName");
117 ValueEnforcer.notNull (sAttrValue, "AttrValue");
118 if (m_aForeignAttrs == null)
119 m_aForeignAttrs = new CommonsLinkedHashMap <> ();
120 m_aForeignAttrs.put (sAttrName, sAttrValue);
121 }
122
123 public boolean hasForeignAttributes ()
124 {
125 return m_aForeignAttrs != null && m_aForeignAttrs.isNotEmpty ();
126 }
127
128 @Nonnull
129 @ReturnsMutableCopy
130 public ICommonsOrderedMap <String, String> getAllForeignAttributes ()
131 {
132 return new CommonsLinkedHashMap <> (m_aForeignAttrs);
133 }
134
135
136
137
138
139 public void setPattern (@Nullable final String sPattern)
140 {
141 m_sPattern = sPattern;
142 }
143
144
145
146
147
148 @Nullable
149 public String getPattern ()
150 {
151 return m_sPattern;
152 }
153
154 public void addText (@Nonnull @Nonempty final String sText)
155 {
156 ValueEnforcer.notEmpty (sText, "Text");
157 m_aContent.add (sText);
158 }
159
160 public boolean hasAnyText ()
161 {
162 return m_aContent.containsAny (e -> e instanceof String);
163 }
164
165 @Nonnull
166 @ReturnsMutableCopy
167 public ICommonsList <String> getAllTexts ()
168 {
169 return m_aContent.getAllInstanceOf (String.class);
170 }
171
172 public void addDir (@Nonnull final PSDir aDir)
173 {
174 ValueEnforcer.notNull (aDir, "Dir");
175 m_aContent.add (aDir);
176 }
177
178 @Nonnull
179 @ReturnsMutableCopy
180 public ICommonsList <PSDir> getAllDirs ()
181 {
182 return m_aContent.getAllInstanceOf (PSDir.class);
183 }
184
185 public void addEmph (@Nonnull final PSEmph aEmph)
186 {
187 ValueEnforcer.notNull (aEmph, "Emph");
188 m_aContent.add (aEmph);
189 }
190
191 @Nonnull
192 @ReturnsMutableCopy
193 public ICommonsList <PSEmph> getAllEmphs ()
194 {
195 return m_aContent.getAllInstanceOf (PSEmph.class);
196 }
197
198 public void addSpan (@Nonnull final PSSpan aSpan)
199 {
200 ValueEnforcer.notNull (aSpan, "Span");
201 m_aContent.add (aSpan);
202 }
203
204 @Nonnull
205 @ReturnsMutableCopy
206 public ICommonsList <PSSpan> getAllSpans ()
207 {
208 return m_aContent.getAllInstanceOf (PSSpan.class);
209 }
210
211
212
213
214
215 @Nonnull
216 @ReturnsMutableCopy
217 public ICommonsList <Object> getAllContentElements ()
218 {
219 return m_aContent.getClone ();
220 }
221
222 @Nonnull
223 public IMicroElement getAsMicroElement ()
224 {
225 final IMicroElement ret = new MicroElement (CSchematron.NAMESPACE_SCHEMATRON, CSchematronXML.ELEMENT_ACTIVE);
226 ret.setAttribute (CSchematronXML.ATTR_PATTERN, m_sPattern);
227 if (m_aForeignElements != null)
228 for (final IMicroElement aForeignElement : m_aForeignElements)
229 ret.appendChild (aForeignElement.getClone ());
230 for (final Object aContent : m_aContent)
231 if (aContent instanceof String)
232 ret.appendText ((String) aContent);
233 else
234 ret.appendChild (((IPSElement) aContent).getAsMicroElement ());
235 if (m_aForeignAttrs != null)
236 for (final Map.Entry <String, String> aEntry : m_aForeignAttrs.entrySet ())
237 ret.setAttribute (aEntry.getKey (), aEntry.getValue ());
238 return ret;
239 }
240
241 @Nonnull
242 public PSActive getClone ()
243 {
244 final PSActive ret = new PSActive ();
245 ret.setPattern (m_sPattern);
246 for (final Object aContent : m_aContent)
247 {
248 if (aContent instanceof String)
249 ret.addText ((String) aContent);
250 else
251 if (aContent instanceof PSDir)
252 ret.addDir (((PSDir) aContent).getClone ());
253 else
254 if (aContent instanceof PSEmph)
255 ret.addEmph (((PSEmph) aContent).getClone ());
256 else
257 if (aContent instanceof PSSpan)
258 ret.addSpan (((PSSpan) aContent).getClone ());
259 }
260 if (hasForeignElements ())
261 ret.addForeignElements (m_aForeignElements);
262 if (hasForeignAttributes ())
263 ret.addForeignAttributes (m_aForeignAttrs);
264 return ret;
265 }
266
267 @Override
268 public String toString ()
269 {
270 return new ToStringGenerator (this).appendIfNotNull ("pattern", m_sPattern)
271 .appendIf ("content", m_aContent, CollectionHelper::isNotEmpty)
272 .appendIf ("foreignAttrs", m_aForeignAttrs, CollectionHelper::isNotEmpty)
273 .appendIf ("foreignElements", m_aForeignElements, CollectionHelper::isNotEmpty)
274 .toString ();
275 }
276 }