CompareToolResult.java
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2026 Apryse Group NV
Authors: Apryse Software.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itextpdf.kernel.utils;
import com.itextpdf.kernel.utils.objectpathitems.ObjectPath;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.OutputStream;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Class containing results of the comparison of two pdf documents.
*/
public final class CompareToolResult {
// LinkedHashMap to retain order. HashMap has different order in Java6/7 and Java8
private final Map<ObjectPath, String> differences = new LinkedHashMap<>();
private int messageLimit = 1;
/**
* Creates new empty instance of CompareToolResult with given limit of difference messages.
*
* @param messageLimit maximum number of difference messages to be handled by this CompareToolResult.
*/
public CompareToolResult(int messageLimit) {
this.messageLimit = messageLimit;
}
/**
* Verifies if documents are considered equal after comparison.
*
* @return true if documents are equal, false otherwise.
*/
public boolean isOk() {
return differences.isEmpty();
}
/**
* Returns number of differences between two documents detected during comparison.
*
* @return number of differences.
*/
public int getErrorCount() {
return differences.size();
}
/**
* Converts this CompareToolResult into text form.
*
* @return text report on the differences between two documents.
*/
public String getReport() {
StringBuilder sb = new StringBuilder();
boolean firstEntry = true;
for (Map.Entry<ObjectPath, String> entry : differences.entrySet()) {
if (!firstEntry)
sb.append("-----------------------------").append("\n");
ObjectPath diffPath = entry.getKey();
sb.append(entry.getValue()).append("\n").append(diffPath.toString()).append("\n");
firstEntry = false;
}
return sb.toString();
}
/**
* Returns map with {@link ObjectPath} as keys and difference descriptions as values.
*
* @return differences map which could be used to find in the document the objects that are different.
*/
public Map<ObjectPath, String> getDifferences() {
return differences;
}
/**
* Converts this CompareToolResult into xml form.
*
* @param stream output stream to which xml report will be written.
* @throws ParserConfigurationException if a XML DocumentBuilder cannot be created
* which satisfies the configuration requested.
* @throws TransformerException if it is not possible to create an XML Transformer instance or
* an unrecoverable error occurs during the course of the transformation.
*/
public void writeReportToXml(OutputStream stream) throws ParserConfigurationException, TransformerException {
final Document xmlReport = XmlUtils.initNewXmlDocument();
Element root = xmlReport.createElement("report");
Element errors = xmlReport.createElement("errors");
errors.setAttribute("count", String.valueOf(differences.size()));
root.appendChild(errors);
for (Map.Entry<ObjectPath, String> entry : differences.entrySet()) {
Node errorNode = xmlReport.createElement("error");
Node message = xmlReport.createElement("message");
message.appendChild(xmlReport.createTextNode(entry.getValue()));
Node path = entry.getKey().toXmlNode(xmlReport);
errorNode.appendChild(message);
errorNode.appendChild(path);
errors.appendChild(errorNode);
}
xmlReport.appendChild(root);
XmlUtils.writeXmlDocToStream(xmlReport, stream);
}
/**
* Checks whether maximum number of difference messages to be handled by this CompareToolResult is reached.
*
* @return true if limit of difference messages is reached, false otherwise.
*/
boolean isMessageLimitReached() {
return differences.size() >= messageLimit;
}
/**
* Returns set limit of difference messages.
*
* @return message limit.
*/
int getMessageLimit() {
return messageLimit;
}
/**
* Adds an error message for the {@link ObjectPath}.
*
* @param path {@link ObjectPath} for the two corresponding objects in the compared documents
* @param message an error message
*/
void addError(ObjectPath path, String message) {
if (differences.size() < messageLimit) {
differences.put(new ObjectPath(path), message);
}
}
}