Skip to content

Commit 698bf89

Browse files
committed
Implement #equals() and #hashCode() methods for PDF primitive objects.
DEVSIX-851
1 parent 3b55640 commit 698bf89

File tree

6 files changed

+93
-6
lines changed

6 files changed

+93
-6
lines changed

io/src/main/java/com/itextpdf/io/LogMessageConstant.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public final class LogMessageConstant {
6666
public static final String IMAGE_SIZE_CANNOT_BE_MORE_4KB = "Inline image size cannot be more than 4KB. It will be added as an ImageXObject";
6767
public static final String INVALID_INDIRECT_REFERENCE = "Invalid indirect reference";
6868
public static final String INVALID_KEY_VALUE_KEY_0_HAS_NULL_VALUE = "Invalid key value: key {0} has null value.";
69+
public static final String CALCULATE_HASHCODE_FOR_MODIFIED_PDFNUMBER = "Calculate hashcode for modified PdfNumber.";
6970
public static final String MAKE_COPY_OF_CATALOG_DICTIONARY_IS_FORBIDDEN = "Make copy of Catalog dictionary is forbidden.";
7071
public static final String NOT_TAGGED_PAGES_IN_TAGGED_DOCUMENT = "Not tagged pages are copied to the tagged document. Destination document now may contain not tagged content.";
7172
public static final String PDF_READER_CLOSING_FAILED = "PdfReader closing failed due to the error occurred!";

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfBoolean.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,15 @@ protected void copyContent(PdfObject from, PdfDocument document) {
152152
PdfBoolean bool = (PdfBoolean)from;
153153
value = bool.value;
154154
}
155+
156+
@Override
157+
public boolean equals(Object obj) {
158+
return this == obj ||
159+
!(obj == null || getClass() != obj.getClass()) && value == ((PdfBoolean) obj).value;
160+
}
161+
162+
@Override
163+
public int hashCode() {
164+
return (value ? 1 : 0);
165+
}
155166
}

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfLiteral.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ protected void generateContent() {
102102

103103
}
104104

105+
@Override
106+
public boolean equals(Object o) {
107+
return this == o ||
108+
!(o == null || getClass() != o.getClass()) && Arrays.equals(content, ((PdfLiteral) o).content);
109+
}
110+
111+
@Override
112+
public int hashCode() {
113+
return content == null ? 0 : Arrays.hashCode(content);
114+
}
115+
105116
@Override
106117
protected PdfLiteral newInstance() {
107118
return new PdfLiteral();

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfNull.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,14 @@ protected PdfNull newInstance() {
144144
protected void copyContent(PdfObject from, PdfDocument document) {
145145

146146
}
147+
148+
@Override
149+
public boolean equals(Object obj) {
150+
return this == obj || !(obj == null || getClass() != obj.getClass());
151+
}
152+
153+
@Override
154+
public int hashCode() {
155+
return 0;
156+
}
147157
}

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfNumber.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,18 @@ This file is part of the iText (R) project.
4343
*/
4444
package com.itextpdf.kernel.pdf;
4545

46+
import com.itextpdf.io.LogMessageConstant;
4647
import com.itextpdf.io.source.ByteUtils;
48+
import org.slf4j.Logger;
49+
import org.slf4j.LoggerFactory;
4750

4851
public class PdfNumber extends PdfPrimitiveObject {
4952

5053
private static final long serialVersionUID = -250799718574024246L;
5154

5255
private double value;
5356
private boolean isDouble;
57+
private boolean changed = false;
5458

5559
public PdfNumber(double value) {
5660
super();
@@ -103,6 +107,7 @@ public void setValue(int value) {
103107
this.value = value;
104108
this.isDouble = false;
105109
this.content = null;
110+
this.changed = true;
106111
}
107112

108113
public void setValue(double value) {
@@ -183,6 +188,24 @@ public String toString() {
183188
}
184189
}
185190

191+
@Override
192+
public boolean equals(Object o) {
193+
return this == o ||
194+
!(o == null || getClass() != o.getClass()) && Double.compare(((PdfNumber) o).value, value) == 0;
195+
}
196+
197+
@Override
198+
public int hashCode() {
199+
if (changed) {
200+
//if the instance was modified, hashCode also will be changed, it may cause inconsistency.
201+
Logger logger = LoggerFactory.getLogger(PdfReader.class);
202+
logger.warn(LogMessageConstant.CALCULATE_HASHCODE_FOR_MODIFIED_PDFNUMBER);
203+
changed = false;
204+
}
205+
long hash = Double.doubleToLongBits(value);
206+
return (int) (hash ^ (hash >>> 32));
207+
}
208+
186209
@Override
187210
protected PdfNumber newInstance() {
188211
return new PdfNumber();

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfString.java

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ public class PdfString extends PdfPrimitiveObject {
6969

7070
private static final long serialVersionUID = 390789504287887010L;
7171

72-
private static String defaultCharset = "UTF-8";
73-
7472
protected String value;
7573
protected String encoding;
7674
protected boolean hexWriting = false;
@@ -97,8 +95,8 @@ public PdfString(byte[] content) {
9795
super();
9896
if (content != null && content.length > 0) {
9997
StringBuilder str = new StringBuilder(content.length);
100-
for (byte b: content) {
101-
str.append((char)(b & 0xff));
98+
for (byte b : content) {
99+
str.append((char) (b & 0xff));
102100
}
103101
this.value = str.toString();
104102
} else {
@@ -152,10 +150,15 @@ public String getEncoding() {
152150
/**
153151
* Sets the encoding of this string.
154152
* NOTE. Byte content will be removed.
153+
* @deprecated Create a new instance with {@link PdfString#PdfString(String, String)} instead.
155154
*/
155+
@Deprecated
156156
public void setEncoding(String encoding) {
157+
if (value == null) {
158+
generateValue();
159+
this.content = null;
160+
}
157161
this.encoding = encoding;
158-
this.content = null;
159162
}
160163

161164
/**
@@ -170,7 +173,7 @@ public String toUnicodeString() {
170173
generateContent();
171174
}
172175
byte[] b = PdfTokenizer.decodeStringContent(content, hexWriting);
173-
if (b.length >= 2 && b[0] == (byte)0xFE && b[1] == (byte)0xFF) {
176+
if (b.length >= 2 && b[0] == (byte) 0xFE && b[1] == (byte) 0xFF) {
174177
return PdfEncodings.convertToString(b, PdfEncodings.UNICODE_BIG);
175178
} else {
176179
return PdfEncodings.convertToString(b, PdfEncodings.PDF_DOC_ENCODING);
@@ -245,6 +248,26 @@ public PdfString copyTo(PdfDocument document, boolean allowDuplicating) {
245248
return (PdfString) super.copyTo(document, allowDuplicating);
246249
}
247250

251+
@Override
252+
public boolean equals(Object o) {
253+
if (this == o)
254+
return true;
255+
if (o == null || getClass() != o.getClass())
256+
return false;
257+
PdfString that = (PdfString) o;
258+
String v1 = getValue();
259+
String v2 = that.getValue();
260+
if (v1 != null && v1.equals(v2)) {
261+
String e1 = getEncoding();
262+
String e2 = that.getEncoding();
263+
if ((e1 == null && e2 == null)
264+
|| (e1 != null && e1.equals(e2))) {
265+
return true;
266+
}
267+
}
268+
return false;
269+
}
270+
248271
@Override
249272
public String toString() {
250273
if (value == null) {
@@ -254,6 +277,14 @@ public String toString() {
254277
}
255278
}
256279

280+
@Override
281+
public int hashCode() {
282+
String v = getValue();
283+
String e = getEncoding();
284+
int result = v != null ? v.hashCode() : 0;
285+
return 31 * result + (e != null ? e.hashCode() : 0);
286+
}
287+
257288
protected void generateValue() {
258289
assert content != null : "No byte[] content to generate value";
259290
value = PdfEncodings.convertToString(PdfTokenizer.decodeStringContent(content, hexWriting), null);

0 commit comments

Comments
 (0)