For developers wishing to integrate the ODF Validator into their own applications, the following information may be useful. You’ll need to use the odf-core package which is currently in the OPF’s Maven repository.
For now the Maven artefacts are hosted on the OPF’s artifactory server. To use them you’ll need to add the following to your Maven setting file (usually ~/.m2/settings.xml):
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" xmlns="http://maven.apache.org/SETTINGS/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<profiles>
<profile>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>opf-dev</name>
<url>https://artifactory.openpreservation.org/artifactory/opf-dev</url>
</repository>
<repository>
<snapshots />
<id>snapshots</id>
<name>opf-dev</name>
<url>https://artifactory.openpreservation.org/artifactory/opf-dev</url>
</repository>
</repositories>
<id>artifactory</id>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
</settings>
To include the core validation library in your project, add the following dependency to your pom.xml:
<dependency>
<groupId>org.openpreservation.odf</groupId>
<artifactId>odf-core</artifactId>
<version>0.14.0-SNAPSHOT</version>
</dependency>
The library employs a parser that parses ODF packages and creates an internal model of the package. This model is then used by the validator classes to validate the package. Validators effectively test properties of the model against the ODF Specification, or other policies.
The library allows a non-validating parse of an ODF package, indeed this is a pre-requisite to valdiation which is performed against a package instance. The following code snippet shows how to parse an ODF package:
import org.openpreservation.odf.pkg.FileEntry;
import org.openpreservation.odf.pkg.Manifest;
import org.openpreservation.odf.pkg.OdfPackage;
import org.openpreservation.odf.pkg.OdfPackages;
import org.openpreservation.odf.pkg.PackageParser;
// Get a package parser instance
PackageParser packageParser = OdfPackages.getPackageParser();
File packageFile = new File("path/to/package.ods");
OdfPackage odfPackage = packageParser.parsePackage(packageFile);
// Get the package manifest
Manifest manifest = odfPackage.getManifest();
// Get the file entries from the manifest
for (FileEntry entry : manifest.getEntries()) {
// Get the entry declared MIME type
String mediaType = entry.getMediaType();
// Get the entry declared full path
String fullPath = entry.getFullPath();
// Get the entry Input Stream
try (InputStream is = odfPackage.getEntryStream(entry)) {
// Do something with the entry
}
}
Note the use of the factory method OdfPackages.getPackageParser()
to obtain a package parser instance. This can be reused to parse multiple packages. You can read more about the ODF Package types in the API documentation:
OdfPackage
Manifest
FileEntry
import org.openpreservation.messages.Message;
import org.openpreservation.odf.pkg.OdfPackage;
import org.openpreservation.odf.validation.ValidatingParser;
import org.openpreservation.odf.validation.ValidationReport;
import org.openpreservation.odf.validation.Validators;
ValidatingParser packageParser = Validators.getValidatingParser();
File packageFile = new File("path/to/package.ods");
// Get the OdfPackage instance from the parser
OdfPackage odfPackage = packageParser.parsePackage(packageFile.toPath());
// Now validate the package and get the validation report
ValidationReport report = packageParser.validatePackage(odfPackage);
// Is the package valid?
if (report.isValid()) {
System.out.println("Package is valid");
// Get any warnings or info message (no errors as the package is valid)
List<Message> messages = report.getMessages();
// Loop through the messages
for (Message message : messages) {
// Get the message id
System.out.println(message.getId());
// Get the message severity (INFO, WARNING, ERROR)
System.out.println(message.getSeverity());
// Print out the message text
System.out.println(message.getMessage());
}
} else {
System.out.println("Package is not valid");
// Get the error messages
List<Message> messages = report.getErrors();
for (Message message : messages) {
// Get the message id
System.out.println(message.getId());
// Print out the message text
System.out.println(message.getMessage());
}
}
This time a ValidatingParser
instance is used. The ValidatingParser.validatePackage(OdfPackage)
method returns a ValidationReport
instance. This can be used to determine if the package is valid or not. If the package is not valid, the report can be used to obtain the error messages.
The ODF Validator can be used to validate spreadsheets only. This is useful if you want to validate a spreadsheet without having to parse the entire package. The following code snippet shows how to validate a spreadsheet:
import org.openpreservation.messages.Message;
import org.openpreservation.odf.validation.ValidationReport;
import org.openpreservation.odf.validation.Validator;
Validator validator = new Validator();
ValidationReport report = validator.validateSpreadsheet(new File("path/to/package.ods"));
if (!report.isValid()) {
List<Message> messages = report.getMessages();
// Loop through the messages
for (Message message : messages) {
// Get the message id
System.out.println(message.getId());
// Get the message severity (INFO, WARNING, ERROR)
System.out.println(message.getSeverity());
// Print out the message text
System.out.println(message.getMessage());
}
} else {
System.out.println("The document is valid");
}
There is an alternative profile validator that can run custom rules to check properties that are beyond the scope of the ODF specification. The following code snippet shows how to validate a spreadsheet using the Preservation Specification profile:
Profile dnaProfile = Rules.getDnaProfile();
ProfileResult result = dnaProfile.check(parser.parsePackage(Path.of("path/to/package.ods")));
// Check if the result is valid and print out any messages found
if (!result.isValid()) {
List<Message> messages = report.getProfileMessages().getMessages();
// Loop through the messages
for (Message message : messages) {
// Get the message id
System.out.println(message.getId());
// Get the message severity (INFO, WARNING, ERROR)
System.out.println(message.getSeverity());
// Print out the message text
System.out.println(message.getMessage());
}
} else {
System.out.println("The document is valid");
}