1 | /* | |
2 | * $Id: XfaForm.java 4105 2009-11-27 12:52:57Z blowagie $ | |
3 | * | |
4 | * Copyright 2006 Paulo Soares | |
5 | * | |
6 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
7 | * (the "License"); you may not use this file except in compliance with the License. | |
8 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
9 | * | |
10 | * Software distributed under the License is distributed on an "AS IS" basis, | |
11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
12 | * for the specific language governing rights and limitations under the License. | |
13 | * | |
14 | * The Original Code is 'iText, a free JAVA-PDF library'. | |
15 | * | |
16 | * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by | |
17 | * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. | |
18 | * All Rights Reserved. | |
19 | * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer | |
20 | * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. | |
21 | * | |
22 | * Contributor(s): all the names of the contributors are added in the source code | |
23 | * where applicable. | |
24 | * | |
25 | * Alternatively, the contents of this file may be used under the terms of the | |
26 | * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the | |
27 | * provisions of LGPL are applicable instead of those above. If you wish to | |
28 | * allow use of your version of this file only under the terms of the LGPL | |
29 | * License and not to allow others to use your version of this file under | |
30 | * the MPL, indicate your decision by deleting the provisions above and | |
31 | * replace them with the notice and other provisions required by the LGPL. | |
32 | * If you do not delete the provisions above, a recipient may use your version | |
33 | * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. | |
34 | * | |
35 | * This library is free software; you can redistribute it and/or modify it | |
36 | * under the terms of the MPL as stated above or under the terms of the GNU | |
37 | * Library General Public License as published by the Free Software Foundation; | |
38 | * either version 2 of the License, or any later version. | |
39 | * | |
40 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
41 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
42 | * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more | |
43 | * details. | |
44 | * | |
45 | * If you didn't download this code from the following link, you should check if | |
46 | * you aren't using an obsolete version: | |
47 | * http://www.lowagie.com/iText/ | |
48 | */ | |
49 | ||
50 | package com.lowagie.text.pdf; | |
51 | ||
52 | import java.io.ByteArrayInputStream; | |
53 | import java.io.ByteArrayOutputStream; | |
54 | import java.io.File; | |
55 | import java.io.FileInputStream; | |
56 | import java.io.IOException; | |
57 | import java.io.InputStream; | |
58 | import java.io.StringReader; | |
59 | import java.util.*; | |
60 | ||
61 | import javax.annotation.Nullable; | |
62 | import javax.xml.parsers.DocumentBuilder; | |
63 | import javax.xml.parsers.DocumentBuilderFactory; | |
64 | import javax.xml.parsers.ParserConfigurationException; | |
65 | ||
66 | import org.w3c.dom.Document; | |
67 | import org.w3c.dom.Node; | |
68 | import org.w3c.dom.NodeList; | |
69 | import org.xml.sax.InputSource; | |
70 | import org.xml.sax.SAXException; | |
71 | ||
72 | import com.lowagie.text.xml.XmlDomWriter; | |
73 | ||
74 | /** | |
75 | * Processes XFA forms. | |
76 | * @author Paulo Soares (psoares@consiste.pt) | |
77 | */ | |
78 | public class XfaForm { | |
79 | ||
80 | private Xml2SomTemplate templateSom; | |
81 | private Node templateNode; | |
82 | private Xml2SomDatasets datasetsSom; | |
83 | private Node datasetsNode; | |
84 | private AcroFieldsSearch acroFieldsSom; | |
85 | private PdfReader reader; | |
86 | private boolean xfaPresent; | |
87 | private org.w3c.dom.Document domDocument; | |
88 | private boolean changed; | |
89 | public static final String XFA_DATA_SCHEMA = "http://www.xfa.org/schema/xfa-data/1.0/"; | |
90 | | |
91 | /** | |
92 | * An empty constructor to build on. | |
93 | */ | |
94 | public XfaForm() { | |
95 | } | |
96 | | |
97 | /** | |
98 | * Return the XFA Object, could be an array, could be a Stream. | |
99 | * Returns null f no XFA Object is present. | |
100 | * @param reader a PdfReader instance | |
101 | * @return the XFA object | |
102 | * @since 2.1.3 | |
103 | */ | |
104 | public static PdfObject getXfaObject(PdfReader reader) { | |
105 | PdfDictionary af = (PdfDictionary)PdfReader.getPdfObjectRelease(reader.getCatalog().get(PdfName.ACROFORM)); | |
106 |
1
1. getXfaObject : negated conditional → NO_COVERAGE |
if (af == null) { |
107 |
1
1. getXfaObject : mutated return of Object value for com/lowagie/text/pdf/XfaForm::getXfaObject to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
108 | } | |
109 |
1
1. getXfaObject : mutated return of Object value for com/lowagie/text/pdf/XfaForm::getXfaObject to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return PdfReader.getPdfObjectRelease(af.get(PdfName.XFA)); |
110 | } | |
111 | | |
112 | /** | |
113 | * A constructor from a <CODE>PdfReader</CODE>. It basically does everything | |
114 | * from finding the XFA stream to the XML parsing. | |
115 | * @param reader the reader | |
116 | * @throws java.io.IOException on error | |
117 | * @throws javax.xml.parsers.ParserConfigurationException on error | |
118 | * @throws org.xml.sax.SAXException on error | |
119 | */ | |
120 | public XfaForm(PdfReader reader) throws IOException, ParserConfigurationException, SAXException { | |
121 | this.reader = reader; | |
122 | PdfObject xfa = getXfaObject(reader); | |
123 |
1
1. |
if (xfa == null) { |
124 | xfaPresent = false; | |
125 | return; | |
126 | } | |
127 | xfaPresent = true; | |
128 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); | |
129 |
1
1. |
if (xfa.isArray()) { |
130 | PdfArray ar = (PdfArray)xfa; | |
131 |
2
1. 2. |
for (int k = 1; k < ar.size(); k += 2) { |
132 | PdfObject ob = ar.getDirectObject(k); | |
133 |
1
1. |
if (ob instanceof PRStream) { |
134 | byte[] b = PdfReader.getStreamBytes((PRStream)ob); | |
135 |
1
1. |
bout.write(b); |
136 | } | |
137 | } | |
138 | } | |
139 |
1
1. |
else if (xfa instanceof PRStream) { |
140 | byte[] b = PdfReader.getStreamBytes((PRStream)xfa); | |
141 |
1
1. |
bout.write(b); |
142 | } | |
143 |
1
1. |
bout.close(); |
144 | DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance(); | |
145 |
1
1. |
fact.setNamespaceAware(true); |
146 | DocumentBuilder db = fact.newDocumentBuilder(); | |
147 |
1
1. |
db.setEntityResolver((publicId, systemId) -> new InputSource(new StringReader(""))); |
148 | domDocument = db.parse(new ByteArrayInputStream(bout.toByteArray())); | |
149 |
1
1. |
extractNodes(); |
150 | } | |
151 | | |
152 | /** | |
153 | * Extracts the nodes from the domDocument. | |
154 | * @since 2.1.5 | |
155 | */ | |
156 | private void extractNodes() { | |
157 | Node n = domDocument.getFirstChild(); | |
158 |
1
1. extractNodes : negated conditional → NO_COVERAGE |
while (n.getChildNodes().getLength() == 0) { |
159 | n = n.getNextSibling(); | |
160 | } | |
161 | n = n.getFirstChild(); | |
162 |
1
1. extractNodes : negated conditional → NO_COVERAGE |
while (n != null) { |
163 |
1
1. extractNodes : negated conditional → NO_COVERAGE |
if (n.getNodeType() == Node.ELEMENT_NODE) { |
164 | String s = n.getLocalName(); | |
165 |
1
1. extractNodes : negated conditional → NO_COVERAGE |
if (s.equals("template")) { |
166 | templateNode = n; | |
167 | templateSom = new Xml2SomTemplate(n); | |
168 | } | |
169 |
1
1. extractNodes : negated conditional → NO_COVERAGE |
else if (s.equals("datasets")) { |
170 | datasetsNode = n; | |
171 | datasetsSom = new Xml2SomDatasets(n.getFirstChild()); | |
172 | } | |
173 | } | |
174 | n = n.getNextSibling(); | |
175 | } | |
176 | } | |
177 | | |
178 | /** | |
179 | * Sets the XFA key from a byte array. The old XFA is erased. | |
180 | * @param form the data | |
181 | * @param reader the reader | |
182 | * @param writer the writer | |
183 | * @throws java.io.IOException on error | |
184 | */ | |
185 | public static void setXfa(XfaForm form, PdfReader reader, PdfWriter writer) throws IOException { | |
186 | PdfDictionary af = (PdfDictionary)PdfReader.getPdfObjectRelease(reader.getCatalog().get(PdfName.ACROFORM)); | |
187 |
1
1. setXfa : negated conditional → NO_COVERAGE |
if (af == null) { |
188 | return; | |
189 | } | |
190 | PdfObject xfa = getXfaObject(reader); | |
191 |
1
1. setXfa : negated conditional → NO_COVERAGE |
if (xfa.isArray()) { |
192 | PdfArray ar = (PdfArray)xfa; | |
193 | int t = -1; | |
194 | int d = -1; | |
195 |
3
1. setXfa : changed conditional boundary → NO_COVERAGE 2. setXfa : Changed increment from 2 to -2 → NO_COVERAGE 3. setXfa : negated conditional → NO_COVERAGE |
for (int k = 0; k < ar.size(); k += 2) { |
196 | PdfString s = ar.getAsString(k); | |
197 |
1
1. setXfa : negated conditional → NO_COVERAGE |
if ("template".equals(s.toString())) { |
198 |
1
1. setXfa : Replaced integer addition with subtraction → NO_COVERAGE |
t = k + 1; |
199 | } | |
200 |
1
1. setXfa : negated conditional → NO_COVERAGE |
if ("datasets".equals(s.toString())) { |
201 |
1
1. setXfa : Replaced integer addition with subtraction → NO_COVERAGE |
d = k + 1; |
202 | } | |
203 | } | |
204 |
4
1. setXfa : changed conditional boundary → NO_COVERAGE 2. setXfa : changed conditional boundary → NO_COVERAGE 3. setXfa : negated conditional → NO_COVERAGE 4. setXfa : negated conditional → NO_COVERAGE |
if (t > -1 && d > -1) { |
205 |
1
1. setXfa : removed call to com/lowagie/text/pdf/PdfReader::killXref → NO_COVERAGE |
reader.killXref(ar.getAsIndirectObject(t)); |
206 |
1
1. setXfa : removed call to com/lowagie/text/pdf/PdfReader::killXref → NO_COVERAGE |
reader.killXref(ar.getAsIndirectObject(d)); |
207 | PdfStream tStream = new PdfStream(serializeDoc(form.templateNode)); | |
208 |
1
1. setXfa : removed call to com/lowagie/text/pdf/PdfStream::flateCompress → NO_COVERAGE |
tStream.flateCompress(writer.getCompressionLevel()); |
209 | ar.set(t, writer.addToBody(tStream).getIndirectReference()); | |
210 | PdfStream dStream = new PdfStream(serializeDoc(form.datasetsNode)); | |
211 |
1
1. setXfa : removed call to com/lowagie/text/pdf/PdfStream::flateCompress → NO_COVERAGE |
dStream.flateCompress(writer.getCompressionLevel()); |
212 | ar.set(d, writer.addToBody(dStream).getIndirectReference()); | |
213 |
1
1. setXfa : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
af.put(PdfName.XFA, new PdfArray(ar)); |
214 | return; | |
215 | } | |
216 | } | |
217 |
1
1. setXfa : removed call to com/lowagie/text/pdf/PdfReader::killXref → NO_COVERAGE |
reader.killXref(af.get(PdfName.XFA)); |
218 | PdfStream str = new PdfStream(serializeDoc(form.domDocument)); | |
219 |
1
1. setXfa : removed call to com/lowagie/text/pdf/PdfStream::flateCompress → NO_COVERAGE |
str.flateCompress(writer.getCompressionLevel()); |
220 | PdfIndirectReference ref = writer.addToBody(str).getIndirectReference(); | |
221 |
1
1. setXfa : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
af.put(PdfName.XFA, ref); |
222 | } | |
223 | ||
224 | /** | |
225 | * Sets the XFA key from the instance data. The old XFA is erased. | |
226 | * @param writer the writer | |
227 | * @throws java.io.IOException on error | |
228 | */ | |
229 | public void setXfa(PdfWriter writer) throws IOException { | |
230 |
1
1. setXfa : removed call to com/lowagie/text/pdf/XfaForm::setXfa → NO_COVERAGE |
setXfa(this, reader, writer); |
231 | } | |
232 | ||
233 | /** | |
234 | * Serializes a XML document to a byte array. | |
235 | * @param n the XML document | |
236 | * @throws java.io.IOException on error | |
237 | * @return the serialized XML document | |
238 | */ | |
239 | public static byte[] serializeDoc(Node n) throws IOException { | |
240 | XmlDomWriter xw = new XmlDomWriter(); | |
241 | ByteArrayOutputStream fout = new ByteArrayOutputStream(); | |
242 |
1
1. serializeDoc : removed call to com/lowagie/text/xml/XmlDomWriter::setOutput → NO_COVERAGE |
xw.setOutput(fout, null); |
243 |
1
1. serializeDoc : removed call to com/lowagie/text/xml/XmlDomWriter::setCanonical → NO_COVERAGE |
xw.setCanonical(false); |
244 |
1
1. serializeDoc : removed call to com/lowagie/text/xml/XmlDomWriter::write → NO_COVERAGE |
xw.write(n); |
245 |
1
1. serializeDoc : removed call to java/io/ByteArrayOutputStream::close → NO_COVERAGE |
fout.close(); |
246 |
1
1. serializeDoc : mutated return of Object value for com/lowagie/text/pdf/XfaForm::serializeDoc to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return fout.toByteArray(); |
247 | } | |
248 | | |
249 | /** | |
250 | * Returns <CODE>true</CODE> if it is a XFA form. | |
251 | * @return <CODE>true</CODE> if it is a XFA form | |
252 | */ | |
253 | public boolean isXfaPresent() { | |
254 | return xfaPresent; | |
255 | } | |
256 | ||
257 | /** | |
258 | * Gets the top level DOM document. | |
259 | * @return the top level DOM document | |
260 | */ | |
261 | public org.w3c.dom.Document getDomDocument() { | |
262 | return domDocument; | |
263 | } | |
264 | | |
265 | | |
266 | /** | |
267 | * Finds the complete field name contained in the "classic" forms from a partial | |
268 | * name. | |
269 | * @param name the complete or partial name | |
270 | * @param af the fields | |
271 | * @return the complete name or <CODE>null</CODE> if not found | |
272 | */ | |
273 | public String findFieldName(String name, AcroFields af) { | |
274 | Map<String, AcroFields.Item> items = af.getFields(); | |
275 |
1
1. findFieldName : negated conditional → NO_COVERAGE |
if (items.containsKey(name)) |
276 |
1
1. findFieldName : mutated return of Object value for com/lowagie/text/pdf/XfaForm::findFieldName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return name; |
277 |
1
1. findFieldName : negated conditional → NO_COVERAGE |
if (acroFieldsSom == null) { |
278 |
2
1. findFieldName : negated conditional → NO_COVERAGE 2. findFieldName : negated conditional → NO_COVERAGE |
if (items.isEmpty() && xfaPresent) |
279 | acroFieldsSom = new AcroFieldsSearch(datasetsSom.getName2Node().keySet()); | |
280 | else | |
281 | acroFieldsSom = new AcroFieldsSearch(items.keySet()); | |
282 | } | |
283 |
1
1. findFieldName : negated conditional → NO_COVERAGE |
if (acroFieldsSom.getAcroShort2LongName().containsKey(name)) |
284 |
1
1. findFieldName : mutated return of Object value for com/lowagie/text/pdf/XfaForm::findFieldName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return acroFieldsSom.getAcroShort2LongName().get(name); |
285 |
1
1. findFieldName : mutated return of Object value for com/lowagie/text/pdf/XfaForm::findFieldName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return acroFieldsSom.inverseSearchGlobal(Xml2Som.splitParts(name)); |
286 | } | |
287 | | |
288 | /** | |
289 | * Finds the complete SOM name contained in the datasets section from a | |
290 | * possibly partial name. | |
291 | * @param name the complete or partial name | |
292 | * @return the complete name or <CODE>null</CODE> if not found | |
293 | */ | |
294 | public String findDatasetsName(String name) { | |
295 |
1
1. findDatasetsName : negated conditional → NO_COVERAGE |
if (datasetsSom.getName2Node().containsKey(name)) |
296 |
1
1. findDatasetsName : mutated return of Object value for com/lowagie/text/pdf/XfaForm::findDatasetsName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return name; |
297 |
1
1. findDatasetsName : mutated return of Object value for com/lowagie/text/pdf/XfaForm::findDatasetsName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return datasetsSom.inverseSearchGlobal(Xml2Som.splitParts(name)); |
298 | } | |
299 | ||
300 | /** | |
301 | * Finds the <CODE>Node</CODE> contained in the datasets section from a | |
302 | * possibly partial name. | |
303 | * @param name the complete or partial name | |
304 | * @return the <CODE>Node</CODE> or <CODE>null</CODE> if not found | |
305 | */ | |
306 | public Node findDatasetsNode(@Nullable String name) { | |
307 |
1
1. findDatasetsNode : negated conditional → NO_COVERAGE |
if (name == null) |
308 |
1
1. findDatasetsNode : mutated return of Object value for com/lowagie/text/pdf/XfaForm::findDatasetsNode to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
309 | name = findDatasetsName(name); | |
310 |
1
1. findDatasetsNode : negated conditional → NO_COVERAGE |
if (name == null) |
311 |
1
1. findDatasetsNode : mutated return of Object value for com/lowagie/text/pdf/XfaForm::findDatasetsNode to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
312 |
1
1. findDatasetsNode : mutated return of Object value for com/lowagie/text/pdf/XfaForm::findDatasetsNode to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return datasetsSom.getName2Node().get(name); |
313 | } | |
314 | ||
315 | /** | |
316 | * Gets all the text contained in the child nodes of this node. | |
317 | * @param n the <CODE>Node</CODE> | |
318 | * @return the text found or "" if no text was found | |
319 | */ | |
320 | public static String getNodeText(@Nullable Node n) { | |
321 |
1
1. getNodeText : negated conditional → NO_COVERAGE |
if (n == null) |
322 |
1
1. getNodeText : mutated return of Object value for com/lowagie/text/pdf/XfaForm::getNodeText to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return ""; |
323 |
1
1. getNodeText : mutated return of Object value for com/lowagie/text/pdf/XfaForm::getNodeText to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return getNodeText(n, ""); |
324 | | |
325 | } | |
326 | | |
327 | private static String getNodeText(Node n, String name) { | |
328 | Node n2 = n.getFirstChild(); | |
329 |
1
1. getNodeText : negated conditional → NO_COVERAGE |
while (n2 != null) { |
330 |
1
1. getNodeText : negated conditional → NO_COVERAGE |
if (n2.getNodeType() == Node.ELEMENT_NODE) { |
331 | name = getNodeText(n2, name); | |
332 | } | |
333 |
1
1. getNodeText : negated conditional → NO_COVERAGE |
else if (n2.getNodeType() == Node.TEXT_NODE) { |
334 | name += n2.getNodeValue(); | |
335 | } | |
336 | n2 = n2.getNextSibling(); | |
337 | } | |
338 |
1
1. getNodeText : mutated return of Object value for com/lowagie/text/pdf/XfaForm::getNodeText to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return name; |
339 | } | |
340 | | |
341 | /** | |
342 | * Sets the text of this node. All the child's node are deleted and a new | |
343 | * child text node is created. | |
344 | * @param n the <CODE>Node</CODE> to add the text to | |
345 | * @param text the text to add | |
346 | */ | |
347 | public void setNodeText(@Nullable Node n, String text) { | |
348 |
1
1. setNodeText : negated conditional → NO_COVERAGE |
if (n == null) |
349 | return; | |
350 | Node nc; | |
351 |
1
1. setNodeText : negated conditional → NO_COVERAGE |
while ((nc = n.getFirstChild()) != null) { |
352 | n.removeChild(nc); | |
353 | } | |
354 |
1
1. setNodeText : negated conditional → NO_COVERAGE |
if (n.getAttributes().getNamedItemNS(XFA_DATA_SCHEMA, "dataNode") != null) |
355 | n.getAttributes().removeNamedItemNS(XFA_DATA_SCHEMA, "dataNode"); | |
356 | n.appendChild(domDocument.createTextNode(text)); | |
357 | changed = true; | |
358 | } | |
359 | | |
360 | /** | |
361 | * Sets the XFA form flag signaling that this is a valid XFA form. | |
362 | * @param xfaPresent the XFA form flag signaling that this is a valid XFA form | |
363 | */ | |
364 | public void setXfaPresent(boolean xfaPresent) { | |
365 | this.xfaPresent = xfaPresent; | |
366 | } | |
367 | ||
368 | /** | |
369 | * Sets the top DOM document. | |
370 | * @param domDocument the top DOM document | |
371 | */ | |
372 | public void setDomDocument(org.w3c.dom.Document domDocument) { | |
373 | this.domDocument = domDocument; | |
374 |
1
1. setDomDocument : removed call to com/lowagie/text/pdf/XfaForm::extractNodes → NO_COVERAGE |
extractNodes(); |
375 | } | |
376 | ||
377 | /** | |
378 | * Gets the <CODE>PdfReader</CODE> used by this instance. | |
379 | * @return the <CODE>PdfReader</CODE> used by this instance | |
380 | */ | |
381 | public PdfReader getReader() { | |
382 | return reader; | |
383 | } | |
384 | ||
385 | /** | |
386 | * Sets the <CODE>PdfReader</CODE> to be used by this instance. | |
387 | * @param reader the <CODE>PdfReader</CODE> to be used by this instance | |
388 | */ | |
389 | public void setReader(PdfReader reader) { | |
390 | this.reader = reader; | |
391 | } | |
392 | ||
393 | /** | |
394 | * Checks if this XFA form was changed. | |
395 | * @return <CODE>true</CODE> if this XFA form was changed | |
396 | */ | |
397 | public boolean isChanged() { | |
398 | return changed; | |
399 | } | |
400 | ||
401 | /** | |
402 | * Sets the changed status of this XFA instance. | |
403 | * @param changed the changed status of this XFA instance | |
404 | */ | |
405 | public void setChanged(boolean changed) { | |
406 | this.changed = changed; | |
407 | } | |
408 | | |
409 | /** | |
410 | * A structure to store each part of a SOM name and link it to the next part | |
411 | * beginning from the lower hierarchy. | |
412 | */ | |
413 | public static class InverseStore { | |
414 | protected List<String> part = new ArrayList<>(); | |
415 | protected List<Object> follow = new ArrayList<>(); | |
416 | | |
417 | /** | |
418 | * Gets the full name by traversing the hierarchy using only the | |
419 | * index 0. | |
420 | * @return the full name | |
421 | */ | |
422 | public String getDefaultName() { | |
423 | InverseStore store = this; | |
424 | while (true) { | |
425 | Object obj = store.follow.get(0); | |
426 |
1
1. getDefaultName : negated conditional → NO_COVERAGE |
if (obj instanceof String) |
427 |
1
1. getDefaultName : mutated return of Object value for com/lowagie/text/pdf/XfaForm$InverseStore::getDefaultName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return (String)obj; |
428 | store = (InverseStore)obj; | |
429 | } | |
430 | } | |
431 | | |
432 | /** | |
433 | * Search the current node for a similar name. A similar name starts | |
434 | * with the same name but has a different index. For example, "detail[3]" | |
435 | * is similar to "detail[9]". The main use is to discard names that | |
436 | * correspond to out of bounds records. | |
437 | * @param name the name to search | |
438 | * @return <CODE>true</CODE> if a similitude was found | |
439 | */ | |
440 | public boolean isSimilar(String name) { | |
441 | int idx = name.indexOf('['); | |
442 |
1
1. isSimilar : Replaced integer addition with subtraction → NO_COVERAGE |
name = name.substring(0, idx + 1); |
443 | for (String o : part) { | |
444 |
1
1. isSimilar : negated conditional → NO_COVERAGE |
if (o.startsWith(name)) |
445 |
1
1. isSimilar : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return true; |
446 | } | |
447 |
1
1. isSimilar : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
448 | } | |
449 | } | |
450 | ||
451 | /** | |
452 | * Another stack implementation. The main use is to facilitate | |
453 | * the porting to other languages. | |
454 | */ | |
455 | public static class Stack2 extends ArrayList<String> { | |
456 | private static final long serialVersionUID = -7451476576174095212L; | |
457 | ||
458 | /** | |
459 | * Looks at the object at the top of this stack without removing it from the stack. | |
460 | * @return the object at the top of this stack | |
461 | */ | |
462 | public String peek() { | |
463 |
1
1. peek : negated conditional → NO_COVERAGE |
if (size() == 0) |
464 | throw new EmptyStackException(); | |
465 |
2
1. peek : Replaced integer subtraction with addition → NO_COVERAGE 2. peek : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Stack2::peek to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return get(size() - 1); |
466 | } | |
467 | | |
468 | /** | |
469 | * Removes the object at the top of this stack and returns that object as the value of this function. | |
470 | * @return the object at the top of this stack | |
471 | */ | |
472 | public String pop() { | |
473 |
1
1. pop : negated conditional → NO_COVERAGE |
if (size() == 0) |
474 | throw new EmptyStackException(); | |
475 |
1
1. pop : Replaced integer subtraction with addition → NO_COVERAGE |
String ret = get(size() - 1); |
476 |
1
1. pop : Replaced integer subtraction with addition → NO_COVERAGE |
remove(size() - 1); |
477 |
1
1. pop : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Stack2::pop to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return ret; |
478 | } | |
479 | | |
480 | /** | |
481 | * Pushes an item onto the top of this stack. | |
482 | * @param item the item to be pushed onto this stack | |
483 | * @return the <CODE>item</CODE> argument | |
484 | */ | |
485 | public String push(String item) { | |
486 | add(item); | |
487 |
1
1. push : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Stack2::push to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return item; |
488 | } | |
489 | | |
490 | /** | |
491 | * Tests if this stack is empty. | |
492 | * @return <CODE>true</CODE> if and only if this stack contains no items; <CODE>false</CODE> otherwise | |
493 | */ | |
494 | public boolean empty() { | |
495 |
2
1. empty : negated conditional → NO_COVERAGE 2. empty : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return size() == 0; |
496 | } | |
497 | } | |
498 | | |
499 | /** | |
500 | * A class for some basic SOM processing. | |
501 | */ | |
502 | public static class Xml2Som { | |
503 | /** | |
504 | * The order the names appear in the XML, depth first. | |
505 | */ | |
506 | protected List<String> order; | |
507 | /** | |
508 | * The mapping of full names to nodes. | |
509 | */ | |
510 | protected Map<String, Node> name2Node; | |
511 | /** | |
512 | * The data to do a search from the bottom hierarchy. | |
513 | */ | |
514 | protected Map<String, InverseStore> inverseSearch; | |
515 | /** | |
516 | * A stack to be used when parsing. | |
517 | */ | |
518 | protected Stack2 stack; | |
519 | /** | |
520 | * A temporary store for the repetition count. | |
521 | */ | |
522 | protected int anform; | |
523 | ||
524 | /** | |
525 | * Escapes a SOM string fragment replacing "." with "\.". | |
526 | * @param s the unescaped string | |
527 | * @return the escaped string | |
528 | */ | |
529 | public static String escapeSom(String s) { | |
530 |
1
1. escapeSom : negated conditional → NO_COVERAGE |
if(s==null) |
531 |
1
1. escapeSom : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::escapeSom to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return ""; |
532 | int idx = s.indexOf('.'); | |
533 |
2
1. escapeSom : changed conditional boundary → NO_COVERAGE 2. escapeSom : negated conditional → NO_COVERAGE |
if (idx < 0) |
534 |
1
1. escapeSom : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::escapeSom to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return s; |
535 | StringBuilder sb = new StringBuilder(); | |
536 | int last = 0; | |
537 |
2
1. escapeSom : changed conditional boundary → NO_COVERAGE 2. escapeSom : negated conditional → NO_COVERAGE |
while (idx >= 0) { |
538 | sb.append(s, last, idx); | |
539 | sb.append('\\'); | |
540 | last = idx; | |
541 |
1
1. escapeSom : Replaced integer addition with subtraction → NO_COVERAGE |
idx = s.indexOf('.', idx + 1); |
542 | } | |
543 | sb.append(s.substring(last)); | |
544 |
1
1. escapeSom : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::escapeSom to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
545 | } | |
546 | ||
547 | /** | |
548 | * Unescapes a SOM string fragment replacing "\." with ".". | |
549 | * @param s the escaped string | |
550 | * @return the unescaped string | |
551 | */ | |
552 | public static String unescapeSom(String s) { | |
553 | int idx = s.indexOf('\\'); | |
554 |
2
1. unescapeSom : changed conditional boundary → NO_COVERAGE 2. unescapeSom : negated conditional → NO_COVERAGE |
if (idx < 0) |
555 |
1
1. unescapeSom : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::unescapeSom to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return s; |
556 | StringBuilder sb = new StringBuilder(); | |
557 | int last = 0; | |
558 |
2
1. unescapeSom : changed conditional boundary → NO_COVERAGE 2. unescapeSom : negated conditional → NO_COVERAGE |
while (idx >= 0) { |
559 | sb.append(s, last, idx); | |
560 |
1
1. unescapeSom : Replaced integer addition with subtraction → NO_COVERAGE |
last = idx + 1; |
561 |
1
1. unescapeSom : Replaced integer addition with subtraction → NO_COVERAGE |
idx = s.indexOf('\\', idx + 1); |
562 | } | |
563 | sb.append(s.substring(last)); | |
564 |
1
1. unescapeSom : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::unescapeSom to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
565 | } | |
566 | ||
567 | /** | |
568 | * Outputs the stack as the sequence of elements separated | |
569 | * by '.'. | |
570 | * @return the stack as the sequence of elements separated by '.' | |
571 | */ | |
572 | protected String printStack() { | |
573 |
1
1. printStack : negated conditional → NO_COVERAGE |
if (stack.empty()) |
574 |
1
1. printStack : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::printStack to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return ""; |
575 | StringBuilder s = new StringBuilder(); | |
576 | for (String o : stack) s.append('.').append(o); | |
577 |
1
1. printStack : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::printStack to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return s.substring(1); |
578 | } | |
579 | | |
580 | /** | |
581 | * Gets the name with the <CODE>#subform</CODE> removed. | |
582 | * @param s the long name | |
583 | * @return the short name | |
584 | */ | |
585 | public static String getShortName(String s) { | |
586 | int idx = s.indexOf(".#subform["); | |
587 |
2
1. getShortName : changed conditional boundary → NO_COVERAGE 2. getShortName : negated conditional → NO_COVERAGE |
if (idx < 0) |
588 |
1
1. getShortName : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::getShortName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return s; |
589 | int last = 0; | |
590 | StringBuilder sb = new StringBuilder(); | |
591 |
2
1. getShortName : changed conditional boundary → NO_COVERAGE 2. getShortName : negated conditional → NO_COVERAGE |
while (idx >= 0) { |
592 | sb.append(s, last, idx); | |
593 |
1
1. getShortName : Replaced integer addition with subtraction → NO_COVERAGE |
idx = s.indexOf("]", idx + 10); |
594 |
2
1. getShortName : changed conditional boundary → NO_COVERAGE 2. getShortName : negated conditional → NO_COVERAGE |
if (idx < 0) |
595 |
1
1. getShortName : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::getShortName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
596 |
1
1. getShortName : Replaced integer addition with subtraction → NO_COVERAGE |
last = idx + 1; |
597 | idx = s.indexOf(".#subform[", last); | |
598 | } | |
599 | sb.append(s.substring(last)); | |
600 |
1
1. getShortName : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::getShortName to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
601 | } | |
602 | | |
603 | /** | |
604 | * Adds a SOM name to the search node chain. | |
605 | * @param unstack the SOM name | |
606 | */ | |
607 | public void inverseSearchAdd(String unstack) { | |
608 |
1
1. inverseSearchAdd : removed call to com/lowagie/text/pdf/XfaForm$Xml2Som::inverseSearchAdd → NO_COVERAGE |
inverseSearchAdd(inverseSearch, stack, unstack); |
609 | } | |
610 | | |
611 | /** | |
612 | * Adds a SOM name to the search node chain. | |
613 | * @param inverseSearch the start point | |
614 | * @param stack the stack with the separated SOM parts | |
615 | * @param unstack the full name | |
616 | */ | |
617 | public static void inverseSearchAdd(Map<String, InverseStore> inverseSearch, Stack2 stack, String unstack) { | |
618 | String last = stack.peek(); | |
619 | InverseStore store = inverseSearch.get(last); | |
620 |
1
1. inverseSearchAdd : negated conditional → NO_COVERAGE |
if (store == null) { |
621 | store = new InverseStore(); | |
622 | inverseSearch.put(last, store); | |
623 | } | |
624 |
4
1. inverseSearchAdd : changed conditional boundary → NO_COVERAGE 2. inverseSearchAdd : Changed increment from -1 to 1 → NO_COVERAGE 3. inverseSearchAdd : Replaced integer subtraction with addition → NO_COVERAGE 4. inverseSearchAdd : negated conditional → NO_COVERAGE |
for (int k = stack.size() - 2; k >= 0; --k) { |
625 | last = stack.get(k); | |
626 | InverseStore store2; | |
627 | int idx = store.part.indexOf(last); | |
628 |
2
1. inverseSearchAdd : changed conditional boundary → NO_COVERAGE 2. inverseSearchAdd : negated conditional → NO_COVERAGE |
if (idx < 0) { |
629 | store.part.add(last); | |
630 | store2 = new InverseStore(); | |
631 | store.follow.add(store2); | |
632 | } | |
633 | else | |
634 | store2 = (InverseStore)store.follow.get(idx); | |
635 | store = store2; | |
636 | } | |
637 | store.part.add(""); | |
638 | store.follow.add(unstack); | |
639 | } | |
640 | ||
641 | /** | |
642 | * Searches the SOM hierarchy from the bottom. | |
643 | * @param parts the SOM parts | |
644 | * @return the full name or <CODE>null</CODE> if not found | |
645 | */ | |
646 | public String inverseSearchGlobal(List<String> parts) { | |
647 |
1
1. inverseSearchGlobal : negated conditional → NO_COVERAGE |
if (parts.isEmpty()) |
648 |
1
1. inverseSearchGlobal : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::inverseSearchGlobal to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
649 |
1
1. inverseSearchGlobal : Replaced integer subtraction with addition → NO_COVERAGE |
InverseStore store = inverseSearch.get(parts.get(parts.size() - 1)); |
650 |
1
1. inverseSearchGlobal : negated conditional → NO_COVERAGE |
if (store == null) |
651 |
1
1. inverseSearchGlobal : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::inverseSearchGlobal to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
652 |
4
1. inverseSearchGlobal : changed conditional boundary → NO_COVERAGE 2. inverseSearchGlobal : Changed increment from -1 to 1 → NO_COVERAGE 3. inverseSearchGlobal : Replaced integer subtraction with addition → NO_COVERAGE 4. inverseSearchGlobal : negated conditional → NO_COVERAGE |
for (int k = parts.size() - 2; k >= 0; --k) { |
653 | String part = parts.get(k); | |
654 | int idx = store.part.indexOf(part); | |
655 |
2
1. inverseSearchGlobal : changed conditional boundary → NO_COVERAGE 2. inverseSearchGlobal : negated conditional → NO_COVERAGE |
if (idx < 0) { |
656 |
1
1. inverseSearchGlobal : negated conditional → NO_COVERAGE |
if (store.isSimilar(part)) |
657 |
1
1. inverseSearchGlobal : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::inverseSearchGlobal to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
658 |
1
1. inverseSearchGlobal : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::inverseSearchGlobal to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return store.getDefaultName(); |
659 | } | |
660 | store = (InverseStore)store.follow.get(idx); | |
661 | } | |
662 |
1
1. inverseSearchGlobal : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::inverseSearchGlobal to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return store.getDefaultName(); |
663 | } | |
664 | | |
665 | /** | |
666 | * Splits a SOM name in the individual parts. | |
667 | * @param name the full SOM name | |
668 | * @return the split name | |
669 | */ | |
670 | public static Stack2 splitParts(String name) { | |
671 |
1
1. splitParts : negated conditional → NO_COVERAGE |
while (name.startsWith(".")) |
672 | name = name.substring(1); | |
673 | Stack2 parts = new Stack2(); | |
674 | int last = 0; | |
675 | int pos = 0; | |
676 | String part; | |
677 | while (true) { | |
678 | pos = last; | |
679 | while (true) { | |
680 | pos = name.indexOf('.', pos); | |
681 |
2
1. splitParts : changed conditional boundary → NO_COVERAGE 2. splitParts : negated conditional → NO_COVERAGE |
if (pos < 0) |
682 | break; | |
683 |
2
1. splitParts : Replaced integer subtraction with addition → NO_COVERAGE 2. splitParts : negated conditional → NO_COVERAGE |
if (name.charAt(pos - 1) == '\\') |
684 |
1
1. splitParts : Changed increment from 1 to -1 → NO_COVERAGE |
++pos; |
685 | else | |
686 | break; | |
687 | } | |
688 |
2
1. splitParts : changed conditional boundary → NO_COVERAGE 2. splitParts : negated conditional → NO_COVERAGE |
if (pos < 0) |
689 | break; | |
690 | part = name.substring(last, pos); | |
691 |
1
1. splitParts : negated conditional → NO_COVERAGE |
if (!part.endsWith("]")) |
692 | part += "[0]"; | |
693 | parts.add(part); | |
694 |
1
1. splitParts : Replaced integer addition with subtraction → NO_COVERAGE |
last = pos + 1; |
695 | } | |
696 | part = name.substring(last); | |
697 |
1
1. splitParts : negated conditional → NO_COVERAGE |
if (!part.endsWith("]")) |
698 | part += "[0]"; | |
699 | parts.add(part); | |
700 |
1
1. splitParts : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2Som::splitParts to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return parts; |
701 | } | |
702 | ||
703 | /** | |
704 | * Gets the order the names appear in the XML, depth first. | |
705 | * @return the order the names appear in the XML, depth first | |
706 | */ | |
707 | public List<String> getOrder() { | |
708 | return order; | |
709 | } | |
710 | ||
711 | /** | |
712 | * Sets the order the names appear in the XML, depth first | |
713 | * @param order the order the names appear in the XML, depth first | |
714 | */ | |
715 | public void setOrder(List<String> order) { | |
716 | this.order = order; | |
717 | } | |
718 | ||
719 | /** | |
720 | * Gets the mapping of full names to nodes. | |
721 | * @return the mapping of full names to nodes | |
722 | */ | |
723 | public Map<String, Node> getName2Node() { | |
724 | return name2Node; | |
725 | } | |
726 | ||
727 | /** | |
728 | * Sets the mapping of full names to nodes. | |
729 | * @param name2Node the mapping of full names to nodes | |
730 | */ | |
731 | public void setName2Node(Map<String, Node> name2Node) { | |
732 | this.name2Node = name2Node; | |
733 | } | |
734 | ||
735 | /** | |
736 | * Gets the data to do a search from the bottom hierarchy. | |
737 | * @return the data to do a search from the bottom hierarchy | |
738 | */ | |
739 | public Map<String, InverseStore> getInverseSearch() { | |
740 | return inverseSearch; | |
741 | } | |
742 | ||
743 | /** | |
744 | * Sets the data to do a search from the bottom hierarchy. | |
745 | * @param inverseSearch the data to do a search from the bottom hierarchy | |
746 | */ | |
747 | public void setInverseSearch(Map<String, InverseStore> inverseSearch) { | |
748 | this.inverseSearch = inverseSearch; | |
749 | } | |
750 | } | |
751 | | |
752 | /** | |
753 | * Processes the datasets section in the XFA form. | |
754 | */ | |
755 | public static class Xml2SomDatasets extends Xml2Som { | |
756 | /** | |
757 | * Creates a new instance from the datasets node. This expects | |
758 | * not the datasets but the data node that comes below. | |
759 | * @param n the datasets node | |
760 | */ | |
761 | public Xml2SomDatasets(Node n) { | |
762 | order = new ArrayList<>(); | |
763 | name2Node = new HashMap<>(); | |
764 | stack = new Stack2(); | |
765 | anform = 0; | |
766 | inverseSearch = new HashMap<>(); | |
767 |
1
1. |
processDatasetsInternal(n); |
768 | } | |
769 | ||
770 | /** | |
771 | * Inserts a new <CODE>Node</CODE> that will match the short name. | |
772 | * @param n the datasets top <CODE>Node</CODE> | |
773 | * @param shortName the short name | |
774 | * @return the new <CODE>Node</CODE> of the inserted name | |
775 | */ | |
776 | public Node insertNode(Node n, String shortName) { | |
777 | Stack2 stack = splitParts(shortName); | |
778 | org.w3c.dom.Document doc = n.getOwnerDocument(); | |
779 | Node n2 = null; | |
780 | n = n.getFirstChild(); | |
781 | for (Object o : stack) { | |
782 | String part = (String) o; | |
783 | int idx = part.lastIndexOf('['); | |
784 | String name = part.substring(0, idx); | |
785 |
2
1. insertNode : Replaced integer addition with subtraction → NO_COVERAGE 2. insertNode : Replaced integer subtraction with addition → NO_COVERAGE |
idx = Integer.parseInt(part.substring(idx + 1, part.length() - 1)); |
786 | int found = -1; | |
787 |
1
1. insertNode : negated conditional → NO_COVERAGE |
for (n2 = n.getFirstChild(); n2 != null; n2 = n2.getNextSibling()) { |
788 |
1
1. insertNode : negated conditional → NO_COVERAGE |
if (n2.getNodeType() == Node.ELEMENT_NODE) { |
789 | String s = escapeSom(n2.getLocalName()); | |
790 |
1
1. insertNode : negated conditional → NO_COVERAGE |
if (s.equals(name)) { |
791 |
1
1. insertNode : Changed increment from 1 to -1 → NO_COVERAGE |
++found; |
792 |
1
1. insertNode : negated conditional → NO_COVERAGE |
if (found == idx) |
793 | break; | |
794 | } | |
795 | } | |
796 | } | |
797 |
3
1. insertNode : changed conditional boundary → NO_COVERAGE 2. insertNode : Changed increment from 1 to -1 → NO_COVERAGE 3. insertNode : negated conditional → NO_COVERAGE |
for (; found < idx; ++found) { |
798 | n2 = doc.createElementNS(null, name); | |
799 | n2 = n.appendChild(n2); | |
800 | Node attr = doc.createAttributeNS(XFA_DATA_SCHEMA, "dataNode"); | |
801 |
1
1. insertNode : removed call to org/w3c/dom/Node::setNodeValue → NO_COVERAGE |
attr.setNodeValue("dataGroup"); |
802 | n2.getAttributes().setNamedItemNS(attr); | |
803 | } | |
804 | n = n2; | |
805 | } | |
806 |
1
1. insertNode : removed call to com/lowagie/text/pdf/XfaForm$Xml2SomDatasets::inverseSearchAdd → NO_COVERAGE |
inverseSearchAdd(inverseSearch, stack, shortName); |
807 | name2Node.put(shortName, n2); | |
808 | order.add(shortName); | |
809 |
1
1. insertNode : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2SomDatasets::insertNode to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return n2; |
810 | } | |
811 | | |
812 | private static boolean hasChildren(Node n) { | |
813 | Node dataNodeN = n.getAttributes().getNamedItemNS(XFA_DATA_SCHEMA, "dataNode"); | |
814 |
1
1. hasChildren : negated conditional → NO_COVERAGE |
if (dataNodeN != null) { |
815 | String dataNode = dataNodeN.getNodeValue(); | |
816 |
1
1. hasChildren : negated conditional → NO_COVERAGE |
if ("dataGroup".equals(dataNode)) |
817 |
1
1. hasChildren : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return true; |
818 |
1
1. hasChildren : negated conditional → NO_COVERAGE |
else if ("dataValue".equals(dataNode)) |
819 |
1
1. hasChildren : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
820 | } | |
821 |
1
1. hasChildren : negated conditional → NO_COVERAGE |
if (!n.hasChildNodes()) |
822 |
1
1. hasChildren : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
823 | Node n2 = n.getFirstChild(); | |
824 |
1
1. hasChildren : negated conditional → NO_COVERAGE |
while (n2 != null) { |
825 |
1
1. hasChildren : negated conditional → NO_COVERAGE |
if (n2.getNodeType() == Node.ELEMENT_NODE) { |
826 |
1
1. hasChildren : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return true; |
827 | } | |
828 | n2 = n2.getNextSibling(); | |
829 | } | |
830 |
1
1. hasChildren : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
831 | } | |
832 | ||
833 | private void processDatasetsInternal(Node n) { | |
834 | Map<String, Integer> ss = new HashMap<>(); | |
835 | Node n2 = n.getFirstChild(); | |
836 |
1
1. processDatasetsInternal : negated conditional → NO_COVERAGE |
while (n2 != null) { |
837 |
1
1. processDatasetsInternal : negated conditional → NO_COVERAGE |
if (n2.getNodeType() == Node.ELEMENT_NODE) { |
838 | String s = escapeSom(n2.getLocalName()); | |
839 | Integer i = ss.get(s); | |
840 |
1
1. processDatasetsInternal : negated conditional → NO_COVERAGE |
if (i == null) |
841 | i = 0; | |
842 | else | |
843 |
1
1. processDatasetsInternal : Replaced integer addition with subtraction → NO_COVERAGE |
i = i + 1; |
844 | ss.put(s, i); | |
845 |
1
1. processDatasetsInternal : negated conditional → NO_COVERAGE |
if (hasChildren(n2)) { |
846 | stack.push(s + "[" + i.toString() + "]"); | |
847 |
1
1. processDatasetsInternal : removed call to com/lowagie/text/pdf/XfaForm$Xml2SomDatasets::processDatasetsInternal → NO_COVERAGE |
processDatasetsInternal(n2); |
848 | stack.pop(); | |
849 | } | |
850 | else { | |
851 | stack.push(s + "[" + i.toString() + "]"); | |
852 | String unstack = printStack(); | |
853 | order.add(unstack); | |
854 |
1
1. processDatasetsInternal : removed call to com/lowagie/text/pdf/XfaForm$Xml2SomDatasets::inverseSearchAdd → NO_COVERAGE |
inverseSearchAdd(unstack); |
855 | name2Node.put(unstack, n2); | |
856 | stack.pop(); | |
857 | } | |
858 | } | |
859 | n2 = n2.getNextSibling(); | |
860 | } | |
861 | } | |
862 | } | |
863 | ||
864 | /** | |
865 | * A class to process "classic" fields. | |
866 | */ | |
867 | public static class AcroFieldsSearch extends Xml2Som { | |
868 | private Map<String, String> acroShort2LongName; | |
869 | | |
870 | /** | |
871 | * Creates a new instance from a Collection with the full names. | |
872 | * @param items the Collection | |
873 | */ | |
874 | public AcroFieldsSearch(Collection<String> items) { | |
875 | inverseSearch = new HashMap<>(); | |
876 | acroShort2LongName = new HashMap<>(); | |
877 | for (String itemName : items) { | |
878 | String itemShort = getShortName(itemName); | |
879 | acroShort2LongName.put(itemShort, itemName); | |
880 |
1
1. |
inverseSearchAdd(inverseSearch, splitParts(itemShort), itemName); |
881 | } | |
882 | } | |
883 | ||
884 | /** | |
885 | * Gets the mapping from short names to long names. A long | |
886 | * name may contain the #subform name part. | |
887 | * @return the mapping from short names to long names | |
888 | */ | |
889 | public Map<String, String> getAcroShort2LongName() { | |
890 | return acroShort2LongName; | |
891 | } | |
892 | ||
893 | /** | |
894 | * Sets the mapping from short names to long names. A long | |
895 | * name may contain the #subform name part. | |
896 | * @param acroShort2LongName the mapping from short names to long names | |
897 | */ | |
898 | public void setAcroShort2LongName(Map<String, String> acroShort2LongName) { | |
899 | this.acroShort2LongName = acroShort2LongName; | |
900 | } | |
901 | } | |
902 | ||
903 | /** | |
904 | * Processes the template section in the XFA form. | |
905 | */ | |
906 | public static class Xml2SomTemplate extends Xml2Som { | |
907 | private boolean dynamicForm; | |
908 | private int templateLevel; | |
909 | | |
910 | /** | |
911 | * Creates a new instance from the datasets node. | |
912 | * @param n the template node | |
913 | */ | |
914 | public Xml2SomTemplate(Node n) { | |
915 | order = new ArrayList<>(); | |
916 | name2Node = new HashMap<>(); | |
917 | stack = new Stack2(); | |
918 | anform = 0; | |
919 | templateLevel = 0; | |
920 | inverseSearch = new HashMap<>(); | |
921 |
1
1. |
processTemplate(n, null); |
922 | } | |
923 | ||
924 | /** | |
925 | * Gets the field type as described in the <CODE>template</CODE> section of the XFA. | |
926 | * @param s the exact template name | |
927 | * @return the field type or <CODE>null</CODE> if not found | |
928 | */ | |
929 | public String getFieldType(String s) { | |
930 | Node n = name2Node.get(s); | |
931 |
1
1. getFieldType : negated conditional → NO_COVERAGE |
if (n == null) |
932 |
1
1. getFieldType : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2SomTemplate::getFieldType to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
933 |
1
1. getFieldType : negated conditional → NO_COVERAGE |
if (n.getLocalName().equals("exclGroup")) |
934 |
1
1. getFieldType : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2SomTemplate::getFieldType to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return "exclGroup"; |
935 | Node ui = n.getFirstChild(); | |
936 |
1
1. getFieldType : negated conditional → NO_COVERAGE |
while (ui != null) { |
937 |
2
1. getFieldType : negated conditional → NO_COVERAGE 2. getFieldType : negated conditional → NO_COVERAGE |
if (ui.getNodeType() == Node.ELEMENT_NODE && ui.getLocalName().equals("ui")) { |
938 | break; | |
939 | } | |
940 | ui = ui.getNextSibling(); | |
941 | } | |
942 |
1
1. getFieldType : negated conditional → NO_COVERAGE |
if (ui == null) |
943 |
1
1. getFieldType : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2SomTemplate::getFieldType to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
944 | Node type = ui.getFirstChild(); | |
945 |
1
1. getFieldType : negated conditional → NO_COVERAGE |
while (type != null) { |
946 |
3
1. getFieldType : negated conditional → NO_COVERAGE 2. getFieldType : negated conditional → NO_COVERAGE 3. getFieldType : negated conditional → NO_COVERAGE |
if (type.getNodeType() == Node.ELEMENT_NODE && !(type.getLocalName().equals("extras") && type.getLocalName().equals("picture"))) { |
947 |
1
1. getFieldType : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2SomTemplate::getFieldType to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return type.getLocalName(); |
948 | } | |
949 | type = type.getNextSibling(); | |
950 | } | |
951 |
1
1. getFieldType : mutated return of Object value for com/lowagie/text/pdf/XfaForm$Xml2SomTemplate::getFieldType to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
952 | } | |
953 | ||
954 | private void processTemplate(Node n, @Nullable Map<String, Integer> ff) { | |
955 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (ff == null) |
956 | ff = new HashMap<>(); | |
957 | Map<String, Integer> ss = new HashMap<>(); | |
958 | Node n2 = n.getFirstChild(); | |
959 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
while (n2 != null) { |
960 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (n2.getNodeType() == Node.ELEMENT_NODE) { |
961 | String s = n2.getLocalName(); | |
962 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (s.equals("subform")) { |
963 | Node name = n2.getAttributes().getNamedItem("name"); | |
964 | String nn = "#subform"; | |
965 | boolean annon = true; | |
966 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (name != null) { |
967 | nn = escapeSom(name.getNodeValue()); | |
968 | annon = false; | |
969 | } | |
970 | Integer i; | |
971 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (annon) { |
972 | i = anform; | |
973 |
1
1. processTemplate : Replaced integer addition with subtraction → NO_COVERAGE |
++anform; |
974 | } | |
975 | else { | |
976 | i = ss.get(nn); | |
977 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (i == null) |
978 | i = 0; | |
979 | else | |
980 |
1
1. processTemplate : Replaced integer addition with subtraction → NO_COVERAGE |
i = i + 1; |
981 | ss.put(nn, i); | |
982 | } | |
983 | stack.push(nn + "[" + i.toString() + "]"); | |
984 |
1
1. processTemplate : Replaced integer addition with subtraction → NO_COVERAGE |
++templateLevel; |
985 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (annon) |
986 |
1
1. processTemplate : removed call to com/lowagie/text/pdf/XfaForm$Xml2SomTemplate::processTemplate → NO_COVERAGE |
processTemplate(n2, ff); |
987 | else | |
988 |
1
1. processTemplate : removed call to com/lowagie/text/pdf/XfaForm$Xml2SomTemplate::processTemplate → NO_COVERAGE |
processTemplate(n2, null); |
989 |
1
1. processTemplate : Replaced integer subtraction with addition → NO_COVERAGE |
--templateLevel; |
990 | stack.pop(); | |
991 | } | |
992 |
2
1. processTemplate : negated conditional → NO_COVERAGE 2. processTemplate : negated conditional → NO_COVERAGE |
else if (s.equals("field") || s.equals("exclGroup")) { |
993 | Node name = n2.getAttributes().getNamedItem("name"); | |
994 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (name != null) { |
995 | String nn = escapeSom(name.getNodeValue()); | |
996 | Integer i = ff.get(nn); | |
997 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (i == null) |
998 | i = 0; | |
999 | else | |
1000 |
1
1. processTemplate : Replaced integer addition with subtraction → NO_COVERAGE |
i = i + 1; |
1001 | ff.put(nn, i); | |
1002 | stack.push(nn + "[" + i.toString() + "]"); | |
1003 | String unstack = printStack(); | |
1004 | order.add(unstack); | |
1005 |
1
1. processTemplate : removed call to com/lowagie/text/pdf/XfaForm$Xml2SomTemplate::inverseSearchAdd → NO_COVERAGE |
inverseSearchAdd(unstack); |
1006 | name2Node.put(unstack, n2); | |
1007 | stack.pop(); | |
1008 | } | |
1009 | } | |
1010 |
4
1. processTemplate : changed conditional boundary → NO_COVERAGE 2. processTemplate : negated conditional → NO_COVERAGE 3. processTemplate : negated conditional → NO_COVERAGE 4. processTemplate : negated conditional → NO_COVERAGE |
else if (!dynamicForm && templateLevel > 0 && s.equals("occur")) { |
1011 | int initial = 1; | |
1012 | int min = 1; | |
1013 | int max = 1; | |
1014 | Node a = n2.getAttributes().getNamedItem("initial"); | |
1015 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (a != null) |
1016 | try{initial = Integer.parseInt(a.getNodeValue().trim());}catch(Exception e){} | |
1017 | a = n2.getAttributes().getNamedItem("min"); | |
1018 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (a != null) |
1019 | try{min = Integer.parseInt(a.getNodeValue().trim());}catch(Exception e){} | |
1020 | a = n2.getAttributes().getNamedItem("max"); | |
1021 |
1
1. processTemplate : negated conditional → NO_COVERAGE |
if (a != null) |
1022 | try{max = Integer.parseInt(a.getNodeValue().trim());}catch(Exception e){} | |
1023 |
2
1. processTemplate : negated conditional → NO_COVERAGE 2. processTemplate : negated conditional → NO_COVERAGE |
if (initial != min || min != max) |
1024 | dynamicForm = true; | |
1025 | } | |
1026 | } | |
1027 | n2 = n2.getNextSibling(); | |
1028 | } | |
1029 | } | |
1030 | ||
1031 | /** | |
1032 | * <CODE>true</CODE> if it's a dynamic form; <CODE>false</CODE> | |
1033 | * if it's a static form. | |
1034 | * @return <CODE>true</CODE> if it's a dynamic form; <CODE>false</CODE> | |
1035 | * if it's a static form | |
1036 | */ | |
1037 | public boolean isDynamicForm() { | |
1038 | return dynamicForm; | |
1039 | } | |
1040 | ||
1041 | /** | |
1042 | * Sets the dynamic form flag. It doesn't change the template. | |
1043 | * @param dynamicForm the dynamic form flag | |
1044 | */ | |
1045 | public void setDynamicForm(boolean dynamicForm) { | |
1046 | this.dynamicForm = dynamicForm; | |
1047 | } | |
1048 | } | |
1049 | ||
1050 | /** | |
1051 | * Gets the class that contains the template processing section of the XFA. | |
1052 | * @return the class that contains the template processing section of the XFA | |
1053 | */ | |
1054 | public Xml2SomTemplate getTemplateSom() { | |
1055 | return templateSom; | |
1056 | } | |
1057 | ||
1058 | /** | |
1059 | * Sets the class that contains the template processing section of the XFA | |
1060 | * @param templateSom the class that contains the template processing section of the XFA | |
1061 | */ | |
1062 | public void setTemplateSom(Xml2SomTemplate templateSom) { | |
1063 | this.templateSom = templateSom; | |
1064 | } | |
1065 | ||
1066 | /** | |
1067 | * Gets the class that contains the datasets processing section of the XFA. | |
1068 | * @return the class that contains the datasets processing section of the XFA | |
1069 | */ | |
1070 | public Xml2SomDatasets getDatasetsSom() { | |
1071 | return datasetsSom; | |
1072 | } | |
1073 | ||
1074 | /** | |
1075 | * Sets the class that contains the datasets processing section of the XFA. | |
1076 | * @param datasetsSom the class that contains the datasets processing section of the XFA | |
1077 | */ | |
1078 | public void setDatasetsSom(Xml2SomDatasets datasetsSom) { | |
1079 | this.datasetsSom = datasetsSom; | |
1080 | } | |
1081 | ||
1082 | /** | |
1083 | * Gets the class that contains the "classic" fields processing. | |
1084 | * @return the class that contains the "classic" fields processing | |
1085 | */ | |
1086 | public AcroFieldsSearch getAcroFieldsSom() { | |
1087 | return acroFieldsSom; | |
1088 | } | |
1089 | ||
1090 | /** | |
1091 | * Sets the class that contains the "classic" fields processing. | |
1092 | * @param acroFieldsSom the class that contains the "classic" fields processing | |
1093 | */ | |
1094 | public void setAcroFieldsSom(AcroFieldsSearch acroFieldsSom) { | |
1095 | this.acroFieldsSom = acroFieldsSom; | |
1096 | } | |
1097 | | |
1098 | /** | |
1099 | * Gets the <CODE>Node</CODE> that corresponds to the datasets part. | |
1100 | * @return the <CODE>Node</CODE> that corresponds to the datasets part | |
1101 | */ | |
1102 | public Node getDatasetsNode() { | |
1103 | return datasetsNode; | |
1104 | } | |
1105 | | |
1106 | public void fillXfaForm(File file) throws ParserConfigurationException, SAXException, IOException { | |
1107 |
1
1. fillXfaForm : removed call to com/lowagie/text/pdf/XfaForm::fillXfaForm → NO_COVERAGE |
fillXfaForm(new FileInputStream(file)); |
1108 | } | |
1109 | | |
1110 | public void fillXfaForm(InputStream is) throws ParserConfigurationException, SAXException, IOException { | |
1111 |
1
1. fillXfaForm : removed call to com/lowagie/text/pdf/XfaForm::fillXfaForm → NO_COVERAGE |
fillXfaForm(new InputSource(is)); |
1112 | } | |
1113 | | |
1114 | | |
1115 | public void fillXfaForm(InputSource is) throws ParserConfigurationException, SAXException, IOException { | |
1116 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | |
1117 | DocumentBuilder db = dbf.newDocumentBuilder(); | |
1118 |
1
1. fillXfaForm : removed call to javax/xml/parsers/DocumentBuilder::setEntityResolver → NO_COVERAGE |
db.setEntityResolver((publicId, systemId) -> new InputSource(new StringReader(""))); |
1119 | Document newdoc = db.parse(is); | |
1120 |
1
1. fillXfaForm : removed call to com/lowagie/text/pdf/XfaForm::fillXfaForm → NO_COVERAGE |
fillXfaForm(newdoc.getDocumentElement()); |
1121 | } | |
1122 | | |
1123 | /** | |
1124 | * Replaces the data under datasets/data. | |
1125 | * @since iText 5.0.0 | |
1126 | */ | |
1127 | public void fillXfaForm(Node node) { | |
1128 | Node data = datasetsNode.getFirstChild(); | |
1129 | NodeList list = data.getChildNodes(); | |
1130 |
1
1. fillXfaForm : negated conditional → NO_COVERAGE |
if (list.getLength() == 0) { |
1131 | data.appendChild(domDocument.importNode(node, true)); | |
1132 | } | |
1133 | else { | |
1134 | data.replaceChild(domDocument.importNode(node, true), data.getFirstChild()); | |
1135 | } | |
1136 |
1
1. fillXfaForm : removed call to com/lowagie/text/pdf/XfaForm::extractNodes → NO_COVERAGE |
extractNodes(); |
1137 |
1
1. fillXfaForm : removed call to com/lowagie/text/pdf/XfaForm::setChanged → NO_COVERAGE |
setChanged(true); |
1138 | } | |
1139 | } | |
Mutations | ||
106 |
1.1 |
|
107 |
1.1 |
|
109 |
1.1 |
|
123 |
1.1 |
|
129 |
1.1 |
|
131 |
1.1 2.2 |
|
133 |
1.1 |
|
135 |
1.1 |
|
139 |
1.1 |
|
141 |
1.1 |
|
143 |
1.1 |
|
145 |
1.1 |
|
147 |
1.1 |
|
149 |
1.1 |
|
158 |
1.1 |
|
162 |
1.1 |
|
163 |
1.1 |
|
165 |
1.1 |
|
169 |
1.1 |
|
187 |
1.1 |
|
191 |
1.1 |
|
195 |
1.1 2.2 3.3 |
|
197 |
1.1 |
|
198 |
1.1 |
|
200 |
1.1 |
|
201 |
1.1 |
|
204 |
1.1 2.2 3.3 4.4 |
|
205 |
1.1 |
|
206 |
1.1 |
|
208 |
1.1 |
|
211 |
1.1 |
|
213 |
1.1 |
|
217 |
1.1 |
|
219 |
1.1 |
|
221 |
1.1 |
|
230 |
1.1 |
|
242 |
1.1 |
|
243 |
1.1 |
|
244 |
1.1 |
|
245 |
1.1 |
|
246 |
1.1 |
|
275 |
1.1 |
|
276 |
1.1 |
|
277 |
1.1 |
|
278 |
1.1 2.2 |
|
283 |
1.1 |
|
284 |
1.1 |
|
285 |
1.1 |
|
295 |
1.1 |
|
296 |
1.1 |
|
297 |
1.1 |
|
307 |
1.1 |
|
308 |
1.1 |
|
310 |
1.1 |
|
311 |
1.1 |
|
312 |
1.1 |
|
321 |
1.1 |
|
322 |
1.1 |
|
323 |
1.1 |
|
329 |
1.1 |
|
330 |
1.1 |
|
333 |
1.1 |
|
338 |
1.1 |
|
348 |
1.1 |
|
351 |
1.1 |
|
354 |
1.1 |
|
374 |
1.1 |
|
426 |
1.1 |
|
427 |
1.1 |
|
442 |
1.1 |
|
444 |
1.1 |
|
445 |
1.1 |
|
447 |
1.1 |
|
463 |
1.1 |
|
465 |
1.1 2.2 |
|
473 |
1.1 |
|
475 |
1.1 |
|
476 |
1.1 |
|
477 |
1.1 |
|
487 |
1.1 |
|
495 |
1.1 2.2 |
|
530 |
1.1 |
|
531 |
1.1 |
|
533 |
1.1 2.2 |
|
534 |
1.1 |
|
537 |
1.1 2.2 |
|
541 |
1.1 |
|
544 |
1.1 |
|
554 |
1.1 2.2 |
|
555 |
1.1 |
|
558 |
1.1 2.2 |
|
560 |
1.1 |
|
561 |
1.1 |
|
564 |
1.1 |
|
573 |
1.1 |
|
574 |
1.1 |
|
577 |
1.1 |
|
587 |
1.1 2.2 |
|
588 |
1.1 |
|
591 |
1.1 2.2 |
|
593 |
1.1 |
|
594 |
1.1 2.2 |
|
595 |
1.1 |
|
596 |
1.1 |
|
600 |
1.1 |
|
608 |
1.1 |
|
620 |
1.1 |
|
624 |
1.1 2.2 3.3 4.4 |
|
628 |
1.1 2.2 |
|
647 |
1.1 |
|
648 |
1.1 |
|
649 |
1.1 |
|
650 |
1.1 |
|
651 |
1.1 |
|
652 |
1.1 2.2 3.3 4.4 |
|
655 |
1.1 2.2 |
|
656 |
1.1 |
|
657 |
1.1 |
|
658 |
1.1 |
|
662 |
1.1 |
|
671 |
1.1 |
|
681 |
1.1 2.2 |
|
683 |
1.1 2.2 |
|
684 |
1.1 |
|
688 |
1.1 2.2 |
|
691 |
1.1 |
|
694 |
1.1 |
|
697 |
1.1 |
|
700 |
1.1 |
|
767 |
1.1 |
|
785 |
1.1 2.2 |
|
787 |
1.1 |
|
788 |
1.1 |
|
790 |
1.1 |
|
791 |
1.1 |
|
792 |
1.1 |
|
797 |
1.1 2.2 3.3 |
|
801 |
1.1 |
|
806 |
1.1 |
|
809 |
1.1 |
|
814 |
1.1 |
|
816 |
1.1 |
|
817 |
1.1 |
|
818 |
1.1 |
|
819 |
1.1 |
|
821 |
1.1 |
|
822 |
1.1 |
|
824 |
1.1 |
|
825 |
1.1 |
|
826 |
1.1 |
|
830 |
1.1 |
|
836 |
1.1 |
|
837 |
1.1 |
|
840 |
1.1 |
|
843 |
1.1 |
|
845 |
1.1 |
|
847 |
1.1 |
|
854 |
1.1 |
|
880 |
1.1 |
|
921 |
1.1 |
|
931 |
1.1 |
|
932 |
1.1 |
|
933 |
1.1 |
|
934 |
1.1 |
|
936 |
1.1 |
|
937 |
1.1 2.2 |
|
942 |
1.1 |
|
943 |
1.1 |
|
945 |
1.1 |
|
946 |
1.1 2.2 3.3 |
|
947 |
1.1 |
|
951 |
1.1 |
|
955 |
1.1 |
|
959 |
1.1 |
|
960 |
1.1 |
|
962 |
1.1 |
|
966 |
1.1 |
|
971 |
1.1 |
|
973 |
1.1 |
|
977 |
1.1 |
|
980 |
1.1 |
|
984 |
1.1 |
|
985 |
1.1 |
|
986 |
1.1 |
|
988 |
1.1 |
|
989 |
1.1 |
|
992 |
1.1 2.2 |
|
994 |
1.1 |
|
997 |
1.1 |
|
1000 |
1.1 |
|
1005 |
1.1 |
|
1010 |
1.1 2.2 3.3 4.4 |
|
1015 |
1.1 |
|
1018 |
1.1 |
|
1021 |
1.1 |
|
1023 |
1.1 2.2 |
|
1107 |
1.1 |
|
1111 |
1.1 |
|
1118 |
1.1 |
|
1120 |
1.1 |
|
1130 |
1.1 |
|
1136 |
1.1 |
|
1137 |
1.1 |