1 | /* | |
2 | * $Id: Row.java 4065 2009-09-16 23:09:11Z psoares33 $ | |
3 | * $Name$ | |
4 | * | |
5 | * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie. | |
6 | * | |
7 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
8 | * (the "License"); you may not use this file except in compliance with the License. | |
9 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
10 | * | |
11 | * Software distributed under the License is distributed on an "AS IS" basis, | |
12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
13 | * for the specific language governing rights and limitations under the License. | |
14 | * | |
15 | * The Original Code is 'iText, a free JAVA-PDF library'. | |
16 | * | |
17 | * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by | |
18 | * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. | |
19 | * All Rights Reserved. | |
20 | * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer | |
21 | * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. | |
22 | * | |
23 | * Contributor(s): all the names of the contributors are added in the source code | |
24 | * where applicable. | |
25 | * | |
26 | * Alternatively, the contents of this file may be used under the terms of the | |
27 | * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the | |
28 | * provisions of LGPL are applicable instead of those above. If you wish to | |
29 | * allow use of your version of this file only under the terms of the LGPL | |
30 | * License and not to allow others to use your version of this file under | |
31 | * the MPL, indicate your decision by deleting the provisions above and | |
32 | * replace them with the notice and other provisions required by the LGPL. | |
33 | * If you do not delete the provisions above, a recipient may use your version | |
34 | * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE | |
35 | * | |
36 | * This library is free software; you can redistribute it and/or modify it | |
37 | * under the terms of the MPL as stated above or under the terms of the GNU | |
38 | * Library General Public License as published by the Free Software Foundation; | |
39 | * either version 2 of the License, or any later version. | |
40 | * | |
41 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
42 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
43 | * FOR A PARTICULAR PURPOSE. See the GNU LIBRARY GENERAL PUBLIC LICENSE for more | |
44 | * details. | |
45 | * | |
46 | * If you didn't download this code from the following link, you should check if | |
47 | * you aren't using an obsolete version: | |
48 | * http://www.lowagie.com/iText/ | |
49 | */ | |
50 | ||
51 | package com.lowagie.text; | |
52 | ||
53 | import com.lowagie.text.alignment.HorizontalAlignment; | |
54 | import com.lowagie.text.alignment.WithHorizontalAlignment; | |
55 | import java.util.ArrayList; | |
56 | import com.lowagie.text.error_messages.MessageLocalization; | |
57 | ||
58 | /** | |
59 | * A <CODE>Row</CODE> is part of a <CODE>Table</CODE> | |
60 | * and contains some <CODE>Cells</CODE>. | |
61 | * <P> | |
62 | * All <CODE>Row</CODE>s are constructed by a <CODE>Table</CODE>-object. | |
63 | * You don't have to construct any <CODE>Row</CODE> yourself. | |
64 | * In fact you can't construct a <CODE>Row</CODE> outside the package. | |
65 | * <P> | |
66 | * Since a <CODE>Cell</CODE> can span several rows and/or columns | |
67 | * a row can contain reserved space without any content. | |
68 | * | |
69 | * @see Element | |
70 | * @see Cell | |
71 | * @see Table | |
72 | */ | |
73 | public class Row implements Element, WithHorizontalAlignment { | |
74 | | |
75 | // constants | |
76 | | |
77 | /** id of a null element in a Row*/ | |
78 | public static final int NULL = 0; | |
79 | | |
80 | /** id of the Cell element in a Row*/ | |
81 | public static final int CELL = 1; | |
82 | | |
83 | /** id of the Table element in a Row*/ | |
84 | public static final int TABLE = 2; | |
85 | | |
86 | // member variables | |
87 | | |
88 | /** This is the number of columns in the <CODE>Row</CODE>. */ | |
89 | protected int columns; | |
90 | | |
91 | /** This is a valid position the <CODE>Row</CODE>. */ | |
92 | protected int currentColumn; | |
93 | | |
94 | /** This is the array that keeps track of reserved cells. */ | |
95 | protected boolean[] reserved; | |
96 | | |
97 | /** This is the array of Objects (<CODE>Cell</CODE> or <CODE>Table</CODE>). */ | |
98 | protected Object[] cells; | |
99 | | |
100 | /** This is the vertical alignment. */ | |
101 | protected int horizontalAlignment; | |
102 | | |
103 | // constructors | |
104 | | |
105 | /** | |
106 | * Constructs a <CODE>Row</CODE> with a certain number of <VAR>columns</VAR>. | |
107 | * | |
108 | * @param columns a number of columns | |
109 | */ | |
110 | protected Row(int columns) { | |
111 | this.columns = columns; | |
112 | reserved = new boolean[columns]; | |
113 | cells = new Object[columns]; | |
114 | currentColumn = 0; | |
115 | } | |
116 | | |
117 | // implementation of the Element-methods | |
118 | | |
119 | /** | |
120 | * Processes the element by adding it (or the different parts) to a | |
121 | * <CODE>ElementListener</CODE>. | |
122 | * | |
123 | * @param listener an <CODE>ElementListener</CODE> | |
124 | * @return <CODE>true</CODE> if the element was processed successfully | |
125 | */ | |
126 | public boolean process(ElementListener listener) { | |
127 | try { | |
128 |
1
1. process : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return listener.add(this); |
129 | } | |
130 | catch(DocumentException de) { | |
131 |
1
1. process : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
132 | } | |
133 | } | |
134 | | |
135 | /** | |
136 | * Gets the type of the text element. | |
137 | * | |
138 | * @return a type | |
139 | */ | |
140 | public int type() { | |
141 | return Element.ROW; | |
142 | } | |
143 | | |
144 | /** | |
145 | * Gets all the chunks in this element. | |
146 | * | |
147 | * @return an <CODE>ArrayList</CODE> | |
148 | */ | |
149 | public ArrayList getChunks() { | |
150 |
1
1. getChunks : mutated return of Object value for com/lowagie/text/Row::getChunks to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return new ArrayList(); |
151 | } | |
152 | | |
153 | /** | |
154 | * @see com.lowagie.text.Element#isContent() | |
155 | * @since iText 2.0.8 | |
156 | */ | |
157 | public boolean isContent() { | |
158 | return true; | |
159 | } | |
160 | ||
161 | /** | |
162 | * @see com.lowagie.text.Element#isNestable() | |
163 | * @since iText 2.0.8 | |
164 | */ | |
165 | public boolean isNestable() { | |
166 | return false; | |
167 | } | |
168 | | |
169 | // method to delete a column | |
170 | | |
171 | /** | |
172 | * Returns a <CODE>Row</CODE> that is a copy of this <CODE>Row</CODE> | |
173 | * in which a certain column has been deleted. | |
174 | * | |
175 | * @param column the number of the column to delete | |
176 | */ | |
177 | void deleteColumn(int column) { | |
178 |
4
1. deleteColumn : changed conditional boundary → NO_COVERAGE 2. deleteColumn : changed conditional boundary → NO_COVERAGE 3. deleteColumn : negated conditional → NO_COVERAGE 4. deleteColumn : negated conditional → NO_COVERAGE |
if ((column >= columns) || (column < 0)) { |
179 | throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("getcell.at.illegal.index.1", column)); | |
180 | } | |
181 |
1
1. deleteColumn : Replaced integer subtraction with addition → NO_COVERAGE |
columns--; |
182 | boolean[] newReserved = new boolean[columns]; | |
183 | Object[] newCells = new Cell[columns]; | |
184 | | |
185 |
3
1. deleteColumn : changed conditional boundary → NO_COVERAGE 2. deleteColumn : Changed increment from 1 to -1 → NO_COVERAGE 3. deleteColumn : negated conditional → NO_COVERAGE |
for (int i = 0; i < column; i++) { |
186 | newReserved[i] = reserved[i]; | |
187 | newCells[i] = cells[i]; | |
188 |
4
1. deleteColumn : changed conditional boundary → NO_COVERAGE 2. deleteColumn : Replaced integer addition with subtraction → NO_COVERAGE 3. deleteColumn : negated conditional → NO_COVERAGE 4. deleteColumn : negated conditional → NO_COVERAGE |
if (newCells[i] != null && (i + ((Cell) newCells[i]).getColspan() > column)) { |
189 |
2
1. deleteColumn : Replaced integer subtraction with addition → NO_COVERAGE 2. deleteColumn : removed call to com/lowagie/text/Cell::setColspan → NO_COVERAGE |
((Cell) newCells[i]).setColspan(((Cell) cells[i]).getColspan() - 1); |
190 | } | |
191 | } | |
192 |
3
1. deleteColumn : changed conditional boundary → NO_COVERAGE 2. deleteColumn : Changed increment from 1 to -1 → NO_COVERAGE 3. deleteColumn : negated conditional → NO_COVERAGE |
for (int i = column; i < columns; i++) { |
193 |
1
1. deleteColumn : Replaced integer addition with subtraction → NO_COVERAGE |
newReserved[i] = reserved[i + 1]; |
194 |
1
1. deleteColumn : Replaced integer addition with subtraction → NO_COVERAGE |
newCells[i] = cells[i + 1]; |
195 | } | |
196 |
3
1. deleteColumn : changed conditional boundary → NO_COVERAGE 2. deleteColumn : negated conditional → NO_COVERAGE 3. deleteColumn : negated conditional → NO_COVERAGE |
if (cells[column] != null && ((Cell) cells[column]).getColspan() > 1) { |
197 | newCells[column] = cells[column]; | |
198 |
2
1. deleteColumn : Replaced integer subtraction with addition → NO_COVERAGE 2. deleteColumn : removed call to com/lowagie/text/Cell::setColspan → NO_COVERAGE |
((Cell) newCells[column]).setColspan(((Cell) newCells[column]).getColspan() - 1); |
199 | } | |
200 | reserved = newReserved; | |
201 | cells = newCells; | |
202 | } | |
203 | | |
204 | // methods | |
205 | | |
206 | /** | |
207 | * Adds a <CODE>Cell</CODE> to the <CODE>Row</CODE>. | |
208 | * | |
209 | * @param element the element to add (currently only Cells and Tables supported) | |
210 | * @return the column position the <CODE>Cell</CODE> was added, | |
211 | * or <CODE>-1</CODE> if the <CODE>element</CODE> couldn't be added. | |
212 | */ | |
213 | int addElement(Object element) { | |
214 |
1
1. addElement : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return addElement(element, currentColumn); |
215 | } | |
216 | | |
217 | /** | |
218 | * Adds an element to the <CODE>Row</CODE> at the position given. | |
219 | * | |
220 | * @param element the element to add. (currently only Cells and Tables supported | |
221 | * @param column the position where to add the cell. | |
222 | * @return the column position the <CODE>Cell</CODE> was added, | |
223 | * or <CODE>-1</CODE> if the <CODE>Cell</CODE> couldn't be added. | |
224 | */ | |
225 | int addElement(Object element, int column) { | |
226 |
1
1. addElement : negated conditional → KILLED |
if (element == null) throw new NullPointerException(MessageLocalization.getComposedMessage("addcell.null.argument")); |
227 |
4
1. addElement : changed conditional boundary → SURVIVED 2. addElement : changed conditional boundary → KILLED 3. addElement : negated conditional → KILLED 4. addElement : negated conditional → KILLED |
if ((column < 0) || (column > columns)) throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("addcell.illegal.column.argument")); |
228 |
2
1. addElement : negated conditional → SURVIVED 2. addElement : negated conditional → KILLED |
if ( !((getObjectID(element) == CELL) || (getObjectID(element) == TABLE)) ) throw new IllegalArgumentException(MessageLocalization.getComposedMessage("addcell.only.cells.or.tables.allowed")); |
229 | | |
230 |
1
1. addElement : negated conditional → SURVIVED |
int lColspan = ( (element instanceof Cell) ? ((Cell) element).getColspan() : 1); |
231 | | |
232 |
1
1. addElement : negated conditional → SURVIVED |
if (!reserve(column, lColspan)) { |
233 |
1
1. addElement : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return -1; |
234 | } | |
235 | | |
236 | cells[column] = element; | |
237 |
2
1. addElement : Replaced integer subtraction with addition → SURVIVED 2. addElement : Replaced integer addition with subtraction → SURVIVED |
currentColumn += lColspan - 1; |
238 | | |
239 |
1
1. addElement : replaced return of integer sized value with (x == 0 ? 1 : 0) → SURVIVED |
return column; |
240 | } | |
241 | | |
242 | /** | |
243 | * Puts <CODE>Cell</CODE> to the <CODE>Row</CODE> at the position given, doesn't reserve colspan. | |
244 | * | |
245 | * @param aElement the cell to add. | |
246 | * @param column the position where to add the cell. | |
247 | */ | |
248 | void setElement(Object aElement, int column) { | |
249 |
1
1. setElement : negated conditional → NO_COVERAGE |
if (reserved[column]) throw new IllegalArgumentException(MessageLocalization.getComposedMessage("setelement.position.already.taken")); |
250 | | |
251 | cells[column] = aElement; | |
252 |
1
1. setElement : negated conditional → NO_COVERAGE |
if (aElement != null) { |
253 | reserved[column] = true; | |
254 | } | |
255 | } | |
256 | | |
257 | /** | |
258 | * Reserves a <CODE>Cell</CODE> in the <CODE>Row</CODE>. | |
259 | * | |
260 | * @param column the column that has to be reserved. | |
261 | * @return <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not. | |
262 | */ | |
263 | boolean reserve(int column) { | |
264 |
1
1. reserve : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return reserve(column, 1); |
265 | } | |
266 | | |
267 | | |
268 | /** | |
269 | * Reserves a <CODE>Cell</CODE> in the <CODE>Row</CODE>. | |
270 | * | |
271 | * @param column the column that has to be reserved. | |
272 | * @param size the number of columns | |
273 | * @return <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not. | |
274 | */ | |
275 | boolean reserve(int column, int size) { | |
276 |
5
1. reserve : Replaced integer addition with subtraction → SURVIVED 2. reserve : changed conditional boundary → KILLED 3. reserve : changed conditional boundary → KILLED 4. reserve : negated conditional → KILLED 5. reserve : negated conditional → KILLED |
if ((column < 0) || ((column + size) > columns)) throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("reserve.incorrect.column.size")); |
277 | | |
278 |
4
1. reserve : Replaced integer addition with subtraction → SURVIVED 2. reserve : negated conditional → SURVIVED 3. reserve : changed conditional boundary → KILLED 4. reserve : Changed increment from 1 to -1 → KILLED |
for(int i=column; i < column + size; i++) |
279 | { | |
280 |
1
1. reserve : negated conditional → SURVIVED |
if (reserved[i]) { |
281 | // undo reserve | |
282 |
3
1. reserve : changed conditional boundary → NO_COVERAGE 2. reserve : Changed increment from -1 to 1 → NO_COVERAGE 3. reserve : negated conditional → NO_COVERAGE |
for(int j=i; j >= column; j--) { |
283 | reserved[j] = false; | |
284 | } | |
285 |
1
1. reserve : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
286 | } | |
287 | reserved[i] = true; | |
288 | } | |
289 |
1
1. reserve : replaced return of integer sized value with (x == 0 ? 1 : 0) → SURVIVED |
return true; |
290 | } | |
291 | | |
292 | // methods to retrieve information | |
293 | | |
294 | /** | |
295 | * Returns true/false when this position in the <CODE>Row</CODE> has been reserved, either filled or through a colspan of an Element. | |
296 | * | |
297 | * @param column the column. | |
298 | * @return <CODE>true</CODE> if the column was reserved, <CODE>false</CODE> if not. | |
299 | */ | |
300 | boolean isReserved(int column) { | |
301 |
1
1. isReserved : replaced return of integer sized value with (x == 0 ? 1 : 0) → SURVIVED |
return reserved[column]; |
302 | } | |
303 | | |
304 | /** | |
305 | * Returns the type-id of the element in a Row. | |
306 | * | |
307 | * @param column the column of which you'd like to know the type | |
308 | * @return the type-id of the element in the row | |
309 | */ | |
310 | int getElementID(int column) { | |
311 |
2
1. getElementID : negated conditional → NO_COVERAGE 2. getElementID : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
if (cells[column] == null) return NULL; |
312 |
2
1. getElementID : negated conditional → NO_COVERAGE 2. getElementID : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
else if (cells[column] instanceof Cell) return CELL; |
313 |
2
1. getElementID : negated conditional → NO_COVERAGE 2. getElementID : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
else if (cells[column] instanceof Table) return TABLE; |
314 | | |
315 |
1
1. getElementID : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return -1; |
316 | } | |
317 | | |
318 | /** | |
319 | * Returns the type-id of an Object. | |
320 | * | |
321 | * @param element the object of which you'd like to know the type-id, -1 if invalid | |
322 | * @return the type-id of an object | |
323 | */ | |
324 | int getObjectID(Object element) { | |
325 |
2
1. getObjectID : replaced return of integer sized value with (x == 0 ? 1 : 0) → SURVIVED 2. getObjectID : negated conditional → KILLED |
if (element == null) return NULL; |
326 |
2
1. getObjectID : negated conditional → KILLED 2. getObjectID : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
else if (element instanceof Cell) return CELL; |
327 |
2
1. getObjectID : negated conditional → NO_COVERAGE 2. getObjectID : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
else if (element instanceof Table) return TABLE; |
328 |
1
1. getObjectID : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return -1; |
329 | } | |
330 | | |
331 | /** | |
332 | * Gets a <CODE>Cell</CODE> or <CODE>Table</CODE> from a certain column. | |
333 | * | |
334 | * @param column the column the <CODE>Cell/Table</CODE> is in. | |
335 | * @return the <CODE>Cell</CODE>,<CODE>Table</CODE> or <VAR>Object</VAR> if the column was | |
336 | * reserved or null if empty. | |
337 | */ | |
338 | public Object getCell(int column) { | |
339 |
4
1. getCell : changed conditional boundary → NO_COVERAGE 2. getCell : changed conditional boundary → NO_COVERAGE 3. getCell : negated conditional → NO_COVERAGE 4. getCell : negated conditional → NO_COVERAGE |
if ((column < 0) || (column > columns)) { |
340 | throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("getcell.at.illegal.index.1.max.is.2", String.valueOf(column), String.valueOf(columns))); | |
341 | } | |
342 |
1
1. getCell : mutated return of Object value for com/lowagie/text/Row::getCell to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return cells[column]; |
343 | } | |
344 | | |
345 | /** | |
346 | * Checks if the row is empty. | |
347 | * | |
348 | * @return <CODE>true</CODE> if none of the columns is reserved. | |
349 | */ | |
350 | public boolean isEmpty() { | |
351 |
3
1. isEmpty : changed conditional boundary → NO_COVERAGE 2. isEmpty : Changed increment from 1 to -1 → NO_COVERAGE 3. isEmpty : negated conditional → NO_COVERAGE |
for (int i = 0; i < columns; i++) { |
352 |
1
1. isEmpty : negated conditional → NO_COVERAGE |
if (cells[i] != null) { |
353 |
1
1. isEmpty : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return false; |
354 | } | |
355 | } | |
356 |
1
1. isEmpty : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return true; |
357 | } | |
358 | | |
359 | /** | |
360 | * Gets the number of columns. | |
361 | * | |
362 | * @return a value | |
363 | */ | |
364 | public int getColumns() { | |
365 | return columns; | |
366 | } | |
367 | | |
368 | /** | |
369 | * Sets the horizontal alignment. | |
370 | * | |
371 | * @param value the new value | |
372 | * @deprecated Setting alignment through unconstrained types is non-obvious and error-prone, | |
373 | * use {@link Row#setHorizontalAlignment(HorizontalAlignment)} instead | |
374 | */ | |
375 | public void setHorizontalAlignment(int value) { | |
376 | horizontalAlignment = value; | |
377 | } | |
378 | | |
379 | /** | |
380 | * Gets the horizontal alignment. | |
381 | * | |
382 | * @return a value | |
383 | */ | |
384 | public int getHorizontalAlignment() { | |
385 | return horizontalAlignment; | |
386 | } | |
387 | ||
388 | @Override | |
389 | public void setHorizontalAlignment(final HorizontalAlignment alignment) { | |
390 |
1
1. setHorizontalAlignment : negated conditional → NO_COVERAGE |
if (alignment == null) { |
391 | return; | |
392 | } | |
393 | ||
394 | horizontalAlignment = alignment.getId(); | |
395 | } | |
396 | } | |
Mutations | ||
128 |
1.1 |
|
131 |
1.1 |
|
150 |
1.1 |
|
178 |
1.1 2.2 3.3 4.4 |
|
181 |
1.1 |
|
185 |
1.1 2.2 3.3 |
|
188 |
1.1 2.2 3.3 4.4 |
|
189 |
1.1 2.2 |
|
192 |
1.1 2.2 3.3 |
|
193 |
1.1 |
|
194 |
1.1 |
|
196 |
1.1 2.2 3.3 |
|
198 |
1.1 2.2 |
|
214 |
1.1 |
|
226 |
1.1 |
|
227 |
1.1 2.2 3.3 4.4 |
|
228 |
1.1 2.2 |
|
230 |
1.1 |
|
232 |
1.1 |
|
233 |
1.1 |
|
237 |
1.1 2.2 |
|
239 |
1.1 |
|
249 |
1.1 |
|
252 |
1.1 |
|
264 |
1.1 |
|
276 |
1.1 2.2 3.3 4.4 5.5 |
|
278 |
1.1 2.2 3.3 4.4 |
|
280 |
1.1 |
|
282 |
1.1 2.2 3.3 |
|
285 |
1.1 |
|
289 |
1.1 |
|
301 |
1.1 |
|
311 |
1.1 2.2 |
|
312 |
1.1 2.2 |
|
313 |
1.1 2.2 |
|
315 |
1.1 |
|
325 |
1.1 2.2 |
|
326 |
1.1 2.2 |
|
327 |
1.1 2.2 |
|
328 |
1.1 |
|
339 |
1.1 2.2 3.3 4.4 |
|
342 |
1.1 |
|
351 |
1.1 2.2 3.3 |
|
352 |
1.1 |
|
353 |
1.1 |
|
356 |
1.1 |
|
390 |
1.1 |