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
50
51
52
53
54 @NotThreadSafe
55 public class PSDiagnostic implements
56 IPSClonableElement <PSDiagnostic>,
57 IPSOptionalElement,
58 IPSHasID,
59 IPSHasForeignElements,
60 IPSHasMixedContent,
61 IPSHasRichGroup
62 {
63 private String m_sID;
64 private PSRichGroup m_aRich;
65 private final ICommonsList <Object> m_aContent = new CommonsArrayList <> ();
66 private ICommonsOrderedMap <String, String> m_aForeignAttrs;
67 private ICommonsList <IMicroElement> m_aForeignElements;
68
69 public PSDiagnostic ()
70 {}
71
72 public boolean isValid (@Nonnull final IPSErrorHandler aErrorHandler)
73 {
74 for (final Object aContent : m_aContent)
75 if (aContent instanceof IPSElement)
76 if (!((IPSElement) aContent).isValid (aErrorHandler))
77 return false;
78 if (StringHelper.hasNoText (m_sID))
79 {
80 aErrorHandler.error (this, "<diagnostic> has no 'id'");
81 return false;
82 }
83 return true;
84 }
85
86 public void validateCompletely (@Nonnull final IPSErrorHandler aErrorHandler)
87 {
88 for (final Object aContent : m_aContent)
89 if (aContent instanceof IPSElement)
90 ((IPSElement) aContent).validateCompletely (aErrorHandler);
91 if (StringHelper.hasNoText (m_sID))
92 aErrorHandler.error (this, "<diagnostic> has no 'id'");
93 }
94
95 public boolean isMinimal ()
96 {
97 return false;
98 }
99
100 public void addForeignElement (@Nonnull final IMicroElement aForeignElement)
101 {
102 ValueEnforcer.notNull (aForeignElement, "ForeignElement");
103 if (aForeignElement.hasParent ())
104 throw new IllegalArgumentException ("ForeignElement already has a parent!");
105 if (m_aForeignElements == null)
106 m_aForeignElements = new CommonsArrayList <> ();
107 m_aForeignElements.add (aForeignElement);
108 }
109
110 public boolean hasForeignElements ()
111 {
112 return m_aForeignElements != null && m_aForeignElements.isNotEmpty ();
113 }
114
115 @Nonnull
116 @ReturnsMutableCopy
117 public ICommonsList <IMicroElement> getAllForeignElements ()
118 {
119 return new CommonsArrayList <> (m_aForeignElements);
120 }
121
122 public void addForeignAttribute (@Nonnull final String sAttrName, @Nonnull final String sAttrValue)
123 {
124 ValueEnforcer.notNull (sAttrName, "AttrName");
125 ValueEnforcer.notNull (sAttrValue, "AttrValue");
126 if (m_aForeignAttrs == null)
127 m_aForeignAttrs = new CommonsLinkedHashMap <> ();
128 m_aForeignAttrs.put (sAttrName, sAttrValue);
129 }
130
131 public boolean hasForeignAttributes ()
132 {
133 return m_aForeignAttrs != null && m_aForeignAttrs.isNotEmpty ();
134 }
135
136 @Nonnull
137 @ReturnsMutableCopy
138 public ICommonsOrderedMap <String, String> getAllForeignAttributes ()
139 {
140 return new CommonsLinkedHashMap <> (m_aForeignAttrs);
141 }
142
143 public void setID (@Nullable final String sID)
144 {
145 m_sID = sID;
146 }
147
148 @Nullable
149 public String getID ()
150 {
151 return m_sID;
152 }
153
154 public void setRich (@Nullable final PSRichGroup aRich)
155 {
156 m_aRich = aRich;
157 }
158
159 @Nullable
160 public PSRichGroup getRich ()
161 {
162 return m_aRich;
163 }
164
165 public void addText (@Nonnull @Nonempty final String sText)
166 {
167 ValueEnforcer.notEmpty (sText, "Text");
168 m_aContent.add (sText);
169 }
170
171 public boolean hasAnyText ()
172 {
173 return m_aContent.containsAny (e -> e instanceof String);
174 }
175
176 @Nonnull
177 @ReturnsMutableCopy
178 public ICommonsList <String> getAllTexts ()
179 {
180 return m_aContent.getAllInstanceOf (String.class);
181 }
182
183 public void addValueOf (@Nonnull final PSValueOf aValueOf)
184 {
185 ValueEnforcer.notNull (aValueOf, "ValueOf");
186 m_aContent.add (aValueOf);
187 }
188
189 @Nonnull
190 @ReturnsMutableCopy
191 public ICommonsList <PSValueOf> getAllValueOfs ()
192 {
193 return m_aContent.getAllInstanceOf (PSValueOf.class);
194 }
195
196 public void addEmph (@Nonnull final PSEmph aEmph)
197 {
198 ValueEnforcer.notNull (aEmph, "Emph");
199 m_aContent.add (aEmph);
200 }
201
202 @Nonnull
203 @ReturnsMutableCopy
204 public ICommonsList <PSEmph> getAllEmphs ()
205 {
206 return m_aContent.getAllInstanceOf (PSEmph.class);
207 }
208
209 public void addDir (@Nonnull final PSDir aDir)
210 {
211 ValueEnforcer.notNull (aDir, "Dir");
212 m_aContent.add (aDir);
213 }
214
215 @Nonnull
216 @ReturnsMutableCopy
217 public ICommonsList <PSDir> getAllDirs ()
218 {
219 return m_aContent.getAllInstanceOf (PSDir.class);
220 }
221
222 public void addSpan (@Nonnull final PSSpan aSpan)
223 {
224 ValueEnforcer.notNull (aSpan, "Span");
225 m_aContent.add (aSpan);
226 }
227
228 @Nonnull
229 @ReturnsMutableCopy
230 public ICommonsList <PSSpan> getAllSpans ()
231 {
232 return m_aContent.getAllInstanceOf (PSSpan.class);
233 }
234
235
236
237
238
239 @Nonnull
240 @ReturnsMutableCopy
241 public ICommonsList <Object> getAllContentElements ()
242 {
243 return m_aContent.getClone ();
244 }
245
246 @Nonnull
247 public IMicroElement getAsMicroElement ()
248 {
249 final IMicroElement ret = new MicroElement (CSchematron.NAMESPACE_SCHEMATRON, CSchematronXML.ELEMENT_DIAGNOSTIC);
250 ret.setAttribute (CSchematronXML.ATTR_ID, m_sID);
251 if (m_aRich != null)
252 m_aRich.fillMicroElement (ret);
253 if (m_aForeignElements != null)
254 for (final IMicroElement aForeignElement : m_aForeignElements)
255 ret.appendChild (aForeignElement.getClone ());
256 for (final Object aContent : m_aContent)
257 if (aContent instanceof String)
258 ret.appendText ((String) aContent);
259 else
260 ret.appendChild (((IPSElement) aContent).getAsMicroElement ());
261 if (m_aForeignAttrs != null)
262 for (final Map.Entry <String, String> aEntry : m_aForeignAttrs.entrySet ())
263 ret.setAttribute (aEntry.getKey (), aEntry.getValue ());
264 return ret;
265 }
266
267 @Nonnull
268 public PSDiagnostic getClone ()
269 {
270 final PSDiagnostic ret = new PSDiagnostic ();
271 ret.setID (m_sID);
272 ret.setRich (getRichClone ());
273 for (final Object aContent : m_aContent)
274 {
275 if (aContent instanceof String)
276 ret.addText ((String) aContent);
277 else
278 if (aContent instanceof PSValueOf)
279 ret.addValueOf (((PSValueOf) aContent).getClone ());
280 else
281 if (aContent instanceof PSEmph)
282 ret.addEmph (((PSEmph) aContent).getClone ());
283 else
284 if (aContent instanceof PSDir)
285 ret.addDir (((PSDir) aContent).getClone ());
286 else
287 if (aContent instanceof PSSpan)
288 ret.addSpan (((PSSpan) aContent).getClone ());
289 else
290 throw new IllegalStateException ("Unexpected content element: " + aContent);
291 }
292 if (hasForeignElements ())
293 ret.addForeignElements (m_aForeignElements);
294 if (hasForeignAttributes ())
295 ret.addForeignAttributes (m_aForeignAttrs);
296 return ret;
297 }
298
299 @Override
300 public String toString ()
301 {
302 return new ToStringGenerator (this).appendIfNotNull ("id", m_sID)
303 .appendIfNotNull ("rich", m_aRich)
304 .appendIf ("content", m_aContent, CollectionHelper::isNotEmpty)
305 .appendIf ("foreignAttrs", m_aForeignAttrs, CollectionHelper::isNotEmpty)
306 .appendIf ("foreignElements", m_aForeignElements, CollectionHelper::isNotEmpty)
307 .toString ();
308 }
309 }