1 | /* | |
2 | * Copyright 2003 by Paulo Soares. | |
3 | * | |
4 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
5 | * (the "License"); you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
7 | * | |
8 | * Software distributed under the License is distributed on an "AS IS" basis, | |
9 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
10 | * for the specific language governing rights and limitations under the License. | |
11 | * | |
12 | * The Original Code is 'iText, a free JAVA-PDF library'. | |
13 | * | |
14 | * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by | |
15 | * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. | |
16 | * All Rights Reserved. | |
17 | * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer | |
18 | * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. | |
19 | * | |
20 | * Contributor(s): all the names of the contributors are added in the source code | |
21 | * where applicable. | |
22 | * | |
23 | * Alternatively, the contents of this file may be used under the terms of the | |
24 | * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the | |
25 | * provisions of LGPL are applicable instead of those above. If you wish to | |
26 | * allow use of your version of this file only under the terms of the LGPL | |
27 | * License and not to allow others to use your version of this file under | |
28 | * the MPL, indicate your decision by deleting the provisions above and | |
29 | * replace them with the notice and other provisions required by the LGPL. | |
30 | * If you do not delete the provisions above, a recipient may use your version | |
31 | * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. | |
32 | * | |
33 | * This library is free software; you can redistribute it and/or modify it | |
34 | * under the terms of the MPL as stated above or under the terms of the GNU | |
35 | * Library General Public License as published by the Free Software Foundation; | |
36 | * either version 2 of the License, or any later version. | |
37 | * | |
38 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
39 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
40 | * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more | |
41 | * details. | |
42 | * | |
43 | * If you didn't download this code from the following link, you should check if | |
44 | * you aren't using an obsolete version: | |
45 | * http://www.lowagie.com/iText/ | |
46 | */ | |
47 | ||
48 | package com.lowagie.text.pdf; | |
49 | ||
50 | import java.io.BufferedWriter; | |
51 | import java.io.IOException; | |
52 | import java.io.InputStream; | |
53 | import java.io.OutputStream; | |
54 | import java.io.OutputStreamWriter; | |
55 | import java.io.Reader; | |
56 | import java.io.Writer; | |
57 | import java.util.ArrayList; | |
58 | import java.util.HashMap; | |
59 | import java.util.Iterator; | |
60 | import java.util.List; | |
61 | import java.util.Map; | |
62 | import java.util.Stack; | |
63 | import java.util.StringTokenizer; | |
64 | import com.lowagie.text.error_messages.MessageLocalization; | |
65 | ||
66 | import com.lowagie.text.xml.simpleparser.IanaEncodings; | |
67 | import com.lowagie.text.xml.simpleparser.SimpleXMLDocHandler; | |
68 | import com.lowagie.text.xml.simpleparser.SimpleXMLParser; | |
69 | import com.lowagie.text.xml.XMLUtil; | |
70 | ||
71 | /** | |
72 | * Bookmark processing in a simple way. It has some limitations, mainly the only | |
73 | * action types supported are GoTo, GoToR, URI and Launch. | |
74 | * <p> | |
75 | * The list structure is composed by a number of HashMap, keyed by strings, one HashMap | |
76 | * for each bookmark. | |
77 | * The element values are all strings with the exception of the key "Kids" that has | |
78 | * another list for the child bookmarks. | |
79 | * <p> | |
80 | * All the bookmarks have a "Title" with the | |
81 | * bookmark title and optionally a "Style" that can be "bold", "italic" or a | |
82 | * combination of both. They can also have a "Color" key with a value of three | |
83 | * floats separated by spaces. The key "Open" can have the values "true" or "false" and | |
84 | * signals the open status of the children. It's "true" by default. | |
85 | * <p> | |
86 | * The actions and the parameters can be: | |
87 | * <ul> | |
88 | * <li>"Action" = "GoTo" - "Page" | "Named" | |
89 | * <ul> | |
90 | * <li>"Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted) | |
91 | * <li>"Named" = "named_destination" | |
92 | * </ul> | |
93 | * <li>"Action" = "GoToR" - "Page" | "Named" | "NamedN", "File", ["NewWindow"] | |
94 | * <ul> | |
95 | * <li>"Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted) | |
96 | * <li>"Named" = "named_destination_as_a_string" | |
97 | * <li>"NamedN" = "named_destination_as_a_name" | |
98 | * <li>"File" - "the_file_to_open" | |
99 | * <li>"NewWindow" - "true" or "false" | |
100 | * </ul> | |
101 | * <li>"Action" = "URI" - "URI" | |
102 | * <ul> | |
103 | * <li>"URI" = "http://sf.net" - URI to jump to | |
104 | * </ul> | |
105 | * <li>"Action" = "Launch" - "File" | |
106 | * <ul> | |
107 | * <li>"File" - "the_file_to_open_or_execute" | |
108 | * </ul> | |
109 | * @author Paulo Soares (psoares@consiste.pt) | |
110 | */ | |
111 | public final class SimpleBookmark implements SimpleXMLDocHandler { | |
112 | | |
113 | private List<Map<String, Object>> topList; | |
114 | private Stack<Map<String, Object>> attr = new Stack<>(); | |
115 | | |
116 | /** Creates a new instance of SimpleBookmark */ | |
117 | private SimpleBookmark() { | |
118 | } | |
119 | | |
120 | private static List<Map<String, Object>> bookmarkDepth(PdfReader reader, PdfDictionary outline, IntHashtable pages) { | |
121 | List<Map<String, Object>> list = new ArrayList<>(); | |
122 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
while (outline != null) { |
123 | Map<String, Object> map = new HashMap<>(); | |
124 | PdfString title = (PdfString)PdfReader.getPdfObjectRelease(outline.get(PdfName.TITLE)); | |
125 | map.put("Title", title.toUnicodeString()); | |
126 | PdfArray color = (PdfArray)PdfReader.getPdfObjectRelease(outline.get(PdfName.C)); | |
127 |
2
1. bookmarkDepth : negated conditional → NO_COVERAGE 2. bookmarkDepth : negated conditional → NO_COVERAGE |
if (color != null && color.size() == 3) { |
128 | ByteBuffer out = new ByteBuffer(); | |
129 | out.append(color.getAsNumber(0).floatValue()).append(' '); | |
130 | out.append(color.getAsNumber(1).floatValue()).append(' '); | |
131 | out.append(color.getAsNumber(2).floatValue()); | |
132 | map.put("Color", PdfEncodings.convertToString(out.toByteArray(), null)); | |
133 | } | |
134 | PdfNumber style = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.F)); | |
135 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (style != null) { |
136 | int f = style.intValue(); | |
137 | String s = ""; | |
138 |
2
1. bookmarkDepth : Replaced bitwise AND with OR → NO_COVERAGE 2. bookmarkDepth : negated conditional → NO_COVERAGE |
if ((f & 1) != 0) |
139 | s += "italic "; | |
140 |
2
1. bookmarkDepth : Replaced bitwise AND with OR → NO_COVERAGE 2. bookmarkDepth : negated conditional → NO_COVERAGE |
if ((f & 2) != 0) |
141 | s += "bold "; | |
142 | s = s.trim(); | |
143 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (s.length() != 0) |
144 | map.put("Style", s); | |
145 | } | |
146 | PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.COUNT)); | |
147 |
3
1. bookmarkDepth : changed conditional boundary → NO_COVERAGE 2. bookmarkDepth : negated conditional → NO_COVERAGE 3. bookmarkDepth : negated conditional → NO_COVERAGE |
if (count != null && count.intValue() < 0) |
148 | map.put("Open", "false"); | |
149 | try { | |
150 | PdfObject dest = PdfReader.getPdfObjectRelease(outline.get(PdfName.DEST)); | |
151 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (dest != null) { |
152 |
1
1. bookmarkDepth : removed call to com/lowagie/text/pdf/SimpleBookmark::mapGotoBookmark → NO_COVERAGE |
mapGotoBookmark(map, dest, pages); //changed by ujihara 2004-06-13 |
153 | } | |
154 | else { | |
155 | PdfDictionary action = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.A)); | |
156 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (action != null) { |
157 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (PdfName.GOTO.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) { |
158 | dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D)); | |
159 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (dest != null) { |
160 |
1
1. bookmarkDepth : removed call to com/lowagie/text/pdf/SimpleBookmark::mapGotoBookmark → NO_COVERAGE |
mapGotoBookmark(map, dest, pages); |
161 | } | |
162 | } | |
163 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
else if (PdfName.URI.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) { |
164 | map.put("Action", "URI"); | |
165 | map.put("URI", ((PdfString)PdfReader.getPdfObjectRelease(action.get(PdfName.URI))).toUnicodeString()); | |
166 | } | |
167 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
else if (PdfName.GOTOR.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) { |
168 | dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D)); | |
169 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (dest != null) { |
170 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (dest.isString()) |
171 | map.put("Named", dest.toString()); | |
172 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
else if (dest.isName()) |
173 | map.put("NamedN", PdfName.decodeName(dest.toString())); | |
174 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
else if (dest.isArray()) { |
175 | PdfArray arr = (PdfArray)dest; | |
176 | StringBuilder s = new StringBuilder(); | |
177 | s.append(arr.getPdfObject(0).toString()); | |
178 | s.append(' ').append(arr.getPdfObject(1).toString()); | |
179 |
2
1. bookmarkDepth : changed conditional boundary → NO_COVERAGE 2. bookmarkDepth : negated conditional → NO_COVERAGE |
for (int k = 2; k < arr.size(); ++k) |
180 | s.append(' ').append(arr.getPdfObject(k).toString()); | |
181 | map.put("Page", s.toString()); | |
182 | } | |
183 | } | |
184 | map.put("Action", "GoToR"); | |
185 | PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F)); | |
186 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (file != null) { |
187 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (file.isString()) |
188 | map.put("File", ((PdfString)file).toUnicodeString()); | |
189 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
else if (file.isDictionary()) { |
190 | file = PdfReader.getPdfObject(((PdfDictionary)file).get(PdfName.F)); | |
191 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (file.isString()) |
192 | map.put("File", ((PdfString)file).toUnicodeString()); | |
193 | } | |
194 | } | |
195 | PdfObject newWindow = PdfReader.getPdfObjectRelease(action.get(PdfName.NEWWINDOW)); | |
196 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (newWindow != null) |
197 | map.put("NewWindow", newWindow.toString()); | |
198 | } | |
199 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
else if (PdfName.LAUNCH.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) { |
200 | map.put("Action", "Launch"); | |
201 | PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F)); | |
202 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (file == null) |
203 | file = PdfReader.getPdfObjectRelease(action.get(PdfName.WIN)); | |
204 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (file != null) { |
205 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (file.isString()) |
206 | map.put("File", ((PdfString)file).toUnicodeString()); | |
207 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
else if (file.isDictionary()) { |
208 | file = PdfReader.getPdfObjectRelease(((PdfDictionary)file).get(PdfName.F)); | |
209 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (file.isString()) |
210 | map.put("File", ((PdfString)file).toUnicodeString()); | |
211 | } | |
212 | } | |
213 | } | |
214 | } | |
215 | } | |
216 | } | |
217 | catch (Exception e) { | |
218 | //empty on purpose | |
219 | } | |
220 | PdfDictionary first = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.FIRST)); | |
221 |
1
1. bookmarkDepth : negated conditional → NO_COVERAGE |
if (first != null) { |
222 | map.put("Kids", bookmarkDepth(reader, first, pages)); | |
223 | } | |
224 | list.add(map); | |
225 | outline = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.NEXT)); | |
226 | } | |
227 |
1
1. bookmarkDepth : mutated return of Object value for com/lowagie/text/pdf/SimpleBookmark::bookmarkDepth to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return list; |
228 | } | |
229 | | |
230 | private static void mapGotoBookmark(Map<String, Object> map, PdfObject dest, IntHashtable pages) | |
231 | { | |
232 |
1
1. mapGotoBookmark : negated conditional → NO_COVERAGE |
if (dest.isString()) |
233 | map.put("Named", dest.toString()); | |
234 |
1
1. mapGotoBookmark : negated conditional → NO_COVERAGE |
else if (dest.isName()) |
235 | map.put("Named", PdfName.decodeName(dest.toString())); | |
236 |
1
1. mapGotoBookmark : negated conditional → NO_COVERAGE |
else if (dest.isArray()) |
237 | map.put("Page", makeBookmarkParam((PdfArray)dest, pages)); //changed by ujihara 2004-06-13 | |
238 | map.put("Action", "GoTo"); | |
239 | } | |
240 | ||
241 | private static String makeBookmarkParam(PdfArray dest, IntHashtable pages) | |
242 | { | |
243 | StringBuilder s = new StringBuilder(); | |
244 | PdfObject obj = dest.getPdfObject(0); | |
245 |
1
1. makeBookmarkParam : negated conditional → NO_COVERAGE |
if (obj.isNumber()) |
246 |
1
1. makeBookmarkParam : Replaced integer addition with subtraction → NO_COVERAGE |
s.append(((PdfNumber)obj).intValue() + 1); |
247 | else | |
248 | s.append(pages.get(getNumber((PdfIndirectReference)obj))); //changed by ujihara 2004-06-13 | |
249 | s.append(' ').append(dest.getPdfObject(1).toString().substring(1)); | |
250 |
2
1. makeBookmarkParam : changed conditional boundary → NO_COVERAGE 2. makeBookmarkParam : negated conditional → NO_COVERAGE |
for (int k = 2; k < dest.size(); ++k) |
251 | s.append(' ').append(dest.getPdfObject(k).toString()); | |
252 |
1
1. makeBookmarkParam : mutated return of Object value for com/lowagie/text/pdf/SimpleBookmark::makeBookmarkParam to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return s.toString(); |
253 | } | |
254 | | |
255 | /** | |
256 | * Gets number of indirect. If type of directed indirect is PAGES, it refers PAGE object through KIDS. | |
257 | * (Contributed by Kazuya Ujihara) | |
258 | * @param indirect | |
259 | * 2004-06-13 | |
260 | */ | |
261 | private static int getNumber(PdfIndirectReference indirect) | |
262 | { | |
263 | PdfDictionary pdfObj = (PdfDictionary)PdfReader.getPdfObjectRelease(indirect); | |
264 |
3
1. getNumber : negated conditional → NO_COVERAGE 2. getNumber : negated conditional → NO_COVERAGE 3. getNumber : negated conditional → NO_COVERAGE |
if (pdfObj.contains(PdfName.TYPE) && pdfObj.get(PdfName.TYPE).equals(PdfName.PAGES) && pdfObj.contains(PdfName.KIDS)) |
265 | { | |
266 | PdfArray kids = (PdfArray)pdfObj.get(PdfName.KIDS); | |
267 | indirect = (PdfIndirectReference)kids.getPdfObject(0); | |
268 | } | |
269 |
1
1. getNumber : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return indirect.getNumber(); |
270 | } | |
271 | | |
272 | /** | |
273 | * Gets a <CODE>List</CODE> with the bookmarks. It returns <CODE>null</CODE> if | |
274 | * the document doesn't have any bookmarks. | |
275 | * @param reader the document | |
276 | * @return a <CODE>List</CODE> with the bookmarks or <CODE>null</CODE> if the | |
277 | * document doesn't have any | |
278 | */ | |
279 | public static List<Map<String, Object>> getBookmark(PdfReader reader) { | |
280 | PdfDictionary catalog = reader.getCatalog(); | |
281 | PdfObject obj = PdfReader.getPdfObjectRelease(catalog.get(PdfName.OUTLINES)); | |
282 |
2
1. getBookmark : negated conditional → NO_COVERAGE 2. getBookmark : negated conditional → NO_COVERAGE |
if (obj == null || !obj.isDictionary()) |
283 |
1
1. getBookmark : mutated return of Object value for com/lowagie/text/pdf/SimpleBookmark::getBookmark to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
284 | PdfDictionary outlines = (PdfDictionary)obj; | |
285 | IntHashtable pages = new IntHashtable(); | |
286 | int numPages = reader.getNumberOfPages(); | |
287 |
3
1. getBookmark : changed conditional boundary → NO_COVERAGE 2. getBookmark : Changed increment from 1 to -1 → NO_COVERAGE 3. getBookmark : negated conditional → NO_COVERAGE |
for (int k = 1; k <= numPages; ++k) { |
288 | pages.put(reader.getPageOrigRef(k).getNumber(), k); | |
289 |
1
1. getBookmark : removed call to com/lowagie/text/pdf/PdfReader::releasePage → NO_COVERAGE |
reader.releasePage(k); |
290 | } | |
291 |
1
1. getBookmark : mutated return of Object value for com/lowagie/text/pdf/SimpleBookmark::getBookmark to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return bookmarkDepth(reader, (PdfDictionary)PdfReader.getPdfObjectRelease(outlines.get(PdfName.FIRST)), pages); |
292 | } | |
293 | | |
294 | /** | |
295 | * Removes the bookmark entries for a number of page ranges. The page ranges | |
296 | * consists of a number of pairs with the start/end page range. The page numbers | |
297 | * are inclusive. | |
298 | * @param list the bookmarks | |
299 | * @param pageRange the page ranges, always in pairs. | |
300 | */ | |
301 | public static void eliminatePages(List list, int[] pageRange) { | |
302 |
1
1. eliminatePages : negated conditional → NO_COVERAGE |
if (list == null) |
303 | return; | |
304 |
1
1. eliminatePages : negated conditional → NO_COVERAGE |
for (Iterator it = list.listIterator(); it.hasNext();) { |
305 | HashMap map = (HashMap)it.next(); | |
306 | boolean hit = false; | |
307 |
1
1. eliminatePages : negated conditional → NO_COVERAGE |
if ("GoTo".equals(map.get("Action"))) { |
308 | String page = (String)map.get("Page"); | |
309 |
1
1. eliminatePages : negated conditional → NO_COVERAGE |
if (page != null) { |
310 | page = page.trim(); | |
311 | int idx = page.indexOf(' '); | |
312 | int pageNum; | |
313 |
2
1. eliminatePages : changed conditional boundary → NO_COVERAGE 2. eliminatePages : negated conditional → NO_COVERAGE |
if (idx < 0) |
314 | pageNum = Integer.parseInt(page); | |
315 | else | |
316 | pageNum = Integer.parseInt(page.substring(0, idx)); | |
317 |
1
1. eliminatePages : Replaced bitwise AND with OR → NO_COVERAGE |
int len = pageRange.length & 0xfffffffe; |
318 |
3
1. eliminatePages : changed conditional boundary → NO_COVERAGE 2. eliminatePages : Changed increment from 2 to -2 → NO_COVERAGE 3. eliminatePages : negated conditional → NO_COVERAGE |
for (int k = 0; k < len; k += 2) { |
319 |
5
1. eliminatePages : changed conditional boundary → NO_COVERAGE 2. eliminatePages : changed conditional boundary → NO_COVERAGE 3. eliminatePages : Replaced integer addition with subtraction → NO_COVERAGE 4. eliminatePages : negated conditional → NO_COVERAGE 5. eliminatePages : negated conditional → NO_COVERAGE |
if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) { |
320 | hit = true; | |
321 | break; | |
322 | } | |
323 | } | |
324 | } | |
325 | } | |
326 | List kids = (List)map.get("Kids"); | |
327 |
1
1. eliminatePages : negated conditional → NO_COVERAGE |
if (kids != null) { |
328 |
1
1. eliminatePages : removed call to com/lowagie/text/pdf/SimpleBookmark::eliminatePages → NO_COVERAGE |
eliminatePages(kids, pageRange); |
329 |
1
1. eliminatePages : negated conditional → NO_COVERAGE |
if (kids.isEmpty()) { |
330 | map.remove("Kids"); | |
331 | kids = null; | |
332 | } | |
333 | } | |
334 |
1
1. eliminatePages : negated conditional → NO_COVERAGE |
if (hit) { |
335 |
1
1. eliminatePages : negated conditional → NO_COVERAGE |
if (kids == null) |
336 |
1
1. eliminatePages : removed call to java/util/Iterator::remove → NO_COVERAGE |
it.remove(); |
337 | else { | |
338 | map.remove("Action"); | |
339 | map.remove("Page"); | |
340 | map.remove("Named"); | |
341 | } | |
342 | } | |
343 | } | |
344 | } | |
345 | | |
346 | /** | |
347 | * For the pages in range add the <CODE>pageShift</CODE> to the page number. | |
348 | * The page ranges | |
349 | * consists of a number of pairs with the start/end page range. The page numbers | |
350 | * are inclusive. | |
351 | * @param list the bookmarks | |
352 | * @param pageShift the number to add to the pages in range | |
353 | * @param pageRange the page ranges, always in pairs. It can be <CODE>null</CODE> | |
354 | * to include all the pages | |
355 | */ | |
356 | public static void shiftPageNumbers(List<Map<String, Object>> list, int pageShift, int[] pageRange) { | |
357 |
1
1. shiftPageNumbers : negated conditional → NO_COVERAGE |
if (list == null) |
358 | return; | |
359 | for (Map<String, Object> map : list) { | |
360 |
1
1. shiftPageNumbers : negated conditional → NO_COVERAGE |
if ("GoTo".equals(map.get("Action"))) { |
361 | String page = (String) map.get("Page"); | |
362 |
1
1. shiftPageNumbers : negated conditional → NO_COVERAGE |
if (page != null) { |
363 | page = page.trim(); | |
364 | int idx = page.indexOf(' '); | |
365 | int pageNum; | |
366 |
2
1. shiftPageNumbers : changed conditional boundary → NO_COVERAGE 2. shiftPageNumbers : negated conditional → NO_COVERAGE |
if (idx < 0) |
367 | pageNum = Integer.parseInt(page); | |
368 | else | |
369 | pageNum = Integer.parseInt(page.substring(0, idx)); | |
370 | boolean hit = false; | |
371 |
1
1. shiftPageNumbers : negated conditional → NO_COVERAGE |
if (pageRange == null) |
372 | hit = true; | |
373 | else { | |
374 |
1
1. shiftPageNumbers : Replaced bitwise AND with OR → NO_COVERAGE |
int len = pageRange.length & 0xfffffffe; |
375 |
3
1. shiftPageNumbers : changed conditional boundary → NO_COVERAGE 2. shiftPageNumbers : Changed increment from 2 to -2 → NO_COVERAGE 3. shiftPageNumbers : negated conditional → NO_COVERAGE |
for (int k = 0; k < len; k += 2) { |
376 |
5
1. shiftPageNumbers : changed conditional boundary → NO_COVERAGE 2. shiftPageNumbers : changed conditional boundary → NO_COVERAGE 3. shiftPageNumbers : Replaced integer addition with subtraction → NO_COVERAGE 4. shiftPageNumbers : negated conditional → NO_COVERAGE 5. shiftPageNumbers : negated conditional → NO_COVERAGE |
if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) { |
377 | hit = true; | |
378 | break; | |
379 | } | |
380 | } | |
381 | } | |
382 |
1
1. shiftPageNumbers : negated conditional → NO_COVERAGE |
if (hit) { |
383 |
2
1. shiftPageNumbers : changed conditional boundary → NO_COVERAGE 2. shiftPageNumbers : negated conditional → NO_COVERAGE |
if (idx < 0) |
384 |
1
1. shiftPageNumbers : Replaced integer addition with subtraction → NO_COVERAGE |
page = Integer.toString(pageNum + pageShift); |
385 | else | |
386 |
1
1. shiftPageNumbers : Replaced integer addition with subtraction → NO_COVERAGE |
page = (pageNum + pageShift) + page.substring(idx); |
387 | } | |
388 | map.put("Page", page); | |
389 | } | |
390 | } | |
391 | List<Map<String, Object>> kids = (List<Map<String, Object>>) map.get("Kids"); | |
392 |
1
1. shiftPageNumbers : negated conditional → NO_COVERAGE |
if (kids != null) |
393 |
1
1. shiftPageNumbers : removed call to com/lowagie/text/pdf/SimpleBookmark::shiftPageNumbers → NO_COVERAGE |
shiftPageNumbers(kids, pageShift, pageRange); |
394 | } | |
395 | } | |
396 | | |
397 | static void createOutlineAction(PdfDictionary outline, HashMap map, PdfWriter writer, boolean namedAsNames) { | |
398 | try { | |
399 | String action = (String)map.get("Action"); | |
400 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if ("GoTo".equals(action)) { |
401 | String p; | |
402 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if ((p = (String)map.get("Named")) != null) { |
403 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (namedAsNames) |
404 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.DEST, new PdfName(p)); |
405 | else | |
406 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.DEST, new PdfString(p, null)); |
407 | } | |
408 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
else if ((p = (String)map.get("Page")) != null) { |
409 | PdfArray ar = new PdfArray(); | |
410 | StringTokenizer tk = new StringTokenizer(p); | |
411 | int n = Integer.parseInt(tk.nextToken()); | |
412 | ar.add(writer.getPageReference(n)); | |
413 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (!tk.hasMoreTokens()) { |
414 | ar.add(PdfName.XYZ); | |
415 | ar.add(new float[]{0, 10000, 0}); | |
416 | } | |
417 | else { | |
418 | String fn = tk.nextToken(); | |
419 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (fn.startsWith("/")) |
420 | fn = fn.substring(1); | |
421 | ar.add(new PdfName(fn)); | |
422 |
4
1. createOutlineAction : changed conditional boundary → NO_COVERAGE 2. createOutlineAction : Changed increment from 1 to -1 → NO_COVERAGE 3. createOutlineAction : negated conditional → NO_COVERAGE 4. createOutlineAction : negated conditional → NO_COVERAGE |
for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) { |
423 | fn = tk.nextToken(); | |
424 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (fn.equals("null")) |
425 | ar.add(PdfNull.PDFNULL); | |
426 | else | |
427 | ar.add(new PdfNumber(fn)); | |
428 | } | |
429 | } | |
430 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.DEST, ar); |
431 | } | |
432 | } | |
433 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
else if ("GoToR".equals(action)) { |
434 | String p; | |
435 | PdfDictionary dic = new PdfDictionary(); | |
436 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if ((p = (String)map.get("Named")) != null) |
437 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.D, new PdfString(p, null)); |
438 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
else if ((p = (String)map.get("NamedN")) != null) |
439 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.D, new PdfName(p)); |
440 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
else if ((p = (String)map.get("Page")) != null){ |
441 | PdfArray ar = new PdfArray(); | |
442 | StringTokenizer tk = new StringTokenizer(p); | |
443 | ar.add(new PdfNumber(tk.nextToken())); | |
444 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (!tk.hasMoreTokens()) { |
445 | ar.add(PdfName.XYZ); | |
446 | ar.add(new float[]{0, 10000, 0}); | |
447 | } | |
448 | else { | |
449 | String fn = tk.nextToken(); | |
450 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (fn.startsWith("/")) |
451 | fn = fn.substring(1); | |
452 | ar.add(new PdfName(fn)); | |
453 |
4
1. createOutlineAction : changed conditional boundary → NO_COVERAGE 2. createOutlineAction : Changed increment from 1 to -1 → NO_COVERAGE 3. createOutlineAction : negated conditional → NO_COVERAGE 4. createOutlineAction : negated conditional → NO_COVERAGE |
for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) { |
454 | fn = tk.nextToken(); | |
455 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (fn.equals("null")) |
456 | ar.add(PdfNull.PDFNULL); | |
457 | else | |
458 | ar.add(new PdfNumber(fn)); | |
459 | } | |
460 | } | |
461 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.D, ar); |
462 | } | |
463 | String file = (String)map.get("File"); | |
464 |
3
1. createOutlineAction : changed conditional boundary → NO_COVERAGE 2. createOutlineAction : negated conditional → NO_COVERAGE 3. createOutlineAction : negated conditional → NO_COVERAGE |
if (dic.size() > 0 && file != null) { |
465 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.S, PdfName.GOTOR); |
466 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.F, new PdfString(file)); |
467 | String nw = (String)map.get("NewWindow"); | |
468 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (nw != null) { |
469 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (nw.equals("true")) |
470 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE); |
471 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
else if (nw.equals("false")) |
472 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFFALSE); |
473 | } | |
474 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.A, dic); |
475 | } | |
476 | } | |
477 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
else if ("URI".equals(action)) { |
478 | String uri = (String)map.get("URI"); | |
479 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (uri != null) { |
480 | PdfDictionary dic = new PdfDictionary(); | |
481 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.S, PdfName.URI); |
482 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.URI, new PdfString(uri)); |
483 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.A, dic); |
484 | } | |
485 | } | |
486 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
else if ("Launch".equals(action)) { |
487 | String file = (String)map.get("File"); | |
488 |
1
1. createOutlineAction : negated conditional → NO_COVERAGE |
if (file != null) { |
489 | PdfDictionary dic = new PdfDictionary(); | |
490 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.S, PdfName.LAUNCH); |
491 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
dic.put(PdfName.F, new PdfString(file)); |
492 |
1
1. createOutlineAction : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.A, dic); |
493 | } | |
494 | } | |
495 | } | |
496 | catch (Exception e) { | |
497 | // empty on purpose | |
498 | } | |
499 | } | |
500 | ||
501 | public static Object[] iterateOutlines(PdfWriter writer, PdfIndirectReference parent, List kids, boolean namedAsNames) throws IOException { | |
502 | PdfIndirectReference[] refs = new PdfIndirectReference[kids.size()]; | |
503 |
2
1. iterateOutlines : changed conditional boundary → NO_COVERAGE 2. iterateOutlines : negated conditional → NO_COVERAGE |
for (int k = 0; k < refs.length; ++k) |
504 | refs[k] = writer.getPdfIndirectReference(); | |
505 | int ptr = 0; | |
506 | int count = 0; | |
507 |
2
1. iterateOutlines : Changed increment from 1 to -1 → NO_COVERAGE 2. iterateOutlines : negated conditional → NO_COVERAGE |
for (Iterator it = kids.listIterator(); it.hasNext(); ++ptr) { |
508 | HashMap map = (HashMap)it.next(); | |
509 | Object[] lower = null; | |
510 | List subKid = (List)map.get("Kids"); | |
511 |
2
1. iterateOutlines : negated conditional → NO_COVERAGE 2. iterateOutlines : negated conditional → NO_COVERAGE |
if (subKid != null && !subKid.isEmpty()) |
512 | lower = iterateOutlines(writer, refs[ptr], subKid, namedAsNames); | |
513 | PdfDictionary outline = new PdfDictionary(); | |
514 |
1
1. iterateOutlines : Changed increment from 1 to -1 → NO_COVERAGE |
++count; |
515 |
1
1. iterateOutlines : negated conditional → NO_COVERAGE |
if (lower != null) { |
516 |
1
1. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.FIRST, (PdfIndirectReference)lower[0]); |
517 |
1
1. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.LAST, (PdfIndirectReference)lower[1]); |
518 | int n = (Integer) lower[2]; | |
519 |
1
1. iterateOutlines : negated conditional → NO_COVERAGE |
if ("false".equals(map.get("Open"))) { |
520 |
2
1. iterateOutlines : removed negation → NO_COVERAGE 2. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.COUNT, new PdfNumber(-n)); |
521 | } | |
522 | else { | |
523 |
1
1. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.COUNT, new PdfNumber(n)); |
524 |
1
1. iterateOutlines : Replaced integer addition with subtraction → NO_COVERAGE |
count += n; |
525 | } | |
526 | } | |
527 |
1
1. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.PARENT, parent); |
528 |
2
1. iterateOutlines : changed conditional boundary → NO_COVERAGE 2. iterateOutlines : negated conditional → NO_COVERAGE |
if (ptr > 0) |
529 |
2
1. iterateOutlines : Replaced integer subtraction with addition → NO_COVERAGE 2. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.PREV, refs[ptr - 1]); |
530 |
3
1. iterateOutlines : changed conditional boundary → NO_COVERAGE 2. iterateOutlines : Replaced integer subtraction with addition → NO_COVERAGE 3. iterateOutlines : negated conditional → NO_COVERAGE |
if (ptr < refs.length - 1) |
531 |
2
1. iterateOutlines : Replaced integer addition with subtraction → NO_COVERAGE 2. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.NEXT, refs[ptr + 1]); |
532 |
1
1. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.TITLE, new PdfString((String)map.get("Title"), PdfObject.TEXT_UNICODE)); |
533 | String color = (String)map.get("Color"); | |
534 |
1
1. iterateOutlines : negated conditional → NO_COVERAGE |
if (color != null) { |
535 | try { | |
536 | PdfArray arr = new PdfArray(); | |
537 | StringTokenizer tk = new StringTokenizer(color); | |
538 |
3
1. iterateOutlines : changed conditional boundary → NO_COVERAGE 2. iterateOutlines : Changed increment from 1 to -1 → NO_COVERAGE 3. iterateOutlines : negated conditional → NO_COVERAGE |
for (int k = 0; k < 3; ++k) { |
539 | float f = Float.parseFloat(tk.nextToken()); | |
540 |
2
1. iterateOutlines : changed conditional boundary → NO_COVERAGE 2. iterateOutlines : negated conditional → NO_COVERAGE |
if (f < 0) f = 0; |
541 |
2
1. iterateOutlines : changed conditional boundary → NO_COVERAGE 2. iterateOutlines : negated conditional → NO_COVERAGE |
if (f > 1) f = 1; |
542 | arr.add(new PdfNumber(f)); | |
543 | } | |
544 |
1
1. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.C, arr); |
545 | } catch(Exception e){} //in case it's malformed | |
546 | } | |
547 | String style = (String)map.get("Style"); | |
548 |
1
1. iterateOutlines : negated conditional → NO_COVERAGE |
if (style != null) { |
549 | style = style.toLowerCase(); | |
550 | int bits = 0; | |
551 |
1
1. iterateOutlines : negated conditional → NO_COVERAGE |
if (style.contains("italic")) |
552 |
1
1. iterateOutlines : Replaced bitwise OR with AND → NO_COVERAGE |
bits |= 1; |
553 |
1
1. iterateOutlines : negated conditional → NO_COVERAGE |
if (style.contains("bold")) |
554 |
1
1. iterateOutlines : Replaced bitwise OR with AND → NO_COVERAGE |
bits |= 2; |
555 |
1
1. iterateOutlines : negated conditional → NO_COVERAGE |
if (bits != 0) |
556 |
1
1. iterateOutlines : removed call to com/lowagie/text/pdf/PdfDictionary::put → NO_COVERAGE |
outline.put(PdfName.F, new PdfNumber(bits)); |
557 | } | |
558 |
1
1. iterateOutlines : removed call to com/lowagie/text/pdf/SimpleBookmark::createOutlineAction → NO_COVERAGE |
createOutlineAction(outline, map, writer, namedAsNames); |
559 | writer.addToBody(outline, refs[ptr]); | |
560 | } | |
561 |
2
1. iterateOutlines : Replaced integer subtraction with addition → NO_COVERAGE 2. iterateOutlines : mutated return of Object value for com/lowagie/text/pdf/SimpleBookmark::iterateOutlines to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return new Object[]{refs[0], refs[refs.length - 1], count}; |
562 | } | |
563 | ||
564 | /** | |
565 | * Exports the bookmarks to XML. Only of use if the generation is to be include in | |
566 | * some other XML document. | |
567 | * @param list the bookmarks | |
568 | * @param out the export destination. The writer is not closed | |
569 | * @param indent the indentation level. Pretty printing significant only | |
570 | * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>, | |
571 | * whatever the encoding | |
572 | * @throws IOException on error | |
573 | */ | |
574 | public static void exportToXMLNode(List list, Writer out, int indent, boolean onlyASCII) throws IOException { | |
575 | String dep = ""; | |
576 |
3
1. exportToXMLNode : changed conditional boundary → NO_COVERAGE 2. exportToXMLNode : Changed increment from 1 to -1 → NO_COVERAGE 3. exportToXMLNode : negated conditional → NO_COVERAGE |
for (int k = 0; k < indent; ++k) |
577 | dep += " "; | |
578 | for (Object o1 : list) { | |
579 | HashMap map = (HashMap) o1; | |
580 | String title = null; | |
581 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write(dep); |
582 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write("<Title "); |
583 | List kids = null; | |
584 | for (Object o : map.entrySet()) { | |
585 | Map.Entry entry = (Map.Entry) o; | |
586 | String key = (String) entry.getKey(); | |
587 |
1
1. exportToXMLNode : negated conditional → NO_COVERAGE |
if (key.equals("Title")) { |
588 | title = (String) entry.getValue(); | |
589 | continue; | |
590 |
1
1. exportToXMLNode : negated conditional → NO_COVERAGE |
} else if (key.equals("Kids")) { |
591 | kids = (List) entry.getValue(); | |
592 | continue; | |
593 | } else { | |
594 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write(key); |
595 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write("=\""); |
596 | String value = (String) entry.getValue(); | |
597 |
2
1. exportToXMLNode : negated conditional → NO_COVERAGE 2. exportToXMLNode : negated conditional → NO_COVERAGE |
if (key.equals("Named") || key.equals("NamedN")) |
598 | value = SimpleNamedDestination.escapeBinaryString(value); | |
599 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write(XMLUtil.escapeXML(value, onlyASCII)); |
600 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write("\" "); |
601 | } | |
602 | } | |
603 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write(">"); |
604 |
1
1. exportToXMLNode : negated conditional → NO_COVERAGE |
if (title == null) |
605 | title = ""; | |
606 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write(XMLUtil.escapeXML(title, onlyASCII)); |
607 |
1
1. exportToXMLNode : negated conditional → NO_COVERAGE |
if (kids != null) { |
608 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write("\n"); |
609 |
2
1. exportToXMLNode : Replaced integer addition with subtraction → NO_COVERAGE 2. exportToXMLNode : removed call to com/lowagie/text/pdf/SimpleBookmark::exportToXMLNode → NO_COVERAGE |
exportToXMLNode(kids, out, indent + 1, onlyASCII); |
610 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write(dep); |
611 | } | |
612 |
1
1. exportToXMLNode : removed call to java/io/Writer::write → NO_COVERAGE |
out.write("</Title>\n"); |
613 | } | |
614 | } | |
615 | ||
616 | /** | |
617 | * Exports the bookmarks to XML. The DTD for this XML is: | |
618 | * <p> | |
619 | * <pre> | |
620 | * <?xml version='1.0' encoding='UTF-8'?> | |
621 | * <!ELEMENT Title (#PCDATA|Title)*> | |
622 | * <!ATTLIST Title | |
623 | * Action CDATA #IMPLIED | |
624 | * Open CDATA #IMPLIED | |
625 | * Page CDATA #IMPLIED | |
626 | * URI CDATA #IMPLIED | |
627 | * File CDATA #IMPLIED | |
628 | * Named CDATA #IMPLIED | |
629 | * NamedN CDATA #IMPLIED | |
630 | * NewWindow CDATA #IMPLIED | |
631 | * Style CDATA #IMPLIED | |
632 | * Color CDATA #IMPLIED | |
633 | * > | |
634 | * <!ELEMENT Bookmark (Title)*> | |
635 | * </pre> | |
636 | * @param list the bookmarks | |
637 | * @param out the export destination. The stream is not closed | |
638 | * @param encoding the encoding according to IANA conventions | |
639 | * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>, | |
640 | * whatever the encoding | |
641 | * @throws IOException on error | |
642 | */ | |
643 | public static void exportToXML(List list, OutputStream out, String encoding, boolean onlyASCII) throws IOException { | |
644 | String jenc = IanaEncodings.getJavaEncoding(encoding); | |
645 | Writer wrt = new BufferedWriter(new OutputStreamWriter(out, jenc)); | |
646 |
1
1. exportToXML : removed call to com/lowagie/text/pdf/SimpleBookmark::exportToXML → NO_COVERAGE |
exportToXML(list, wrt, encoding, onlyASCII); |
647 | } | |
648 | ||
649 | /** | |
650 | * Exports the bookmarks to XML. | |
651 | * @param list the bookmarks | |
652 | * @param wrt the export destination. The writer is not closed | |
653 | * @param encoding the encoding according to IANA conventions | |
654 | * @param onlyASCII codes above 127 will always be escaped with &#nn; if <CODE>true</CODE>, | |
655 | * whatever the encoding | |
656 | * @throws IOException on error | |
657 | */ | |
658 | public static void exportToXML(List list, Writer wrt, String encoding, boolean onlyASCII) throws IOException { | |
659 |
1
1. exportToXML : removed call to java/io/Writer::write → NO_COVERAGE |
wrt.write("<?xml version=\"1.0\" encoding=\""); |
660 |
1
1. exportToXML : removed call to java/io/Writer::write → NO_COVERAGE |
wrt.write(XMLUtil.escapeXML(encoding, onlyASCII)); |
661 |
1
1. exportToXML : removed call to java/io/Writer::write → NO_COVERAGE |
wrt.write("\"?>\n<Bookmark>\n"); |
662 |
1
1. exportToXML : removed call to com/lowagie/text/pdf/SimpleBookmark::exportToXMLNode → NO_COVERAGE |
exportToXMLNode(list, wrt, 1, onlyASCII); |
663 |
1
1. exportToXML : removed call to java/io/Writer::write → NO_COVERAGE |
wrt.write("</Bookmark>\n"); |
664 |
1
1. exportToXML : removed call to java/io/Writer::flush → NO_COVERAGE |
wrt.flush(); |
665 | } | |
666 | ||
667 | /** | |
668 | * Import the bookmarks from XML. | |
669 | * @param in the XML source. The stream is not closed | |
670 | * @throws IOException on error | |
671 | * @return the bookmarks | |
672 | */ | |
673 | public static List importFromXML(InputStream in) throws IOException { | |
674 | SimpleBookmark book = new SimpleBookmark(); | |
675 |
1
1. importFromXML : removed call to com/lowagie/text/xml/simpleparser/SimpleXMLParser::parse → NO_COVERAGE |
SimpleXMLParser.parse(book, in); |
676 |
1
1. importFromXML : mutated return of Object value for com/lowagie/text/pdf/SimpleBookmark::importFromXML to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return book.topList; |
677 | } | |
678 | ||
679 | /** | |
680 | * Import the bookmarks from XML. | |
681 | * @param in the XML source. The reader is not closed | |
682 | * @throws IOException on error | |
683 | * @return the bookmarks | |
684 | */ | |
685 | public static List importFromXML(Reader in) throws IOException { | |
686 | SimpleBookmark book = new SimpleBookmark(); | |
687 |
1
1. importFromXML : removed call to com/lowagie/text/xml/simpleparser/SimpleXMLParser::parse → NO_COVERAGE |
SimpleXMLParser.parse(book, in); |
688 |
1
1. importFromXML : mutated return of Object value for com/lowagie/text/pdf/SimpleBookmark::importFromXML to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return book.topList; |
689 | } | |
690 | ||
691 | public void endDocument() { | |
692 | } | |
693 | ||
694 | public void endElement(String tag) { | |
695 |
1
1. endElement : negated conditional → NO_COVERAGE |
if (tag.equals("Bookmark")) { |
696 |
1
1. endElement : negated conditional → NO_COVERAGE |
if (attr.isEmpty()) |
697 | return; | |
698 | else | |
699 | throw new RuntimeException(MessageLocalization.getComposedMessage("bookmark.end.tag.out.of.place")); | |
700 | } | |
701 |
1
1. endElement : negated conditional → NO_COVERAGE |
if (!tag.equals("Title")) |
702 | throw new RuntimeException(MessageLocalization.getComposedMessage("invalid.end.tag.1", tag)); | |
703 | Map<String, Object> attributes = attr.pop(); | |
704 | String title = (String) attributes.get("Title"); | |
705 | attributes.put("Title", title.trim()); | |
706 | String named = (String) attributes.get("Named"); | |
707 |
1
1. endElement : negated conditional → NO_COVERAGE |
if (named != null) |
708 | attributes.put("Named", SimpleNamedDestination.unEscapeBinaryString(named)); | |
709 | named = (String) attributes.get("NamedN"); | |
710 |
1
1. endElement : negated conditional → NO_COVERAGE |
if (named != null) |
711 | attributes.put("NamedN", SimpleNamedDestination.unEscapeBinaryString(named)); | |
712 |
1
1. endElement : negated conditional → NO_COVERAGE |
if (attr.isEmpty()) |
713 | topList.add(attributes); | |
714 | else { | |
715 | Map<String, Object> parent = attr.peek(); | |
716 | List<Map<String, Object>> kids = (List<Map<String, Object>>) parent.get("Kids"); | |
717 |
1
1. endElement : negated conditional → NO_COVERAGE |
if (kids == null) { |
718 | kids = new ArrayList<>(); | |
719 | parent.put("Kids", kids); | |
720 | } | |
721 | kids.add(attributes); | |
722 | } | |
723 | } | |
724 | ||
725 | public void startDocument() { | |
726 | } | |
727 | ||
728 | public void startElement(String tag, Map<String, String> h) { | |
729 |
1
1. startElement : negated conditional → NO_COVERAGE |
if (topList == null) { |
730 |
1
1. startElement : negated conditional → NO_COVERAGE |
if (tag.equals("Bookmark")) { |
731 | topList = new ArrayList<>(); | |
732 | return; | |
733 | } | |
734 | else | |
735 | throw new RuntimeException(MessageLocalization.getComposedMessage("root.element.is.not.bookmark.1", tag)); | |
736 | } | |
737 |
1
1. startElement : negated conditional → NO_COVERAGE |
if (!tag.equals("Title")) |
738 | throw new RuntimeException(MessageLocalization.getComposedMessage("tag.1.not.allowed", tag)); | |
739 | Map<String, Object> attributes = new HashMap<>(h); | |
740 | attributes.put("Title", ""); | |
741 | attributes.remove("Kids"); | |
742 | attr.push(attributes); | |
743 | } | |
744 | ||
745 | public void text(String str) { | |
746 |
1
1. text : negated conditional → NO_COVERAGE |
if (attr.isEmpty()) |
747 | return; | |
748 | Map<String, Object> attributes = attr.peek(); | |
749 | String title = (String) attributes.get("Title"); | |
750 | title += str; | |
751 | attributes.put("Title", title); | |
752 | } | |
753 | } | |
Mutations | ||
122 |
1.1 |
|
127 |
1.1 2.2 |
|
135 |
1.1 |
|
138 |
1.1 2.2 |
|
140 |
1.1 2.2 |
|
143 |
1.1 |
|
147 |
1.1 2.2 3.3 |
|
151 |
1.1 |
|
152 |
1.1 |
|
156 |
1.1 |
|
157 |
1.1 |
|
159 |
1.1 |
|
160 |
1.1 |
|
163 |
1.1 |
|
167 |
1.1 |
|
169 |
1.1 |
|
170 |
1.1 |
|
172 |
1.1 |
|
174 |
1.1 |
|
179 |
1.1 2.2 |
|
186 |
1.1 |
|
187 |
1.1 |
|
189 |
1.1 |
|
191 |
1.1 |
|
196 |
1.1 |
|
199 |
1.1 |
|
202 |
1.1 |
|
204 |
1.1 |
|
205 |
1.1 |
|
207 |
1.1 |
|
209 |
1.1 |
|
221 |
1.1 |
|
227 |
1.1 |
|
232 |
1.1 |
|
234 |
1.1 |
|
236 |
1.1 |
|
245 |
1.1 |
|
246 |
1.1 |
|
250 |
1.1 2.2 |
|
252 |
1.1 |
|
264 |
1.1 2.2 3.3 |
|
269 |
1.1 |
|
282 |
1.1 2.2 |
|
283 |
1.1 |
|
287 |
1.1 2.2 3.3 |
|
289 |
1.1 |
|
291 |
1.1 |
|
302 |
1.1 |
|
304 |
1.1 |
|
307 |
1.1 |
|
309 |
1.1 |
|
313 |
1.1 2.2 |
|
317 |
1.1 |
|
318 |
1.1 2.2 3.3 |
|
319 |
1.1 2.2 3.3 4.4 5.5 |
|
327 |
1.1 |
|
328 |
1.1 |
|
329 |
1.1 |
|
334 |
1.1 |
|
335 |
1.1 |
|
336 |
1.1 |
|
357 |
1.1 |
|
360 |
1.1 |
|
362 |
1.1 |
|
366 |
1.1 2.2 |
|
371 |
1.1 |
|
374 |
1.1 |
|
375 |
1.1 2.2 3.3 |
|
376 |
1.1 2.2 3.3 4.4 5.5 |
|
382 |
1.1 |
|
383 |
1.1 2.2 |
|
384 |
1.1 |
|
386 |
1.1 |
|
392 |
1.1 |
|
393 |
1.1 |
|
400 |
1.1 |
|
402 |
1.1 |
|
403 |
1.1 |
|
404 |
1.1 |
|
406 |
1.1 |
|
408 |
1.1 |
|
413 |
1.1 |
|
419 |
1.1 |
|
422 |
1.1 2.2 3.3 4.4 |
|
424 |
1.1 |
|
430 |
1.1 |
|
433 |
1.1 |
|
436 |
1.1 |
|
437 |
1.1 |
|
438 |
1.1 |
|
439 |
1.1 |
|
440 |
1.1 |
|
444 |
1.1 |
|
450 |
1.1 |
|
453 |
1.1 2.2 3.3 4.4 |
|
455 |
1.1 |
|
461 |
1.1 |
|
464 |
1.1 2.2 3.3 |
|
465 |
1.1 |
|
466 |
1.1 |
|
468 |
1.1 |
|
469 |
1.1 |
|
470 |
1.1 |
|
471 |
1.1 |
|
472 |
1.1 |
|
474 |
1.1 |
|
477 |
1.1 |
|
479 |
1.1 |
|
481 |
1.1 |
|
482 |
1.1 |
|
483 |
1.1 |
|
486 |
1.1 |
|
488 |
1.1 |
|
490 |
1.1 |
|
491 |
1.1 |
|
492 |
1.1 |
|
503 |
1.1 2.2 |
|
507 |
1.1 2.2 |
|
511 |
1.1 2.2 |
|
514 |
1.1 |
|
515 |
1.1 |
|
516 |
1.1 |
|
517 |
1.1 |
|
519 |
1.1 |
|
520 |
1.1 2.2 |
|
523 |
1.1 |
|
524 |
1.1 |
|
527 |
1.1 |
|
528 |
1.1 2.2 |
|
529 |
1.1 2.2 |
|
530 |
1.1 2.2 3.3 |
|
531 |
1.1 2.2 |
|
532 |
1.1 |
|
534 |
1.1 |
|
538 |
1.1 2.2 3.3 |
|
540 |
1.1 2.2 |
|
541 |
1.1 2.2 |
|
544 |
1.1 |
|
548 |
1.1 |
|
551 |
1.1 |
|
552 |
1.1 |
|
553 |
1.1 |
|
554 |
1.1 |
|
555 |
1.1 |
|
556 |
1.1 |
|
558 |
1.1 |
|
561 |
1.1 2.2 |
|
576 |
1.1 2.2 3.3 |
|
581 |
1.1 |
|
582 |
1.1 |
|
587 |
1.1 |
|
590 |
1.1 |
|
594 |
1.1 |
|
595 |
1.1 |
|
597 |
1.1 2.2 |
|
599 |
1.1 |
|
600 |
1.1 |
|
603 |
1.1 |
|
604 |
1.1 |
|
606 |
1.1 |
|
607 |
1.1 |
|
608 |
1.1 |
|
609 |
1.1 2.2 |
|
610 |
1.1 |
|
612 |
1.1 |
|
646 |
1.1 |
|
659 |
1.1 |
|
660 |
1.1 |
|
661 |
1.1 |
|
662 |
1.1 |
|
663 |
1.1 |
|
664 |
1.1 |
|
675 |
1.1 |
|
676 |
1.1 |
|
687 |
1.1 |
|
688 |
1.1 |
|
695 |
1.1 |
|
696 |
1.1 |
|
701 |
1.1 |
|
707 |
1.1 |
|
710 |
1.1 |
|
712 |
1.1 |
|
717 |
1.1 |
|
729 |
1.1 |
|
730 |
1.1 |
|
737 |
1.1 |
|
746 |
1.1 |