git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1890119 13f79535-47bb-0310-9956-ffa450edef68tags/REL_5_1_0
@@ -28,72 +28,72 @@ import org.apache.poi.openxml4j.opc.OPCPackage; | |||
import org.apache.poi.openxml4j.util.ZipSecureFile; | |||
public interface POIXMLTextExtractor extends POITextExtractor { | |||
/** | |||
* Returns the core document properties | |||
* | |||
* @return the core document properties | |||
*/ | |||
default CoreProperties getCoreProperties() { | |||
return getDocument().getProperties().getCoreProperties(); | |||
} | |||
/** | |||
* Returns the extended document properties | |||
* | |||
* @return the extended document properties | |||
*/ | |||
default ExtendedProperties getExtendedProperties() { | |||
return getDocument().getProperties().getExtendedProperties(); | |||
} | |||
/** | |||
* Returns the custom document properties | |||
* | |||
* @return the custom document properties | |||
*/ | |||
default CustomProperties getCustomProperties() { | |||
return getDocument().getProperties().getCustomProperties(); | |||
} | |||
/** | |||
* Returns the core document properties | |||
* | |||
* @return the core document properties | |||
*/ | |||
default CoreProperties getCoreProperties() { | |||
return getDocument().getProperties().getCoreProperties(); | |||
} | |||
/** | |||
* Returns the extended document properties | |||
* | |||
* @return the extended document properties | |||
*/ | |||
default ExtendedProperties getExtendedProperties() { | |||
return getDocument().getProperties().getExtendedProperties(); | |||
} | |||
/** | |||
* Returns the custom document properties | |||
* | |||
* @return the custom document properties | |||
*/ | |||
default CustomProperties getCustomProperties() { | |||
return getDocument().getProperties().getCustomProperties(); | |||
} | |||
/** | |||
* Returns opened document | |||
* | |||
* @return the opened document | |||
*/ | |||
@Override | |||
POIXMLDocument getDocument(); | |||
/** | |||
* Returns opened document | |||
* | |||
* @return the opened document | |||
*/ | |||
@Override | |||
POIXMLDocument getDocument(); | |||
/** | |||
* Returns the opened OPCPackage that contains the document | |||
* | |||
* @return the opened OPCPackage | |||
*/ | |||
default OPCPackage getPackage() { | |||
POIXMLDocument doc = getDocument(); | |||
return doc != null ? doc.getPackage() : null; | |||
} | |||
/** | |||
* Returns the opened OPCPackage that contains the document | |||
* | |||
* @return the opened OPCPackage | |||
*/ | |||
default OPCPackage getPackage() { | |||
POIXMLDocument doc = getDocument(); | |||
return doc != null ? doc.getPackage() : null; | |||
} | |||
/** | |||
* Returns an OOXML properties text extractor for the | |||
* document properties metadata, such as title and author. | |||
*/ | |||
@Override | |||
/** | |||
* Returns an OOXML properties text extractor for the | |||
* document properties metadata, such as title and author. | |||
*/ | |||
@Override | |||
default POIXMLPropertiesTextExtractor getMetadataTextExtractor() { | |||
return new POIXMLPropertiesTextExtractor(getDocument()); | |||
} | |||
return new POIXMLPropertiesTextExtractor(getDocument()); | |||
} | |||
@Override | |||
default void close() throws IOException { | |||
// e.g. XSSFEventBaseExcelExtractor passes a null-document | |||
if (isCloseFilesystem()) { | |||
@SuppressWarnings("resource") | |||
@Override | |||
default void close() throws IOException { | |||
// e.g. XSSFEventBaseExcelExtractor passes a null-document | |||
if (isCloseFilesystem()) { | |||
@SuppressWarnings("resource") | |||
OPCPackage pkg = getPackage(); | |||
if (pkg != null) { | |||
// revert the package to not re-write the file, which is very likely not wanted for a TextExtractor! | |||
pkg.revert(); | |||
} | |||
} | |||
} | |||
if (pkg != null) { | |||
// revert the package to not re-write the file, which is very likely not wanted for a TextExtractor! | |||
pkg.revert(); | |||
} | |||
} | |||
} | |||
default void checkMaxTextSize(CharSequence text, String string) { | |||
default void checkMaxTextSize(CharSequence text, String string) { | |||
if(string == null) { | |||
return; | |||
} |
@@ -28,8 +28,8 @@ public class IdentifierManager { | |||
private final long lowerbound; | |||
/** | |||
* List of segments of available identifiers | |||
*/ | |||
* List of segments of available identifiers | |||
*/ | |||
private LinkedList<Segment> segments; | |||
/** | |||
@@ -220,8 +220,8 @@ public class IdentifierManager { | |||
} | |||
/** | |||
* | |||
*/ | |||
* | |||
*/ | |||
private void verifyIdentifiersLeft() { | |||
if (segments.isEmpty()) { | |||
throw new IllegalStateException("No identifiers left"); |
@@ -20,9 +20,9 @@ package org.apache.poi.openxml4j.exceptions; | |||
@SuppressWarnings("serial") | |||
public final class InvalidFormatException extends OpenXML4JException { | |||
public InvalidFormatException(String message){ | |||
super(message); | |||
} | |||
public InvalidFormatException(String message){ | |||
super(message); | |||
} | |||
public InvalidFormatException(String message, Throwable cause){ | |||
super(message,cause); |
@@ -22,11 +22,11 @@ package org.apache.poi.openxml4j.exceptions; | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class InvalidOperationException extends OpenXML4JRuntimeException{ | |||
public InvalidOperationException(String message){ | |||
super(message); | |||
} | |||
public InvalidOperationException(String message){ | |||
super(message); | |||
} | |||
public InvalidOperationException(String message, Throwable reason){ | |||
super(message, reason); | |||
} | |||
super(message, reason); | |||
} | |||
} |
@@ -25,9 +25,9 @@ package org.apache.poi.openxml4j.exceptions; | |||
@SuppressWarnings("serial") | |||
public class OpenXML4JException extends Exception { | |||
public OpenXML4JException(String msg) { | |||
super(msg); | |||
} | |||
public OpenXML4JException(String msg) { | |||
super(msg); | |||
} | |||
public OpenXML4JException(String msg, Throwable cause) { | |||
super(msg, cause); |
@@ -27,9 +27,9 @@ package org.apache.poi.openxml4j.exceptions; | |||
@SuppressWarnings("serial") | |||
public class OpenXML4JRuntimeException extends RuntimeException { | |||
public OpenXML4JRuntimeException(String msg) { | |||
super(msg); | |||
} | |||
public OpenXML4JRuntimeException(String msg) { | |||
super(msg); | |||
} | |||
public OpenXML4JRuntimeException(String msg, Throwable reason) { | |||
super(msg, reason); |
@@ -25,7 +25,7 @@ import org.apache.poi.openxml4j.opc.PackagePart; | |||
*/ | |||
@SuppressWarnings("serial") | |||
public final class PartAlreadyExistsException extends InvalidOperationException { | |||
public PartAlreadyExistsException(String message){ | |||
super(message); | |||
} | |||
public PartAlreadyExistsException(String message){ | |||
super(message); | |||
} | |||
} |
@@ -21,10 +21,10 @@ package org.apache.poi.openxml4j.opc; | |||
* Specifies the location where the X.509 certificate that is used in signing is stored. | |||
*/ | |||
public enum CertificateEmbeddingOption { | |||
/** The certificate is embedded in its own PackagePart. */ | |||
IN_CERTIFICATE_PART, | |||
/** The certificate is embedded in the SignaturePart that is created for the signature being added. */ | |||
IN_SIGNATURE_PART, | |||
/** The certificate in not embedded in the package. */ | |||
NOT_EMBEDDED | |||
/** The certificate is embedded in its own PackagePart. */ | |||
IN_CERTIFICATE_PART, | |||
/** The certificate is embedded in the SignaturePart that is created for the signature being added. */ | |||
IN_SIGNATURE_PART, | |||
/** The certificate in not embedded in the package. */ | |||
NOT_EMBEDDED | |||
} |
@@ -25,106 +25,106 @@ import java.util.Locale; | |||
*/ | |||
public final class ContentTypes { | |||
/* | |||
* Open Packaging Convention (Annex F : Standard Namespaces and Content | |||
* Types) | |||
*/ | |||
/** | |||
* Core Properties part. | |||
*/ | |||
public static final String CORE_PROPERTIES_PART = "application/vnd.openxmlformats-package.core-properties+xml"; | |||
/** | |||
* Digital Signature Certificate part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_CERTIFICATE_PART = "application/vnd.openxmlformats-package.digital-signature-certificate"; | |||
/** | |||
* Digital Signature Origin part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_ORIGIN_PART = "application/vnd.openxmlformats-package.digital-signature-origin"; | |||
/** | |||
* Digital Signature XML Signature part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_XML_SIGNATURE_PART = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"; | |||
/** | |||
* Relationships part. | |||
*/ | |||
public static final String RELATIONSHIPS_PART = "application/vnd.openxmlformats-package.relationships+xml"; | |||
/** | |||
* Custom XML part. | |||
*/ | |||
public static final String CUSTOM_XML_PART = "application/vnd.openxmlformats-officedocument.customXmlProperties+xml"; | |||
/** | |||
* Plain old xml. Note - OOXML uses application/xml, and not text/xml! | |||
*/ | |||
public static final String PLAIN_OLD_XML = "application/xml"; | |||
public static final String IMAGE_JPEG = "image/jpeg"; | |||
public static final String EXTENSION_JPG_1 = "jpg"; | |||
public static final String EXTENSION_JPG_2 = "jpeg"; | |||
// image/png ISO/IEC 15948:2003 http://www.libpng.org/pub/png/spec/ | |||
public static final String IMAGE_PNG = "image/png"; | |||
public static final String EXTENSION_PNG = "png"; | |||
// image/gif http://www.w3.org/Graphics/GIF/spec-gif89a.txt | |||
public static final String IMAGE_GIF = "image/gif"; | |||
public static final String EXTENSION_GIF = "gif"; | |||
/** | |||
* TIFF image format. | |||
* | |||
* @see <a href="http://partners.adobe.com/public/developer/tiff/index.html#spec"> | |||
* http://partners.adobe.com/public/developer/tiff/index.html#spec</a> | |||
*/ | |||
public static final String IMAGE_TIFF = "image/tiff"; | |||
public static final String EXTENSION_TIFF = "tiff"; | |||
/** | |||
* Pict image format. | |||
* | |||
* @see <a href="http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html"> | |||
* http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html</a> | |||
*/ | |||
public static final String IMAGE_PICT = "image/pict"; | |||
public static final String EXTENSION_PICT = "pict"; | |||
/** | |||
* XML file. | |||
*/ | |||
public static final String XML = "text/xml"; | |||
public static final String EXTENSION_XML = "xml"; | |||
public static String getContentTypeFromFileExtension(String filename) { | |||
String extension = filename.substring(filename.lastIndexOf('.') + 1) | |||
.toLowerCase(Locale.ROOT); | |||
if (extension.equals(EXTENSION_JPG_1) | |||
|| extension.equals(EXTENSION_JPG_2)) | |||
return IMAGE_JPEG; | |||
else if (extension.equals(EXTENSION_GIF)) | |||
return IMAGE_GIF; | |||
else if (extension.equals(EXTENSION_PICT)) | |||
return IMAGE_PICT; | |||
else if (extension.equals(EXTENSION_PNG)) | |||
return IMAGE_PNG; | |||
else if (extension.equals(EXTENSION_TIFF)) | |||
return IMAGE_TIFF; | |||
else if (extension.equals(EXTENSION_XML)) | |||
return XML; | |||
else | |||
return null; | |||
} | |||
/* | |||
* Open Packaging Convention (Annex F : Standard Namespaces and Content | |||
* Types) | |||
*/ | |||
/** | |||
* Core Properties part. | |||
*/ | |||
public static final String CORE_PROPERTIES_PART = "application/vnd.openxmlformats-package.core-properties+xml"; | |||
/** | |||
* Digital Signature Certificate part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_CERTIFICATE_PART = "application/vnd.openxmlformats-package.digital-signature-certificate"; | |||
/** | |||
* Digital Signature Origin part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_ORIGIN_PART = "application/vnd.openxmlformats-package.digital-signature-origin"; | |||
/** | |||
* Digital Signature XML Signature part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_XML_SIGNATURE_PART = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"; | |||
/** | |||
* Relationships part. | |||
*/ | |||
public static final String RELATIONSHIPS_PART = "application/vnd.openxmlformats-package.relationships+xml"; | |||
/** | |||
* Custom XML part. | |||
*/ | |||
public static final String CUSTOM_XML_PART = "application/vnd.openxmlformats-officedocument.customXmlProperties+xml"; | |||
/** | |||
* Plain old xml. Note - OOXML uses application/xml, and not text/xml! | |||
*/ | |||
public static final String PLAIN_OLD_XML = "application/xml"; | |||
public static final String IMAGE_JPEG = "image/jpeg"; | |||
public static final String EXTENSION_JPG_1 = "jpg"; | |||
public static final String EXTENSION_JPG_2 = "jpeg"; | |||
// image/png ISO/IEC 15948:2003 http://www.libpng.org/pub/png/spec/ | |||
public static final String IMAGE_PNG = "image/png"; | |||
public static final String EXTENSION_PNG = "png"; | |||
// image/gif http://www.w3.org/Graphics/GIF/spec-gif89a.txt | |||
public static final String IMAGE_GIF = "image/gif"; | |||
public static final String EXTENSION_GIF = "gif"; | |||
/** | |||
* TIFF image format. | |||
* | |||
* @see <a href="http://partners.adobe.com/public/developer/tiff/index.html#spec"> | |||
* http://partners.adobe.com/public/developer/tiff/index.html#spec</a> | |||
*/ | |||
public static final String IMAGE_TIFF = "image/tiff"; | |||
public static final String EXTENSION_TIFF = "tiff"; | |||
/** | |||
* Pict image format. | |||
* | |||
* @see <a href="http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html"> | |||
* http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html</a> | |||
*/ | |||
public static final String IMAGE_PICT = "image/pict"; | |||
public static final String EXTENSION_PICT = "pict"; | |||
/** | |||
* XML file. | |||
*/ | |||
public static final String XML = "text/xml"; | |||
public static final String EXTENSION_XML = "xml"; | |||
public static String getContentTypeFromFileExtension(String filename) { | |||
String extension = filename.substring(filename.lastIndexOf('.') + 1) | |||
.toLowerCase(Locale.ROOT); | |||
if (extension.equals(EXTENSION_JPG_1) | |||
|| extension.equals(EXTENSION_JPG_2)) | |||
return IMAGE_JPEG; | |||
else if (extension.equals(EXTENSION_GIF)) | |||
return IMAGE_GIF; | |||
else if (extension.equals(EXTENSION_PICT)) | |||
return IMAGE_PICT; | |||
else if (extension.equals(EXTENSION_PNG)) | |||
return IMAGE_PNG; | |||
else if (extension.equals(EXTENSION_TIFF)) | |||
return IMAGE_TIFF; | |||
else if (extension.equals(EXTENSION_XML)) | |||
return XML; | |||
else | |||
return null; | |||
} | |||
} |
@@ -24,28 +24,28 @@ package org.apache.poi.openxml4j.opc; | |||
*/ | |||
public interface PackageNamespaces { | |||
/** | |||
* Content Types. | |||
*/ | |||
public static final String CONTENT_TYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; | |||
/** | |||
* Core Properties. | |||
*/ | |||
public static final String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"; | |||
/** | |||
* Digital Signatures. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/digital-signature"; | |||
/** | |||
* Relationships. | |||
*/ | |||
public static final String RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; | |||
/** | |||
* Markup Compatibility. | |||
*/ | |||
public static final String MARKUP_COMPATIBILITY = "http://schemas.openxmlformats.org/markup-compatibility/2006"; | |||
/** | |||
* Content Types. | |||
*/ | |||
public static final String CONTENT_TYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; | |||
/** | |||
* Core Properties. | |||
*/ | |||
public static final String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"; | |||
/** | |||
* Digital Signatures. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/digital-signature"; | |||
/** | |||
* Relationships. | |||
*/ | |||
public static final String RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; | |||
/** | |||
* Markup Compatibility. | |||
*/ | |||
public static final String MARKUP_COMPATIBILITY = "http://schemas.openxmlformats.org/markup-compatibility/2006"; | |||
} |
@@ -36,7 +36,7 @@ import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
*/ | |||
public final class PackagePartCollection implements Serializable { | |||
private static final long serialVersionUID = 2515031135957635517L; | |||
private static final long serialVersionUID = 2515031135957635517L; | |||
/** | |||
* HashSet use to store this collection part names as string for rule | |||
@@ -44,73 +44,73 @@ public final class PackagePartCollection implements Serializable { | |||
*/ | |||
private final Set<String> registerPartNameStr = new HashSet<>(); | |||
private final TreeMap<String, PackagePart> packagePartLookup = | |||
private final TreeMap<String, PackagePart> packagePartLookup = | |||
new TreeMap<>(PackagePartName::compare); | |||
/** | |||
* Check rule [M1.11]: a package implementer shall neither create nor | |||
* recognize a part with a part name derived from another part name by | |||
* appending segments to it. | |||
* | |||
* @param partName name of part | |||
* @param part part to put | |||
/** | |||
* Check rule [M1.11]: a package implementer shall neither create nor | |||
* recognize a part with a part name derived from another part name by | |||
* appending segments to it. | |||
* | |||
* @param partName name of part | |||
* @param part part to put | |||
* @return the previous value associated with {@code partName}, or | |||
* {@code null} if there was no mapping for {@code partName}. | |||
* @exception InvalidOperationException | |||
* Throws if you try to add a part with a name derived from | |||
* another part name. | |||
*/ | |||
public PackagePart put(final PackagePartName partName, final PackagePart part) { | |||
final String ppName = partName.getName(); | |||
* @exception InvalidOperationException | |||
* Throws if you try to add a part with a name derived from | |||
* another part name. | |||
*/ | |||
public PackagePart put(final PackagePartName partName, final PackagePart part) { | |||
final String ppName = partName.getName(); | |||
final StringBuilder concatSeg = new StringBuilder(); | |||
// split at slash, but keep leading slash | |||
final String delim = "(?=["+PackagingURIHelper.FORWARD_SLASH_STRING+".])"; | |||
for (String seg : ppName.split(delim)) { | |||
concatSeg.append(seg); | |||
if (registerPartNameStr.contains(concatSeg.toString())) { | |||
throw new InvalidOperationException( | |||
"You can't add a part with a part name derived from another part ! [M1.11]"); | |||
} | |||
} | |||
registerPartNameStr.add(ppName); | |||
return packagePartLookup.put(ppName, part); | |||
} | |||
public PackagePart remove(PackagePartName key) { | |||
if (key == null) { | |||
return null; | |||
} | |||
for (String seg : ppName.split(delim)) { | |||
concatSeg.append(seg); | |||
if (registerPartNameStr.contains(concatSeg.toString())) { | |||
throw new InvalidOperationException( | |||
"You can't add a part with a part name derived from another part ! [M1.11]"); | |||
} | |||
} | |||
registerPartNameStr.add(ppName); | |||
return packagePartLookup.put(ppName, part); | |||
} | |||
public PackagePart remove(PackagePartName key) { | |||
if (key == null) { | |||
return null; | |||
} | |||
final String ppName = key.getName(); | |||
PackagePart pp = packagePartLookup.remove(ppName); | |||
if (pp != null) { | |||
this.registerPartNameStr.remove(ppName); | |||
} | |||
return pp; | |||
} | |||
PackagePart pp = packagePartLookup.remove(ppName); | |||
if (pp != null) { | |||
this.registerPartNameStr.remove(ppName); | |||
} | |||
return pp; | |||
} | |||
/** | |||
* The values themselves should be returned in sorted order. Doing it here | |||
* avoids paying the high cost of Natural Ordering per insertion. | |||
/** | |||
* The values themselves should be returned in sorted order. Doing it here | |||
* avoids paying the high cost of Natural Ordering per insertion. | |||
* @return unmodifiable collection of parts | |||
*/ | |||
public Collection<PackagePart> sortedValues() { | |||
return Collections.unmodifiableCollection(packagePartLookup.values()); | |||
*/ | |||
public Collection<PackagePart> sortedValues() { | |||
return Collections.unmodifiableCollection(packagePartLookup.values()); | |||
} | |||
} | |||
public boolean containsKey(PackagePartName partName) { | |||
return partName != null && packagePartLookup.containsKey(partName.getName()); | |||
} | |||
public boolean containsKey(PackagePartName partName) { | |||
return partName != null && packagePartLookup.containsKey(partName.getName()); | |||
} | |||
public PackagePart get(PackagePartName partName) { | |||
return partName == null ? null : packagePartLookup.get(partName.getName()); | |||
} | |||
public PackagePart get(PackagePartName partName) { | |||
return partName == null ? null : packagePartLookup.get(partName.getName()); | |||
} | |||
public int size() { | |||
return packagePartLookup.size(); | |||
} | |||
public int size() { | |||
return packagePartLookup.size(); | |||
} | |||
@@ -32,271 +32,271 @@ import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; | |||
*/ | |||
public final class PackagePartName implements Comparable<PackagePartName> { | |||
/** | |||
* Part name stored as an URI. | |||
*/ | |||
private final URI partNameURI; | |||
/* | |||
* URI Characters definition (RFC 3986) | |||
*/ | |||
/** | |||
* Reserved characters for sub delimiters. | |||
*/ | |||
private static final String RFC3986_PCHAR_SUB_DELIMS = "!$&'()*+,;="; | |||
/** | |||
* Unreserved character (+ ALPHA & DIGIT). | |||
*/ | |||
private static final String RFC3986_PCHAR_UNRESERVED_SUP = "-._~"; | |||
/** | |||
* Authorized reserved characters for pChar. | |||
*/ | |||
private static final String RFC3986_PCHAR_AUTHORIZED_SUP = ":@"; | |||
/** | |||
* Flag to know if this part name is from a relationship part name. | |||
*/ | |||
private final boolean isRelationship; | |||
/** | |||
* Constructor. Makes a ValidPartName object from a java.net.URI | |||
* | |||
* @param uri | |||
* The URI to validate and to transform into ValidPartName. | |||
* @param checkConformance | |||
* Flag to specify if the constructor have to validate the OPC | |||
* conformance. Must be always <code>true</code> except for | |||
* special URI like '/' which is needed for internal use by | |||
* OpenXML4J but is not valid. | |||
* @throws InvalidFormatException | |||
* Throw if the specified part name is not conform to Open | |||
* Packaging Convention specifications. | |||
* @see java.net.URI | |||
*/ | |||
PackagePartName(URI uri, boolean checkConformance) | |||
throws InvalidFormatException { | |||
if (checkConformance) { | |||
throwExceptionIfInvalidPartUri(uri); | |||
} else { | |||
if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(uri)) { | |||
throw new OpenXML4JRuntimeException( | |||
"OCP conformance must be check for ALL part name except special cases : ['/']"); | |||
} | |||
} | |||
this.partNameURI = uri; | |||
this.isRelationship = isRelationshipPartURI(this.partNameURI); | |||
} | |||
/** | |||
* Constructor. Makes a ValidPartName object from a String part name. | |||
* | |||
* @param partName | |||
* Part name to valid and to create. | |||
* @param checkConformance | |||
* Flag to specify if the constructor have to validate the OPC | |||
* conformance. Must be always <code>true</code> except for | |||
* special URI like '/' which is needed for internal use by | |||
* OpenXML4J but is not valid. | |||
* @throws InvalidFormatException | |||
* Throw if the specified part name is not conform to Open | |||
* Packaging Convention specifications. | |||
*/ | |||
PackagePartName(String partName, boolean checkConformance) | |||
throws InvalidFormatException { | |||
URI partURI; | |||
try { | |||
partURI = new URI(partName); | |||
} catch (URISyntaxException e) { | |||
throw new IllegalArgumentException( | |||
"partName argmument is not a valid OPC part name !"); | |||
} | |||
if (checkConformance) { | |||
throwExceptionIfInvalidPartUri(partURI); | |||
} else { | |||
if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(partURI)) { | |||
throw new OpenXML4JRuntimeException( | |||
"OCP conformance must be check for ALL part name except special cases : ['/']"); | |||
} | |||
} | |||
this.partNameURI = partURI; | |||
this.isRelationship = isRelationshipPartURI(this.partNameURI); | |||
} | |||
/** | |||
* Check if the specified part name is a relationship part name. | |||
* | |||
* @param partUri | |||
* The URI to check. | |||
* @return <code>true</code> if this part name respect the relationship | |||
* part naming convention else <code>false</code>. | |||
*/ | |||
private boolean isRelationshipPartURI(URI partUri) { | |||
if (partUri == null) { | |||
/** | |||
* Part name stored as an URI. | |||
*/ | |||
private final URI partNameURI; | |||
/* | |||
* URI Characters definition (RFC 3986) | |||
*/ | |||
/** | |||
* Reserved characters for sub delimiters. | |||
*/ | |||
private static final String RFC3986_PCHAR_SUB_DELIMS = "!$&'()*+,;="; | |||
/** | |||
* Unreserved character (+ ALPHA & DIGIT). | |||
*/ | |||
private static final String RFC3986_PCHAR_UNRESERVED_SUP = "-._~"; | |||
/** | |||
* Authorized reserved characters for pChar. | |||
*/ | |||
private static final String RFC3986_PCHAR_AUTHORIZED_SUP = ":@"; | |||
/** | |||
* Flag to know if this part name is from a relationship part name. | |||
*/ | |||
private final boolean isRelationship; | |||
/** | |||
* Constructor. Makes a ValidPartName object from a java.net.URI | |||
* | |||
* @param uri | |||
* The URI to validate and to transform into ValidPartName. | |||
* @param checkConformance | |||
* Flag to specify if the constructor have to validate the OPC | |||
* conformance. Must be always <code>true</code> except for | |||
* special URI like '/' which is needed for internal use by | |||
* OpenXML4J but is not valid. | |||
* @throws InvalidFormatException | |||
* Throw if the specified part name is not conform to Open | |||
* Packaging Convention specifications. | |||
* @see java.net.URI | |||
*/ | |||
PackagePartName(URI uri, boolean checkConformance) | |||
throws InvalidFormatException { | |||
if (checkConformance) { | |||
throwExceptionIfInvalidPartUri(uri); | |||
} else { | |||
if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(uri)) { | |||
throw new OpenXML4JRuntimeException( | |||
"OCP conformance must be check for ALL part name except special cases : ['/']"); | |||
} | |||
} | |||
this.partNameURI = uri; | |||
this.isRelationship = isRelationshipPartURI(this.partNameURI); | |||
} | |||
/** | |||
* Constructor. Makes a ValidPartName object from a String part name. | |||
* | |||
* @param partName | |||
* Part name to valid and to create. | |||
* @param checkConformance | |||
* Flag to specify if the constructor have to validate the OPC | |||
* conformance. Must be always <code>true</code> except for | |||
* special URI like '/' which is needed for internal use by | |||
* OpenXML4J but is not valid. | |||
* @throws InvalidFormatException | |||
* Throw if the specified part name is not conform to Open | |||
* Packaging Convention specifications. | |||
*/ | |||
PackagePartName(String partName, boolean checkConformance) | |||
throws InvalidFormatException { | |||
URI partURI; | |||
try { | |||
partURI = new URI(partName); | |||
} catch (URISyntaxException e) { | |||
throw new IllegalArgumentException( | |||
"partName argmument is not a valid OPC part name !"); | |||
} | |||
if (checkConformance) { | |||
throwExceptionIfInvalidPartUri(partURI); | |||
} else { | |||
if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(partURI)) { | |||
throw new OpenXML4JRuntimeException( | |||
"OCP conformance must be check for ALL part name except special cases : ['/']"); | |||
} | |||
} | |||
this.partNameURI = partURI; | |||
this.isRelationship = isRelationshipPartURI(this.partNameURI); | |||
} | |||
/** | |||
* Check if the specified part name is a relationship part name. | |||
* | |||
* @param partUri | |||
* The URI to check. | |||
* @return <code>true</code> if this part name respect the relationship | |||
* part naming convention else <code>false</code>. | |||
*/ | |||
private boolean isRelationshipPartURI(URI partUri) { | |||
if (partUri == null) { | |||
throw new IllegalArgumentException("partUri"); | |||
} | |||
return partUri.getPath().matches( | |||
"^.*/" + PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME + "/.*\\" | |||
+ PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME | |||
+ "$"); | |||
} | |||
/** | |||
* Know if this part name is a relationship part name. | |||
* | |||
* @return <code>true</code> if this part name respect the relationship | |||
* part naming convention else <code>false</code>. | |||
*/ | |||
public boolean isRelationshipPartURI() { | |||
return this.isRelationship; | |||
} | |||
/** | |||
* Throws an exception (of any kind) if the specified part name does not | |||
* follow the Open Packaging Convention specifications naming rules. | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* Throws if the part name is invalid. | |||
*/ | |||
private static void throwExceptionIfInvalidPartUri(URI partUri) | |||
throws InvalidFormatException { | |||
if (partUri == null) { | |||
return partUri.getPath().matches( | |||
"^.*/" + PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME + "/.*\\" | |||
+ PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME | |||
+ "$"); | |||
} | |||
/** | |||
* Know if this part name is a relationship part name. | |||
* | |||
* @return <code>true</code> if this part name respect the relationship | |||
* part naming convention else <code>false</code>. | |||
*/ | |||
public boolean isRelationshipPartURI() { | |||
return this.isRelationship; | |||
} | |||
/** | |||
* Throws an exception (of any kind) if the specified part name does not | |||
* follow the Open Packaging Convention specifications naming rules. | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* Throws if the part name is invalid. | |||
*/ | |||
private static void throwExceptionIfInvalidPartUri(URI partUri) | |||
throws InvalidFormatException { | |||
if (partUri == null) { | |||
throw new IllegalArgumentException("partUri"); | |||
} | |||
// Check if the part name URI is empty [M1.1] | |||
throwExceptionIfEmptyURI(partUri); | |||
// Check if the part name URI is absolute | |||
throwExceptionIfAbsoluteUri(partUri); | |||
// Check if the part name URI starts with a forward slash [M1.4] | |||
throwExceptionIfPartNameNotStartsWithForwardSlashChar(partUri); | |||
// Check if the part name URI ends with a forward slash [M1.5] | |||
throwExceptionIfPartNameEndsWithForwardSlashChar(partUri); | |||
// Check if the part name does not have empty segments. [M1.3] | |||
// Check if a segment ends with a dot ('.') character. [M1.9] | |||
throwExceptionIfPartNameHaveInvalidSegments(partUri); | |||
} | |||
/** | |||
* Throws an exception if the specified URI is empty. [M1.1] | |||
* | |||
* @param partURI | |||
* Part URI to check. | |||
* @throws InvalidFormatException | |||
* If the specified URI is empty. | |||
*/ | |||
private static void throwExceptionIfEmptyURI(URI partURI) | |||
throws InvalidFormatException { | |||
if (partURI == null) { | |||
// Check if the part name URI is empty [M1.1] | |||
throwExceptionIfEmptyURI(partUri); | |||
// Check if the part name URI is absolute | |||
throwExceptionIfAbsoluteUri(partUri); | |||
// Check if the part name URI starts with a forward slash [M1.4] | |||
throwExceptionIfPartNameNotStartsWithForwardSlashChar(partUri); | |||
// Check if the part name URI ends with a forward slash [M1.5] | |||
throwExceptionIfPartNameEndsWithForwardSlashChar(partUri); | |||
// Check if the part name does not have empty segments. [M1.3] | |||
// Check if a segment ends with a dot ('.') character. [M1.9] | |||
throwExceptionIfPartNameHaveInvalidSegments(partUri); | |||
} | |||
/** | |||
* Throws an exception if the specified URI is empty. [M1.1] | |||
* | |||
* @param partURI | |||
* Part URI to check. | |||
* @throws InvalidFormatException | |||
* If the specified URI is empty. | |||
*/ | |||
private static void throwExceptionIfEmptyURI(URI partURI) | |||
throws InvalidFormatException { | |||
if (partURI == null) { | |||
throw new IllegalArgumentException("partURI"); | |||
} | |||
String uriPath = partURI.getPath(); | |||
if (uriPath.length() == 0 | |||
|| ((uriPath.length() == 1) && (uriPath.charAt(0) == PackagingURIHelper.FORWARD_SLASH_CHAR))) { | |||
String uriPath = partURI.getPath(); | |||
if (uriPath.length() == 0 | |||
|| ((uriPath.length() == 1) && (uriPath.charAt(0) == PackagingURIHelper.FORWARD_SLASH_CHAR))) { | |||
throw new InvalidFormatException( | |||
"A part name shall not be empty [M1.1]: " | |||
+ partURI.getPath()); | |||
"A part name shall not be empty [M1.1]: " | |||
+ partURI.getPath()); | |||
} | |||
} | |||
/** | |||
* Throws an exception if the part name has empty segments. [M1.3] | |||
* | |||
* Throws an exception if a segment any characters other than pchar | |||
* characters. [M1.6] | |||
* | |||
* Throws an exception if a segment contain percent-encoded forward slash | |||
* ('/'), or backward slash ('\') characters. [M1.7] | |||
* | |||
* Throws an exception if a segment contain percent-encoded unreserved | |||
* characters. [M1.8] | |||
* | |||
* Throws an exception if the specified part name's segments end with a dot | |||
* ('.') character. [M1.9] | |||
* | |||
* Throws an exception if a segment doesn't include at least one non-dot | |||
* character. [M1.10] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* if the specified URI contain an empty segments or if one the | |||
* segments contained in the part name, ends with a dot ('.') | |||
* character. | |||
*/ | |||
private static void throwExceptionIfPartNameHaveInvalidSegments(URI partUri) | |||
throws InvalidFormatException { | |||
if (partUri == null) { | |||
throw new IllegalArgumentException("partUri"); | |||
} | |||
} | |||
/** | |||
* Throws an exception if the part name has empty segments. [M1.3] | |||
* | |||
* Throws an exception if a segment any characters other than pchar | |||
* characters. [M1.6] | |||
* | |||
* Throws an exception if a segment contain percent-encoded forward slash | |||
* ('/'), or backward slash ('\') characters. [M1.7] | |||
* | |||
* Throws an exception if a segment contain percent-encoded unreserved | |||
* characters. [M1.8] | |||
* | |||
* Throws an exception if the specified part name's segments end with a dot | |||
* ('.') character. [M1.9] | |||
* | |||
* Throws an exception if a segment doesn't include at least one non-dot | |||
* character. [M1.10] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* if the specified URI contain an empty segments or if one the | |||
* segments contained in the part name, ends with a dot ('.') | |||
* character. | |||
*/ | |||
private static void throwExceptionIfPartNameHaveInvalidSegments(URI partUri) | |||
throws InvalidFormatException { | |||
if (partUri == null) { | |||
throw new IllegalArgumentException("partUri"); | |||
} | |||
// Split the URI into several part and analyze each | |||
String[] segments = partUri.toASCIIString() | |||
.replaceFirst("^"+PackagingURIHelper.FORWARD_SLASH_CHAR,"") | |||
.split(PackagingURIHelper.FORWARD_SLASH_STRING); | |||
if (segments.length < 1) { | |||
// Split the URI into several part and analyze each | |||
String[] segments = partUri.toASCIIString() | |||
.replaceFirst("^"+PackagingURIHelper.FORWARD_SLASH_CHAR,"") | |||
.split(PackagingURIHelper.FORWARD_SLASH_STRING); | |||
if (segments.length < 1) { | |||
throw new InvalidFormatException( | |||
"A part name shall not have empty segments [M1.3]: " + partUri.getPath()); | |||
"A part name shall not have empty segments [M1.3]: " + partUri.getPath()); | |||
} | |||
for (final String seg : segments) { | |||
if (seg == null || seg.isEmpty()) { | |||
throw new InvalidFormatException( | |||
"A part name shall not have empty segments [M1.3]: " + partUri.getPath()); | |||
} | |||
if (seg.endsWith(".")) { | |||
throw new InvalidFormatException( | |||
"A segment shall not end with a dot ('.') character [M1.9]: " + partUri.getPath()); | |||
} | |||
if (seg.replaceAll("\\\\.", "").isEmpty()) { | |||
// Normally will never been invoked with the previous | |||
// implementation rule [M1.9] | |||
throw new InvalidFormatException( | |||
"A segment shall include at least one non-dot character. [M1.10]: " + partUri.getPath()); | |||
} | |||
// Check for rule M1.6, M1.7, M1.8 | |||
checkPCharCompliance(seg); | |||
} | |||
} | |||
/** | |||
* Throws an exception if a segment any characters other than pchar | |||
* characters. [M1.6] | |||
* | |||
* Throws an exception if a segment contain percent-encoded forward slash | |||
* ('/'), or backward slash ('\') characters. [M1.7] | |||
* | |||
* Throws an exception if a segment contain percent-encoded unreserved | |||
* characters. [M1.8] | |||
* | |||
* @param segment | |||
* The segment to check | |||
*/ | |||
private static void checkPCharCompliance(String segment) | |||
throws InvalidFormatException { | |||
final int length = segment.length(); | |||
for (int i = 0; i < length; ++i) { | |||
final char c = segment.charAt(i); | |||
/* Check rule M1.6 */ | |||
if ( | |||
// Check for digit or letter | |||
isDigitOrLetter(c) || | |||
for (final String seg : segments) { | |||
if (seg == null || seg.isEmpty()) { | |||
throw new InvalidFormatException( | |||
"A part name shall not have empty segments [M1.3]: " + partUri.getPath()); | |||
} | |||
if (seg.endsWith(".")) { | |||
throw new InvalidFormatException( | |||
"A segment shall not end with a dot ('.') character [M1.9]: " + partUri.getPath()); | |||
} | |||
if (seg.replaceAll("\\\\.", "").isEmpty()) { | |||
// Normally will never been invoked with the previous | |||
// implementation rule [M1.9] | |||
throw new InvalidFormatException( | |||
"A segment shall include at least one non-dot character. [M1.10]: " + partUri.getPath()); | |||
} | |||
// Check for rule M1.6, M1.7, M1.8 | |||
checkPCharCompliance(seg); | |||
} | |||
} | |||
/** | |||
* Throws an exception if a segment any characters other than pchar | |||
* characters. [M1.6] | |||
* | |||
* Throws an exception if a segment contain percent-encoded forward slash | |||
* ('/'), or backward slash ('\') characters. [M1.7] | |||
* | |||
* Throws an exception if a segment contain percent-encoded unreserved | |||
* characters. [M1.8] | |||
* | |||
* @param segment | |||
* The segment to check | |||
*/ | |||
private static void checkPCharCompliance(String segment) | |||
throws InvalidFormatException { | |||
final int length = segment.length(); | |||
for (int i = 0; i < length; ++i) { | |||
final char c = segment.charAt(i); | |||
/* Check rule M1.6 */ | |||
if ( | |||
// Check for digit or letter | |||
isDigitOrLetter(c) || | |||
// Check "-", ".", "_", "~" | |||
RFC3986_PCHAR_UNRESERVED_SUP.indexOf(c) > -1 || | |||
// Check ":", "@" | |||
@@ -304,108 +304,108 @@ public final class PackagePartName implements Comparable<PackagePartName> { | |||
// Check "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" | |||
RFC3986_PCHAR_SUB_DELIMS.indexOf(c) > -1 | |||
) { | |||
continue; | |||
} | |||
continue; | |||
} | |||
if (c != '%') { | |||
throw new InvalidFormatException( | |||
if (c != '%') { | |||
throw new InvalidFormatException( | |||
"A segment shall not hold any characters other than pchar characters. [M1.6]"); | |||
} | |||
// We certainly found an encoded character, check for length | |||
// now ( '%' HEXDIGIT HEXDIGIT) | |||
if ((length - i) < 2 || !isHexDigit(segment.charAt(i+1)) || !isHexDigit(segment.charAt(i+2))) { | |||
throw new InvalidFormatException("The segment " + segment + " contain invalid encoded character !"); | |||
} | |||
// Decode the encoded character | |||
final char decodedChar = (char) Integer.parseInt(segment.substring(i + 1, i + 3), 16); | |||
i += 2; | |||
/* Check rule M1.7 */ | |||
if (decodedChar == '/' || decodedChar == '\\') { | |||
throw new InvalidFormatException( | |||
"A segment shall not contain percent-encoded forward slash ('/'), or backward slash ('\') characters. [M1.7]"); | |||
} | |||
/* Check rule M1.8 */ | |||
if ( | |||
// Check for unreserved character like define in RFC3986 | |||
isDigitOrLetter(decodedChar) || | |||
// Check for unreserved character "-", ".", "_", "~" | |||
RFC3986_PCHAR_UNRESERVED_SUP.indexOf(decodedChar) > -1 | |||
) { | |||
} | |||
// We certainly found an encoded character, check for length | |||
// now ( '%' HEXDIGIT HEXDIGIT) | |||
if ((length - i) < 2 || !isHexDigit(segment.charAt(i+1)) || !isHexDigit(segment.charAt(i+2))) { | |||
throw new InvalidFormatException("The segment " + segment + " contain invalid encoded character !"); | |||
} | |||
// Decode the encoded character | |||
final char decodedChar = (char) Integer.parseInt(segment.substring(i + 1, i + 3), 16); | |||
i += 2; | |||
/* Check rule M1.7 */ | |||
if (decodedChar == '/' || decodedChar == '\\') { | |||
throw new InvalidFormatException( | |||
"A segment shall not contain percent-encoded forward slash ('/'), or backward slash ('\') characters. [M1.7]"); | |||
} | |||
/* Check rule M1.8 */ | |||
if ( | |||
// Check for unreserved character like define in RFC3986 | |||
isDigitOrLetter(decodedChar) || | |||
// Check for unreserved character "-", ".", "_", "~" | |||
RFC3986_PCHAR_UNRESERVED_SUP.indexOf(decodedChar) > -1 | |||
) { | |||
throw new InvalidFormatException( | |||
"A segment shall not contain percent-encoded unreserved characters. [M1.8]"); | |||
} | |||
} | |||
} | |||
/** | |||
* Throws an exception if the specified part name doesn't start with a | |||
* forward slash character '/'. [M1.4] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* If the specified part name doesn't start with a forward slash | |||
* character '/'. | |||
*/ | |||
private static void throwExceptionIfPartNameNotStartsWithForwardSlashChar( | |||
URI partUri) throws InvalidFormatException { | |||
String uriPath = partUri.getPath(); | |||
if (uriPath.length() > 0 | |||
&& uriPath.charAt(0) != PackagingURIHelper.FORWARD_SLASH_CHAR) { | |||
} | |||
} | |||
} | |||
/** | |||
* Throws an exception if the specified part name doesn't start with a | |||
* forward slash character '/'. [M1.4] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* If the specified part name doesn't start with a forward slash | |||
* character '/'. | |||
*/ | |||
private static void throwExceptionIfPartNameNotStartsWithForwardSlashChar( | |||
URI partUri) throws InvalidFormatException { | |||
String uriPath = partUri.getPath(); | |||
if (uriPath.length() > 0 | |||
&& uriPath.charAt(0) != PackagingURIHelper.FORWARD_SLASH_CHAR) { | |||
throw new InvalidFormatException( | |||
"A part name shall start with a forward slash ('/') character [M1.4]: " | |||
+ partUri.getPath()); | |||
"A part name shall start with a forward slash ('/') character [M1.4]: " | |||
+ partUri.getPath()); | |||
} | |||
} | |||
/** | |||
* Throws an exception if the specified part name ends with a forwar slash | |||
* character '/'. [M1.5] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* If the specified part name ends with a forwar slash character | |||
* '/'. | |||
*/ | |||
private static void throwExceptionIfPartNameEndsWithForwardSlashChar( | |||
URI partUri) throws InvalidFormatException { | |||
String uriPath = partUri.getPath(); | |||
if (uriPath.length() > 0 | |||
&& uriPath.charAt(uriPath.length() - 1) == PackagingURIHelper.FORWARD_SLASH_CHAR) { | |||
} | |||
/** | |||
* Throws an exception if the specified part name ends with a forwar slash | |||
* character '/'. [M1.5] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* If the specified part name ends with a forwar slash character | |||
* '/'. | |||
*/ | |||
private static void throwExceptionIfPartNameEndsWithForwardSlashChar( | |||
URI partUri) throws InvalidFormatException { | |||
String uriPath = partUri.getPath(); | |||
if (uriPath.length() > 0 | |||
&& uriPath.charAt(uriPath.length() - 1) == PackagingURIHelper.FORWARD_SLASH_CHAR) { | |||
throw new InvalidFormatException( | |||
"A part name shall not have a forward slash as the last character [M1.5]: " | |||
+ partUri.getPath()); | |||
"A part name shall not have a forward slash as the last character [M1.5]: " | |||
+ partUri.getPath()); | |||
} | |||
} | |||
/** | |||
* Throws an exception if the specified URI is absolute. | |||
* | |||
* @param partUri | |||
* The URI to check. | |||
* @throws InvalidFormatException | |||
* Throws if the specified URI is absolute. | |||
*/ | |||
private static void throwExceptionIfAbsoluteUri(URI partUri) throws InvalidFormatException { | |||
if (partUri.isAbsolute()) { | |||
} | |||
/** | |||
* Throws an exception if the specified URI is absolute. | |||
* | |||
* @param partUri | |||
* The URI to check. | |||
* @throws InvalidFormatException | |||
* Throws if the specified URI is absolute. | |||
*/ | |||
private static void throwExceptionIfAbsoluteUri(URI partUri) throws InvalidFormatException { | |||
if (partUri.isAbsolute()) { | |||
throw new InvalidFormatException("Absolute URI forbidden: " + partUri); | |||
} | |||
} | |||
/** | |||
* Compare two part names following the rule M1.12 : | |||
* | |||
* Part name equivalence is determined by comparing part names as | |||
* case-insensitive ASCII strings. Packages shall not contain equivalent | |||
* part names and package implementers shall neither create nor recognize | |||
* packages with equivalent part names. [M1.12] | |||
*/ | |||
} | |||
/** | |||
* Compare two part names following the rule M1.12 : | |||
* | |||
* Part name equivalence is determined by comparing part names as | |||
* case-insensitive ASCII strings. Packages shall not contain equivalent | |||
* part names and package implementers shall neither create nor recognize | |||
* packages with equivalent part names. [M1.12] | |||
*/ | |||
@Override | |||
public int compareTo(PackagePartName other) { | |||
// compare with natural sort order | |||
@@ -413,64 +413,64 @@ public final class PackagePartName implements Comparable<PackagePartName> { | |||
} | |||
/** | |||
* Retrieves the extension of the part name if any. If there is no extension | |||
* returns an empty String. Example : '/document/content.xml' => 'xml' | |||
* | |||
* @return The extension of the part name. | |||
*/ | |||
public String getExtension() { | |||
String fragment = this.partNameURI.getPath(); | |||
if (fragment.length() > 0) { | |||
int i = fragment.lastIndexOf('.'); | |||
if (i > -1) { | |||
/** | |||
* Retrieves the extension of the part name if any. If there is no extension | |||
* returns an empty String. Example : '/document/content.xml' => 'xml' | |||
* | |||
* @return The extension of the part name. | |||
*/ | |||
public String getExtension() { | |||
String fragment = this.partNameURI.getPath(); | |||
if (fragment.length() > 0) { | |||
int i = fragment.lastIndexOf('.'); | |||
if (i > -1) { | |||
return fragment.substring(i + 1); | |||
} | |||
} | |||
return ""; | |||
} | |||
/** | |||
* Get this part name. | |||
* | |||
* @return The name of this part name. | |||
*/ | |||
public String getName() { | |||
return getURI().toASCIIString(); | |||
} | |||
/** | |||
* Part name equivalence is determined by comparing part names as | |||
* case-insensitive ASCII strings. Packages shall not contain equivalent | |||
* part names and package implementers shall neither create nor recognize | |||
* packages with equivalent part names. [M1.12] | |||
*/ | |||
@Override | |||
public boolean equals(Object other) { | |||
} | |||
return ""; | |||
} | |||
/** | |||
* Get this part name. | |||
* | |||
* @return The name of this part name. | |||
*/ | |||
public String getName() { | |||
return getURI().toASCIIString(); | |||
} | |||
/** | |||
* Part name equivalence is determined by comparing part names as | |||
* case-insensitive ASCII strings. Packages shall not contain equivalent | |||
* part names and package implementers shall neither create nor recognize | |||
* packages with equivalent part names. [M1.12] | |||
*/ | |||
@Override | |||
public boolean equals(Object other) { | |||
return (other instanceof PackagePartName) && | |||
compare(this.getName(), ((PackagePartName)other).getName()) == 0; | |||
} | |||
@Override | |||
public int hashCode() { | |||
return getName().toLowerCase(Locale.ROOT).hashCode(); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return getName().toLowerCase(Locale.ROOT).hashCode(); | |||
} | |||
@Override | |||
public String toString() { | |||
return getName(); | |||
} | |||
@Override | |||
public String toString() { | |||
return getName(); | |||
} | |||
/* Getters and setters */ | |||
/* Getters and setters */ | |||
/** | |||
* Part name property getter. | |||
* | |||
* @return This part name URI. | |||
*/ | |||
public URI getURI() { | |||
return this.partNameURI; | |||
} | |||
/** | |||
* Part name property getter. | |||
* | |||
* @return This part name URI. | |||
*/ | |||
public URI getURI() { | |||
return this.partNameURI; | |||
} | |||
/** | |||
@@ -489,10 +489,10 @@ public final class PackagePartName implements Comparable<PackagePartName> { | |||
* case-insensitive ASCII strings. Packages shall not contain equivalent | |||
* part names and package implementers shall neither create nor recognize | |||
* packages with equivalent part names. [M1.12] | |||
* | |||
* @param obj1 first {@code PackagePartName} to compare | |||
* @param obj2 second {@code PackagePartName} to compare | |||
* @return a negative integer, zero, or a positive integer as the first argument is less than, | |||
* | |||
* @param obj1 first {@code PackagePartName} to compare | |||
* @param obj2 second {@code PackagePartName} to compare | |||
* @return a negative integer, zero, or a positive integer as the first argument is less than, | |||
* equal to, or greater than the second. | |||
*/ | |||
public static int compare(PackagePartName obj1, PackagePartName obj2) { |
@@ -27,182 +27,182 @@ import java.util.Objects; | |||
*/ | |||
public final class PackageRelationship { | |||
private static URI containerRelationshipPart; | |||
static { | |||
try { | |||
containerRelationshipPart = new URI("/_rels/.rels"); | |||
} catch (URISyntaxException e) { | |||
// Do nothing | |||
} | |||
} | |||
/* XML markup */ | |||
public static final String ID_ATTRIBUTE_NAME = "Id"; | |||
public static final String RELATIONSHIPS_TAG_NAME = "Relationships"; | |||
public static final String RELATIONSHIP_TAG_NAME = "Relationship"; | |||
public static final String TARGET_ATTRIBUTE_NAME = "Target"; | |||
public static final String TARGET_MODE_ATTRIBUTE_NAME = "TargetMode"; | |||
public static final String TYPE_ATTRIBUTE_NAME = "Type"; | |||
/* End XML markup */ | |||
/** | |||
* Relation id. | |||
*/ | |||
private final String id; | |||
/** | |||
* Reference to the package. | |||
*/ | |||
private final OPCPackage container; | |||
/** | |||
* Relationship type | |||
*/ | |||
private final String relationshipType; | |||
/** | |||
* Part of this relationship source | |||
*/ | |||
private final PackagePart source; | |||
/** | |||
* Targeting mode [Internal|External] | |||
*/ | |||
private final TargetMode targetMode; | |||
/** | |||
* Target URI | |||
*/ | |||
private final URI targetUri; | |||
/** | |||
* Constructor. | |||
*/ | |||
public PackageRelationship(OPCPackage pkg, PackagePart sourcePart, | |||
URI targetUri, TargetMode targetMode, String relationshipType, | |||
String id) { | |||
if (pkg == null) | |||
throw new IllegalArgumentException("pkg"); | |||
if (targetUri == null) | |||
throw new IllegalArgumentException("targetUri"); | |||
if (relationshipType == null) | |||
throw new IllegalArgumentException("relationshipType"); | |||
if (id == null) | |||
throw new IllegalArgumentException("id"); | |||
this.container = pkg; | |||
this.source = sourcePart; | |||
this.targetUri = targetUri; | |||
this.targetMode = targetMode; | |||
this.relationshipType = relationshipType; | |||
this.id = id; | |||
} | |||
@Override | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof PackageRelationship)) { | |||
return false; | |||
} | |||
PackageRelationship rel = (PackageRelationship) obj; | |||
return (this.id.equals(rel.id) | |||
&& this.relationshipType.equals(rel.relationshipType) | |||
&& (rel.source == null || rel.source.equals(this.source)) | |||
&& this.targetMode == rel.targetMode && this.targetUri | |||
.equals(rel.targetUri)); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id,relationshipType,source,targetMode,targetUri); | |||
} | |||
/* Getters */ | |||
public static URI getContainerPartRelationship() { | |||
return containerRelationshipPart; | |||
} | |||
/** | |||
* @return the container | |||
*/ | |||
public OPCPackage getPackage() { | |||
return container; | |||
} | |||
/** | |||
* @return the id | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the relationshipType | |||
*/ | |||
public String getRelationshipType() { | |||
return relationshipType; | |||
} | |||
/** | |||
* @return the source | |||
*/ | |||
public PackagePart getSource() { | |||
return source; | |||
} | |||
/** | |||
* | |||
* @return URL of the source part of this relationship | |||
*/ | |||
public URI getSourceURI() { | |||
if (source == null) { | |||
return PackagingURIHelper.PACKAGE_ROOT_URI; | |||
} | |||
return source._partName.getURI(); | |||
} | |||
/** | |||
* @return the targetMode | |||
*/ | |||
public TargetMode getTargetMode() { | |||
return targetMode; | |||
} | |||
/** | |||
* @return the targetUri | |||
*/ | |||
public URI getTargetURI() { | |||
// If it's an external target, we don't | |||
// need to apply our normal validation rules | |||
if(targetMode == TargetMode.EXTERNAL) { | |||
return targetUri; | |||
} | |||
// Internal target | |||
// If it isn't absolute, resolve it relative | |||
// to ourselves | |||
if (!targetUri.toASCIIString().startsWith("/")) { | |||
// So it's a relative part name, try to resolve it | |||
return PackagingURIHelper.resolvePartUri(getSourceURI(), targetUri); | |||
} | |||
return targetUri; | |||
} | |||
@Override | |||
public String toString() { | |||
return "id=" + id + | |||
" - container=" + container + | |||
" - relationshipType=" + relationshipType + | |||
(source == null ? " - source=null" : " - source=" + getSourceURI().toASCIIString()) + | |||
" - target=" + getTargetURI().toASCIIString() + | |||
(targetMode == null ? ",targetMode=null" : ",targetMode=" + targetMode); | |||
} | |||
private static URI containerRelationshipPart; | |||
static { | |||
try { | |||
containerRelationshipPart = new URI("/_rels/.rels"); | |||
} catch (URISyntaxException e) { | |||
// Do nothing | |||
} | |||
} | |||
/* XML markup */ | |||
public static final String ID_ATTRIBUTE_NAME = "Id"; | |||
public static final String RELATIONSHIPS_TAG_NAME = "Relationships"; | |||
public static final String RELATIONSHIP_TAG_NAME = "Relationship"; | |||
public static final String TARGET_ATTRIBUTE_NAME = "Target"; | |||
public static final String TARGET_MODE_ATTRIBUTE_NAME = "TargetMode"; | |||
public static final String TYPE_ATTRIBUTE_NAME = "Type"; | |||
/* End XML markup */ | |||
/** | |||
* Relation id. | |||
*/ | |||
private final String id; | |||
/** | |||
* Reference to the package. | |||
*/ | |||
private final OPCPackage container; | |||
/** | |||
* Relationship type | |||
*/ | |||
private final String relationshipType; | |||
/** | |||
* Part of this relationship source | |||
*/ | |||
private final PackagePart source; | |||
/** | |||
* Targeting mode [Internal|External] | |||
*/ | |||
private final TargetMode targetMode; | |||
/** | |||
* Target URI | |||
*/ | |||
private final URI targetUri; | |||
/** | |||
* Constructor. | |||
*/ | |||
public PackageRelationship(OPCPackage pkg, PackagePart sourcePart, | |||
URI targetUri, TargetMode targetMode, String relationshipType, | |||
String id) { | |||
if (pkg == null) | |||
throw new IllegalArgumentException("pkg"); | |||
if (targetUri == null) | |||
throw new IllegalArgumentException("targetUri"); | |||
if (relationshipType == null) | |||
throw new IllegalArgumentException("relationshipType"); | |||
if (id == null) | |||
throw new IllegalArgumentException("id"); | |||
this.container = pkg; | |||
this.source = sourcePart; | |||
this.targetUri = targetUri; | |||
this.targetMode = targetMode; | |||
this.relationshipType = relationshipType; | |||
this.id = id; | |||
} | |||
@Override | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof PackageRelationship)) { | |||
return false; | |||
} | |||
PackageRelationship rel = (PackageRelationship) obj; | |||
return (this.id.equals(rel.id) | |||
&& this.relationshipType.equals(rel.relationshipType) | |||
&& (rel.source == null || rel.source.equals(this.source)) | |||
&& this.targetMode == rel.targetMode && this.targetUri | |||
.equals(rel.targetUri)); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id,relationshipType,source,targetMode,targetUri); | |||
} | |||
/* Getters */ | |||
public static URI getContainerPartRelationship() { | |||
return containerRelationshipPart; | |||
} | |||
/** | |||
* @return the container | |||
*/ | |||
public OPCPackage getPackage() { | |||
return container; | |||
} | |||
/** | |||
* @return the id | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the relationshipType | |||
*/ | |||
public String getRelationshipType() { | |||
return relationshipType; | |||
} | |||
/** | |||
* @return the source | |||
*/ | |||
public PackagePart getSource() { | |||
return source; | |||
} | |||
/** | |||
* | |||
* @return URL of the source part of this relationship | |||
*/ | |||
public URI getSourceURI() { | |||
if (source == null) { | |||
return PackagingURIHelper.PACKAGE_ROOT_URI; | |||
} | |||
return source._partName.getURI(); | |||
} | |||
/** | |||
* @return the targetMode | |||
*/ | |||
public TargetMode getTargetMode() { | |||
return targetMode; | |||
} | |||
/** | |||
* @return the targetUri | |||
*/ | |||
public URI getTargetURI() { | |||
// If it's an external target, we don't | |||
// need to apply our normal validation rules | |||
if(targetMode == TargetMode.EXTERNAL) { | |||
return targetUri; | |||
} | |||
// Internal target | |||
// If it isn't absolute, resolve it relative | |||
// to ourselves | |||
if (!targetUri.toASCIIString().startsWith("/")) { | |||
// So it's a relative part name, try to resolve it | |||
return PackagingURIHelper.resolvePartUri(getSourceURI(), targetUri); | |||
} | |||
return targetUri; | |||
} | |||
@Override | |||
public String toString() { | |||
return "id=" + id + | |||
" - container=" + container + | |||
" - relationshipType=" + relationshipType + | |||
(source == null ? " - source=null" : " - source=" + getSourceURI().toASCIIString()) + | |||
" - target=" + getTargetURI().toASCIIString() + | |||
(targetMode == null ? ",targetMode=null" : ",targetMode=" + targetMode); | |||
} | |||
} |
@@ -22,137 +22,137 @@ import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
public interface RelationshipSource { | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* | |||
* @param targetPartName | |||
* Name of the target part. This one must be relative to the | |||
* source root directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @return The newly created and added relationship | |||
*/ | |||
PackageRelationship addRelationship( | |||
PackagePartName targetPartName, TargetMode targetMode, | |||
String relationshipType); | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* <p> | |||
* Check rule M1.25: The Relationships part shall not have relationships to | |||
* any other part. Package implementers shall enforce this requirement upon | |||
* the attempt to create such a relationship and shall treat any such | |||
* relationship as invalid. | |||
* </p> | |||
* @param targetPartName | |||
* Name of the target part. This one must be relative to the | |||
* source root directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @param id | |||
* Relationship unique id. | |||
* @return The newly created and added relationship | |||
*/ | |||
PackageRelationship addRelationship( | |||
PackagePartName targetPartName, TargetMode targetMode, | |||
String relationshipType, String id); | |||
/** | |||
* Adds an external relationship to a part | |||
* (except relationships part). | |||
* | |||
* The targets of external relationships are not | |||
* subject to the same validity checks that internal | |||
* ones are, as the contents is potentially | |||
* any file, URL or similar. | |||
* | |||
* @param target External target of the relationship | |||
* @param relationshipType Type of relationship. | |||
* @return The newly created and added relationship | |||
*/ | |||
PackageRelationship addExternalRelationship(String target, String relationshipType); | |||
/** | |||
* Adds an external relationship to a part | |||
* (except relationships part). | |||
* | |||
* The targets of external relationships are not | |||
* subject to the same validity checks that internal | |||
* ones are, as the contents is potentially | |||
* any file, URL or similar. | |||
* | |||
* @param target External target of the relationship | |||
* @param relationshipType Type of relationship. | |||
* @param id Relationship unique id. | |||
* @return The newly created and added relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String, java.lang.String) | |||
*/ | |||
PackageRelationship addExternalRelationship(String target, String relationshipType, String id); | |||
/** | |||
* Delete all the relationships attached to this. | |||
*/ | |||
void clearRelationships(); | |||
/** | |||
* Delete the relationship specified by its id. | |||
* | |||
* @param id | |||
* The ID identified the part to delete. | |||
*/ | |||
void removeRelationship(String id); | |||
/** | |||
* Retrieve all the relationships attached to this. | |||
* | |||
* @return This part's relationships. | |||
*/ | |||
PackageRelationshipCollection getRelationships() throws OpenXML4JException; | |||
/** | |||
* Retrieves a package relationship from its id. | |||
* | |||
* @param id | |||
* ID of the package relationship to retrieve. | |||
* @return The package relationship | |||
*/ | |||
PackageRelationship getRelationship(String id); | |||
/** | |||
* Retrieve all relationships attached to this part which have the specified | |||
* type. | |||
* | |||
* @param relationshipType | |||
* Relationship type filter. | |||
* @return All relationships from this part that have the specified type. | |||
* @throws InvalidFormatException | |||
* If an error occurs while parsing the part. | |||
* @throws InvalidOperationException | |||
* If the package is open in write only mode. | |||
*/ | |||
PackageRelationshipCollection getRelationshipsByType(String relationshipType) | |||
throws IllegalArgumentException, OpenXML4JException; | |||
/** | |||
* Knows if the part have any relationships. | |||
* | |||
* @return <b>true</b> if the part have at least one relationship else | |||
* <b>false</b>. | |||
*/ | |||
boolean hasRelationships(); | |||
/** | |||
* Checks if the specified relationship is part of this package part. | |||
* | |||
* @param rel | |||
* The relationship to check. | |||
* @return <b>true</b> if the specified relationship exists in this part, | |||
* else returns <b>false</b> | |||
*/ | |||
boolean isRelationshipExists(PackageRelationship rel); | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* | |||
* @param targetPartName | |||
* Name of the target part. This one must be relative to the | |||
* source root directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @return The newly created and added relationship | |||
*/ | |||
PackageRelationship addRelationship( | |||
PackagePartName targetPartName, TargetMode targetMode, | |||
String relationshipType); | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* <p> | |||
* Check rule M1.25: The Relationships part shall not have relationships to | |||
* any other part. Package implementers shall enforce this requirement upon | |||
* the attempt to create such a relationship and shall treat any such | |||
* relationship as invalid. | |||
* </p> | |||
* @param targetPartName | |||
* Name of the target part. This one must be relative to the | |||
* source root directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @param id | |||
* Relationship unique id. | |||
* @return The newly created and added relationship | |||
*/ | |||
PackageRelationship addRelationship( | |||
PackagePartName targetPartName, TargetMode targetMode, | |||
String relationshipType, String id); | |||
/** | |||
* Adds an external relationship to a part | |||
* (except relationships part). | |||
* | |||
* The targets of external relationships are not | |||
* subject to the same validity checks that internal | |||
* ones are, as the contents is potentially | |||
* any file, URL or similar. | |||
* | |||
* @param target External target of the relationship | |||
* @param relationshipType Type of relationship. | |||
* @return The newly created and added relationship | |||
*/ | |||
PackageRelationship addExternalRelationship(String target, String relationshipType); | |||
/** | |||
* Adds an external relationship to a part | |||
* (except relationships part). | |||
* | |||
* The targets of external relationships are not | |||
* subject to the same validity checks that internal | |||
* ones are, as the contents is potentially | |||
* any file, URL or similar. | |||
* | |||
* @param target External target of the relationship | |||
* @param relationshipType Type of relationship. | |||
* @param id Relationship unique id. | |||
* @return The newly created and added relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String, java.lang.String) | |||
*/ | |||
PackageRelationship addExternalRelationship(String target, String relationshipType, String id); | |||
/** | |||
* Delete all the relationships attached to this. | |||
*/ | |||
void clearRelationships(); | |||
/** | |||
* Delete the relationship specified by its id. | |||
* | |||
* @param id | |||
* The ID identified the part to delete. | |||
*/ | |||
void removeRelationship(String id); | |||
/** | |||
* Retrieve all the relationships attached to this. | |||
* | |||
* @return This part's relationships. | |||
*/ | |||
PackageRelationshipCollection getRelationships() throws OpenXML4JException; | |||
/** | |||
* Retrieves a package relationship from its id. | |||
* | |||
* @param id | |||
* ID of the package relationship to retrieve. | |||
* @return The package relationship | |||
*/ | |||
PackageRelationship getRelationship(String id); | |||
/** | |||
* Retrieve all relationships attached to this part which have the specified | |||
* type. | |||
* | |||
* @param relationshipType | |||
* Relationship type filter. | |||
* @return All relationships from this part that have the specified type. | |||
* @throws InvalidFormatException | |||
* If an error occurs while parsing the part. | |||
* @throws InvalidOperationException | |||
* If the package is open in write only mode. | |||
*/ | |||
PackageRelationshipCollection getRelationshipsByType(String relationshipType) | |||
throws IllegalArgumentException, OpenXML4JException; | |||
/** | |||
* Knows if the part have any relationships. | |||
* | |||
* @return <b>true</b> if the part have at least one relationship else | |||
* <b>false</b>. | |||
*/ | |||
boolean hasRelationships(); | |||
/** | |||
* Checks if the specified relationship is part of this package part. | |||
* | |||
* @param rel | |||
* The relationship to check. | |||
* @return <b>true</b> if the specified relationship exists in this part, | |||
* else returns <b>false</b> | |||
*/ | |||
boolean isRelationshipExists(PackageRelationship rel); | |||
} |
@@ -36,68 +36,68 @@ import org.w3c.dom.Document; | |||
public final class StreamHelper { | |||
private StreamHelper() { | |||
// Do nothing | |||
} | |||
private StreamHelper() { | |||
// Do nothing | |||
} | |||
/** | |||
* Save the document object in the specified output stream. | |||
* | |||
* @param xmlContent | |||
* The XML document. | |||
* @param outStream | |||
* The OutputStream in which the XML document will be written. | |||
* @return <b>true</b> if the xml is successfully written in the stream, | |||
* else <b>false</b>. | |||
*/ | |||
public static boolean saveXmlInStream(Document xmlContent, | |||
OutputStream outStream) { | |||
try { | |||
Transformer trans = XMLHelper.newTransformer(); | |||
Source xmlSource = new DOMSource(xmlContent); | |||
// prevent close of stream by transformer: | |||
Result outputTarget = new StreamResult(new FilterOutputStream( | |||
outStream) { | |||
@Override | |||
public void write(byte[] b, int off, int len) | |||
throws IOException { | |||
out.write(b, off, len); | |||
} | |||
/** | |||
* Save the document object in the specified output stream. | |||
* | |||
* @param xmlContent | |||
* The XML document. | |||
* @param outStream | |||
* The OutputStream in which the XML document will be written. | |||
* @return <b>true</b> if the xml is successfully written in the stream, | |||
* else <b>false</b>. | |||
*/ | |||
public static boolean saveXmlInStream(Document xmlContent, | |||
OutputStream outStream) { | |||
try { | |||
Transformer trans = XMLHelper.newTransformer(); | |||
Source xmlSource = new DOMSource(xmlContent); | |||
// prevent close of stream by transformer: | |||
Result outputTarget = new StreamResult(new FilterOutputStream( | |||
outStream) { | |||
@Override | |||
public void write(byte[] b, int off, int len) | |||
throws IOException { | |||
out.write(b, off, len); | |||
} | |||
@Override | |||
public void close() throws IOException { | |||
out.flush(); // only flush, don't close! | |||
} | |||
}); | |||
// xmlContent.setXmlStandalone(true); | |||
trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); | |||
// don't indent xml documents, the indent will cause errors in calculating the xml signature | |||
// because of different handling of linebreaks in Windows/Unix | |||
// see https://stackoverflow.com/questions/36063375 | |||
trans.setOutputProperty(OutputKeys.INDENT, "no"); | |||
trans.setOutputProperty(OutputKeys.STANDALONE, "yes"); | |||
trans.transform(xmlSource, outputTarget); | |||
} catch (TransformerException e) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
@Override | |||
public void close() throws IOException { | |||
out.flush(); // only flush, don't close! | |||
} | |||
}); | |||
// xmlContent.setXmlStandalone(true); | |||
trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); | |||
// don't indent xml documents, the indent will cause errors in calculating the xml signature | |||
// because of different handling of linebreaks in Windows/Unix | |||
// see https://stackoverflow.com/questions/36063375 | |||
trans.setOutputProperty(OutputKeys.INDENT, "no"); | |||
trans.setOutputProperty(OutputKeys.STANDALONE, "yes"); | |||
trans.transform(xmlSource, outputTarget); | |||
} catch (TransformerException e) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Copy the input stream into the output stream. | |||
* | |||
* @param inStream | |||
* The source stream. | |||
* @param outStream | |||
* The destination stream. | |||
* @return <b>true</b> if the operation succeed, else return <b>false</b>. | |||
*/ | |||
public static boolean copyStream(InputStream inStream, OutputStream outStream) { | |||
try { | |||
IOUtils.copy(inStream, outStream); | |||
return true; | |||
} catch (Exception e) { | |||
return false; | |||
} | |||
} | |||
/** | |||
* Copy the input stream into the output stream. | |||
* | |||
* @param inStream | |||
* The source stream. | |||
* @param outStream | |||
* The destination stream. | |||
* @return <b>true</b> if the operation succeed, else return <b>false</b>. | |||
*/ | |||
public static boolean copyStream(InputStream inStream, OutputStream outStream) { | |||
try { | |||
IOUtils.copy(inStream, outStream); | |||
return true; | |||
} catch (Exception e) { | |||
return false; | |||
} | |||
} | |||
} |
@@ -24,7 +24,7 @@ package org.apache.poi.openxml4j.opc; | |||
*/ | |||
public enum TargetMode { | |||
/** The relationship references a part that is inside the package. */ | |||
INTERNAL, | |||
INTERNAL, | |||
/** The relationship references a resource that is external to the package. */ | |||
EXTERNAL | |||
EXTERNAL | |||
} |
@@ -407,151 +407,151 @@ public final class ZipPackage extends OPCPackage { | |||
// Flush the package | |||
flush(); | |||
if (this.originalPackagePath == null || this.originalPackagePath.isEmpty()) { | |||
return; | |||
} | |||
if (this.originalPackagePath == null || this.originalPackagePath.isEmpty()) { | |||
return; | |||
} | |||
// Save the content | |||
File targetFile = new File(this.originalPackagePath); | |||
if (!targetFile.exists()) { | |||
// Save the content | |||
File targetFile = new File(this.originalPackagePath); | |||
if (!targetFile.exists()) { | |||
throw new InvalidOperationException( | |||
"Can't close a package not previously open with the open() method !"); | |||
} | |||
// Case of a package previously open | |||
String tempFileName = generateTempFileName(FileHelper.getDirectory(targetFile)); | |||
File tempFile = TempFile.createTempFile(tempFileName, ".tmp"); | |||
// Case of a package previously open | |||
String tempFileName = generateTempFileName(FileHelper.getDirectory(targetFile)); | |||
File tempFile = TempFile.createTempFile(tempFileName, ".tmp"); | |||
// Save the final package to a temporary file | |||
// Save the final package to a temporary file | |||
boolean success = false; | |||
try { | |||
save(tempFile); | |||
try { | |||
save(tempFile); | |||
success = true; | |||
} finally { | |||
} finally { | |||
// Close the current zip file, so we can overwrite it on all platforms | |||
IOUtils.closeQuietly(this.zipArchive); | |||
try { | |||
// Copy the new file over the old one if save() succeed | |||
try { | |||
// Copy the new file over the old one if save() succeed | |||
if(success) { | |||
FileHelper.copyFile(tempFile, targetFile); | |||
FileHelper.copyFile(tempFile, targetFile); | |||
} | |||
} finally { | |||
// Either the save operation succeed or not, we delete the temporary file | |||
if (!tempFile.delete()) { | |||
} finally { | |||
// Either the save operation succeed or not, we delete the temporary file | |||
if (!tempFile.delete()) { | |||
LOG.atWarn().log("The temporary file: '{}' cannot be deleted ! Make sure that no other application use it.", targetFile.getAbsolutePath()); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Create a unique identifier to be use as a temp file name. | |||
* | |||
* @return A unique identifier use to be use as a temp file name. | |||
*/ | |||
private synchronized String generateTempFileName(File directory) { | |||
File tmpFilename; | |||
do { | |||
tmpFilename = new File(directory.getAbsoluteFile() + File.separator | |||
+ "OpenXML4J" + System.nanoTime()); | |||
} while (tmpFilename.exists()); | |||
return FileHelper.getFilename(tmpFilename.getAbsoluteFile()); | |||
} | |||
/** | |||
* Close the package without saving the document. Discard all the changes | |||
* made to this package. | |||
*/ | |||
@Override | |||
protected void revertImpl() { | |||
try { | |||
if (this.zipArchive != null) { | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Create a unique identifier to be use as a temp file name. | |||
* | |||
* @return A unique identifier use to be use as a temp file name. | |||
*/ | |||
private synchronized String generateTempFileName(File directory) { | |||
File tmpFilename; | |||
do { | |||
tmpFilename = new File(directory.getAbsoluteFile() + File.separator | |||
+ "OpenXML4J" + System.nanoTime()); | |||
} while (tmpFilename.exists()); | |||
return FileHelper.getFilename(tmpFilename.getAbsoluteFile()); | |||
} | |||
/** | |||
* Close the package without saving the document. Discard all the changes | |||
* made to this package. | |||
*/ | |||
@Override | |||
protected void revertImpl() { | |||
try { | |||
if (this.zipArchive != null) { | |||
this.zipArchive.close(); | |||
} | |||
} catch (IOException e) { | |||
// Do nothing, user dont have to know | |||
} | |||
} | |||
/** | |||
* Save this package into the specified stream | |||
* | |||
* | |||
* @param outputStream | |||
* The stream use to save this package. | |||
* | |||
* @see #save(OutputStream) | |||
*/ | |||
@Override | |||
public void saveImpl(OutputStream outputStream) { | |||
// Check that the document was open in write mode | |||
throwExceptionIfReadOnly(); | |||
final ZipArchiveOutputStream zos = (outputStream instanceof ZipArchiveOutputStream) | |||
} catch (IOException e) { | |||
// Do nothing, user dont have to know | |||
} | |||
} | |||
/** | |||
* Save this package into the specified stream | |||
* | |||
* | |||
* @param outputStream | |||
* The stream use to save this package. | |||
* | |||
* @see #save(OutputStream) | |||
*/ | |||
@Override | |||
public void saveImpl(OutputStream outputStream) { | |||
// Check that the document was open in write mode | |||
throwExceptionIfReadOnly(); | |||
final ZipArchiveOutputStream zos = (outputStream instanceof ZipArchiveOutputStream) | |||
? (ZipArchiveOutputStream) outputStream : new ZipArchiveOutputStream(outputStream); | |||
try { | |||
// If the core properties part does not exist in the part list, | |||
// we save it as well | |||
if (this.getPartsByRelationshipType(PackageRelationshipTypes.CORE_PROPERTIES).size() == 0 && | |||
try { | |||
// If the core properties part does not exist in the part list, | |||
// we save it as well | |||
if (this.getPartsByRelationshipType(PackageRelationshipTypes.CORE_PROPERTIES).size() == 0 && | |||
this.getPartsByRelationshipType(PackageRelationshipTypes.CORE_PROPERTIES_ECMA376).size() == 0 ) { | |||
LOG.atDebug().log("Save core properties part"); | |||
// Ensure that core properties are added if missing | |||
getPackageProperties(); | |||
// Add core properties to part list ... | |||
addPackagePart(this.packageProperties); | |||
// ... and to add its relationship ... | |||
this.relationships.addRelationship(this.packageProperties | |||
.getPartName().getURI(), TargetMode.INTERNAL, | |||
PackageRelationshipTypes.CORE_PROPERTIES, null); | |||
// ... and the content if it has not been added yet. | |||
if (!this.contentTypeManager | |||
.isContentTypeRegister(ContentTypes.CORE_PROPERTIES_PART)) { | |||
this.contentTypeManager.addContentType( | |||
this.packageProperties.getPartName(), | |||
ContentTypes.CORE_PROPERTIES_PART); | |||
} | |||
} | |||
LOG.atDebug().log("Save core properties part"); | |||
// Ensure that core properties are added if missing | |||
getPackageProperties(); | |||
// Add core properties to part list ... | |||
addPackagePart(this.packageProperties); | |||
// ... and to add its relationship ... | |||
this.relationships.addRelationship(this.packageProperties | |||
.getPartName().getURI(), TargetMode.INTERNAL, | |||
PackageRelationshipTypes.CORE_PROPERTIES, null); | |||
// ... and the content if it has not been added yet. | |||
if (!this.contentTypeManager | |||
.isContentTypeRegister(ContentTypes.CORE_PROPERTIES_PART)) { | |||
this.contentTypeManager.addContentType( | |||
this.packageProperties.getPartName(), | |||
ContentTypes.CORE_PROPERTIES_PART); | |||
} | |||
} | |||
// Save content type part. | |||
LOG.atDebug().log("Save content types part"); | |||
this.contentTypeManager.save(zos); | |||
// Save package relationships part. | |||
LOG.atDebug().log("Save package relationships"); | |||
ZipPartMarshaller.marshallRelationshipPart(this.getRelationships(), | |||
PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME, | |||
zos); | |||
// Save parts. | |||
for (PackagePart part : getParts()) { | |||
// If the part is a relationship part, we don't save it, it's | |||
// the source part that will do the job. | |||
if (part.isRelationshipPart()) { | |||
// Save package relationships part. | |||
LOG.atDebug().log("Save package relationships"); | |||
ZipPartMarshaller.marshallRelationshipPart(this.getRelationships(), | |||
PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME, | |||
zos); | |||
// Save parts. | |||
for (PackagePart part : getParts()) { | |||
// If the part is a relationship part, we don't save it, it's | |||
// the source part that will do the job. | |||
if (part.isRelationshipPart()) { | |||
continue; | |||
} | |||
final PackagePartName ppn = part.getPartName(); | |||
final PackagePartName ppn = part.getPartName(); | |||
LOG.atDebug().log(() -> new SimpleMessage("Save part '" + ZipHelper.getZipItemNameFromOPCName(ppn.getName()) + "'")); | |||
final PartMarshaller marshaller = partMarshallers.get(part._contentType); | |||
final PartMarshaller marshaller = partMarshallers.get(part._contentType); | |||
final PartMarshaller pm = (marshaller != null) ? marshaller : defaultPartMarshaller; | |||
final PartMarshaller pm = (marshaller != null) ? marshaller : defaultPartMarshaller; | |||
if (!pm.marshall(part, zos)) { | |||
String errMsg = "The part " + ppn.getURI() + " failed to be saved in the stream with marshaller " + pm + | |||
". Enable logging via Log4j 2 for more details."; | |||
throw new OpenXML4JException(errMsg); | |||
} | |||
} | |||
} | |||
zos.finish(); | |||
} catch (OpenXML4JRuntimeException e) { | |||
// no need to wrap this type of Exception | |||
throw e; | |||
} catch (Exception e) { | |||
} catch (OpenXML4JRuntimeException e) { | |||
// no need to wrap this type of Exception | |||
throw e; | |||
} catch (Exception e) { | |||
throw new OpenXML4JRuntimeException( | |||
"Fail to save: an error occurs while saving the package : " | |||
+ e.getMessage(), e); | |||
+ e.getMessage(), e); | |||
} | |||
} | |||
@@ -37,111 +37,111 @@ import org.apache.poi.util.NotImplemented; | |||
*/ | |||
public class ZipPackagePart extends PackagePart { | |||
/** | |||
* The zip entry corresponding to this part. | |||
*/ | |||
private ZipArchiveEntry zipEntry; | |||
/** | |||
* Constructor. | |||
* | |||
* @param container | |||
* The container package. | |||
* @param zipEntry | |||
* The zip entry corresponding to this part. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* Content type. | |||
* @throws InvalidFormatException | |||
* Throws if the content of this part is invalid. | |||
*/ | |||
public ZipPackagePart(OPCPackage container, ZipArchiveEntry zipEntry, | |||
PackagePartName partName, String contentType) | |||
throws InvalidFormatException { | |||
this(container, zipEntry, partName, contentType, true); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param container | |||
* The container package. | |||
* @param zipEntry | |||
* The zip entry corresponding to this part. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* Content type. | |||
* @throws InvalidFormatException | |||
* Throws if the content of this part is invalid. | |||
*/ | |||
/* package */ ZipPackagePart(OPCPackage container, ZipArchiveEntry zipEntry, | |||
PackagePartName partName, String contentType, boolean loadRelationships) | |||
throws InvalidFormatException { | |||
super(container, partName, new ContentType(contentType), loadRelationships); | |||
this.zipEntry = zipEntry; | |||
} | |||
/** | |||
* Get the zip entry of this part. | |||
* | |||
* @return The zip entry in the zip structure coresponding to this part. | |||
*/ | |||
public ZipArchiveEntry getZipArchive() { | |||
return zipEntry; | |||
} | |||
/** | |||
* Implementation of the getInputStream() which return the inputStream of | |||
* this part zip entry. | |||
* | |||
* @return Input stream of this part zip entry. | |||
*/ | |||
@Override | |||
protected InputStream getInputStreamImpl() throws IOException { | |||
// We use the getInputStream() method from java.util.zip.ZipFile | |||
// class which return an InputStream to this part zip entry. | |||
return ((ZipPackage) _container).getZipArchive() | |||
.getInputStream(zipEntry); | |||
} | |||
/** | |||
* Implementation of the getOutputStream(). Return <b>null</b>. Normally | |||
* will never be called since the MemoryPackage is use instead. | |||
* | |||
* @return <b>null</b> | |||
*/ | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
return null; | |||
} | |||
@Override | |||
public long getSize() { | |||
return zipEntry.getSize(); | |||
} | |||
@Override | |||
public boolean save(OutputStream os) throws OpenXML4JException { | |||
return new ZipPartMarshaller().marshall(this, os); | |||
} | |||
@Override | |||
@NotImplemented | |||
public boolean load(InputStream ios) { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
@Override | |||
@NotImplemented | |||
public void close() { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
@Override | |||
@NotImplemented | |||
public void flush() { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
/** | |||
* The zip entry corresponding to this part. | |||
*/ | |||
private ZipArchiveEntry zipEntry; | |||
/** | |||
* Constructor. | |||
* | |||
* @param container | |||
* The container package. | |||
* @param zipEntry | |||
* The zip entry corresponding to this part. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* Content type. | |||
* @throws InvalidFormatException | |||
* Throws if the content of this part is invalid. | |||
*/ | |||
public ZipPackagePart(OPCPackage container, ZipArchiveEntry zipEntry, | |||
PackagePartName partName, String contentType) | |||
throws InvalidFormatException { | |||
this(container, zipEntry, partName, contentType, true); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param container | |||
* The container package. | |||
* @param zipEntry | |||
* The zip entry corresponding to this part. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* Content type. | |||
* @throws InvalidFormatException | |||
* Throws if the content of this part is invalid. | |||
*/ | |||
/* package */ ZipPackagePart(OPCPackage container, ZipArchiveEntry zipEntry, | |||
PackagePartName partName, String contentType, boolean loadRelationships) | |||
throws InvalidFormatException { | |||
super(container, partName, new ContentType(contentType), loadRelationships); | |||
this.zipEntry = zipEntry; | |||
} | |||
/** | |||
* Get the zip entry of this part. | |||
* | |||
* @return The zip entry in the zip structure coresponding to this part. | |||
*/ | |||
public ZipArchiveEntry getZipArchive() { | |||
return zipEntry; | |||
} | |||
/** | |||
* Implementation of the getInputStream() which return the inputStream of | |||
* this part zip entry. | |||
* | |||
* @return Input stream of this part zip entry. | |||
*/ | |||
@Override | |||
protected InputStream getInputStreamImpl() throws IOException { | |||
// We use the getInputStream() method from java.util.zip.ZipFile | |||
// class which return an InputStream to this part zip entry. | |||
return ((ZipPackage) _container).getZipArchive() | |||
.getInputStream(zipEntry); | |||
} | |||
/** | |||
* Implementation of the getOutputStream(). Return <b>null</b>. Normally | |||
* will never be called since the MemoryPackage is use instead. | |||
* | |||
* @return <b>null</b> | |||
*/ | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
return null; | |||
} | |||
@Override | |||
public long getSize() { | |||
return zipEntry.getSize(); | |||
} | |||
@Override | |||
public boolean save(OutputStream os) throws OpenXML4JException { | |||
return new ZipPartMarshaller().marshall(this, os); | |||
} | |||
@Override | |||
@NotImplemented | |||
public boolean load(InputStream ios) { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
@Override | |||
@NotImplemented | |||
public void close() { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
@Override | |||
@NotImplemented | |||
public void flush() { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
} |
@@ -51,25 +51,25 @@ import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
*/ | |||
public final class ContentType { | |||
/** | |||
* Type in Type/Subtype. | |||
*/ | |||
private final String type; | |||
/** | |||
* Type in Type/Subtype. | |||
*/ | |||
private final String type; | |||
/** | |||
* Subtype | |||
*/ | |||
private final String subType; | |||
/** | |||
* Subtype | |||
*/ | |||
private final String subType; | |||
/** | |||
* Parameters | |||
*/ | |||
private final Map<String, String> parameters; | |||
/** | |||
* Parameters | |||
*/ | |||
private final Map<String, String> parameters; | |||
/** | |||
* Media type compiled pattern, without parameters | |||
*/ | |||
private static final Pattern patternTypeSubType; | |||
/** | |||
* Media type compiled pattern, without parameters | |||
*/ | |||
private static final Pattern patternTypeSubType; | |||
/** | |||
* Media type compiled pattern, with parameters. | |||
*/ | |||
@@ -80,184 +80,184 @@ public final class ContentType { | |||
*/ | |||
private static final Pattern patternParams; | |||
static { | |||
/* | |||
* token = 1*<any CHAR except CTLs or separators> | |||
* | |||
* separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | | |||
* <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT | |||
* | |||
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)> | |||
* | |||
* CHAR = <any US-ASCII character (octets 0 - 127)> | |||
*/ | |||
String token = "[\\x21-\\x7E&&[^()<>@,;:\\\\/\"\\[\\]?={}\\x20\\x09]]"; | |||
static { | |||
/* | |||
* token = 1*<any CHAR except CTLs or separators> | |||
* | |||
* separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | | |||
* <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT | |||
* | |||
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)> | |||
* | |||
* CHAR = <any US-ASCII character (octets 0 - 127)> | |||
*/ | |||
String token = "[\\x21-\\x7E&&[^()<>@,;:\\\\/\"\\[\\]?={}\\x20\\x09]]"; | |||
/* | |||
* parameter = attribute "=" value | |||
* | |||
* attribute = token | |||
* | |||
* value = token | quoted-string | |||
*/ | |||
String parameter = "(" + token + "+)=(\"?" + token + "+\"?)"; | |||
/* | |||
* Pattern for media type. | |||
* | |||
* Don't allow comment, rule M1.15: The package implementer shall | |||
* require a content type that does not include comments and the format | |||
* designer shall specify such a content type. | |||
* | |||
* comment = "(" *( ctext | quoted-pair | comment ) ")" | |||
* | |||
* ctext = <any TEXT excluding "(" and ")"> | |||
* | |||
* TEXT = <any OCTET except CTLs, but including LWS> | |||
* | |||
* LWS = [CRLF] 1*( SP | HT ) | |||
* | |||
* CR = <US-ASCII CR, carriage return (13)> | |||
* | |||
* LF = <US-ASCII LF, linefeed (10)> | |||
* | |||
* SP = <US-ASCII SP, space (32)> | |||
* | |||
* HT = <US-ASCII HT, horizontal-tab (9)> | |||
* | |||
* quoted-pair = "\" CHAR | |||
*/ | |||
/* | |||
* parameter = attribute "=" value | |||
* | |||
* attribute = token | |||
* | |||
* value = token | quoted-string | |||
*/ | |||
String parameter = "(" + token + "+)=(\"?" + token + "+\"?)"; | |||
/* | |||
* Pattern for media type. | |||
* | |||
* Don't allow comment, rule M1.15: The package implementer shall | |||
* require a content type that does not include comments and the format | |||
* designer shall specify such a content type. | |||
* | |||
* comment = "(" *( ctext | quoted-pair | comment ) ")" | |||
* | |||
* ctext = <any TEXT excluding "(" and ")"> | |||
* | |||
* TEXT = <any OCTET except CTLs, but including LWS> | |||
* | |||
* LWS = [CRLF] 1*( SP | HT ) | |||
* | |||
* CR = <US-ASCII CR, carriage return (13)> | |||
* | |||
* LF = <US-ASCII LF, linefeed (10)> | |||
* | |||
* SP = <US-ASCII SP, space (32)> | |||
* | |||
* HT = <US-ASCII HT, horizontal-tab (9)> | |||
* | |||
* quoted-pair = "\" CHAR | |||
*/ | |||
patternTypeSubType = Pattern.compile("^(" + token + "+)/(" + | |||
token + "+)$"); | |||
patternTypeSubTypeParams = Pattern.compile("^(" + token + "+)/(" + | |||
token + "+)(;" + parameter + ")*$"); | |||
patternParams = Pattern.compile(";" + parameter); | |||
} | |||
patternTypeSubType = Pattern.compile("^(" + token + "+)/(" + | |||
token + "+)$"); | |||
patternTypeSubTypeParams = Pattern.compile("^(" + token + "+)/(" + | |||
token + "+)(;" + parameter + ")*$"); | |||
patternParams = Pattern.compile(";" + parameter); | |||
} | |||
/** | |||
* Constructor. Check the input with the RFC 2616 grammar. | |||
* | |||
* @param contentType | |||
* The content type to store. | |||
* @throws InvalidFormatException | |||
* If the specified content type is not valid with RFC 2616. | |||
*/ | |||
public ContentType(String contentType) throws InvalidFormatException { | |||
Matcher mMediaType = patternTypeSubType.matcher(contentType); | |||
if (!mMediaType.matches()) { | |||
// How about with parameters? | |||
mMediaType = patternTypeSubTypeParams.matcher(contentType); | |||
} | |||
if (!mMediaType.matches()) { | |||
throw new InvalidFormatException( | |||
"The specified content type '" | |||
+ contentType | |||
+ "' is not compliant with RFC 2616: malformed content type."); | |||
} | |||
/** | |||
* Constructor. Check the input with the RFC 2616 grammar. | |||
* | |||
* @param contentType | |||
* The content type to store. | |||
* @throws InvalidFormatException | |||
* If the specified content type is not valid with RFC 2616. | |||
*/ | |||
public ContentType(String contentType) throws InvalidFormatException { | |||
Matcher mMediaType = patternTypeSubType.matcher(contentType); | |||
if (!mMediaType.matches()) { | |||
// How about with parameters? | |||
mMediaType = patternTypeSubTypeParams.matcher(contentType); | |||
} | |||
if (!mMediaType.matches()) { | |||
throw new InvalidFormatException( | |||
"The specified content type '" | |||
+ contentType | |||
+ "' is not compliant with RFC 2616: malformed content type."); | |||
} | |||
// Type/subtype | |||
if (mMediaType.groupCount() >= 2) { | |||
this.type = mMediaType.group(1); | |||
this.subType = mMediaType.group(2); | |||
// Type/subtype | |||
if (mMediaType.groupCount() >= 2) { | |||
this.type = mMediaType.group(1); | |||
this.subType = mMediaType.group(2); | |||
// Parameters | |||
this.parameters = new HashMap<>(); | |||
// Java RegExps are unhelpful, and won't do multiple group captures | |||
// See http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#cg | |||
if (mMediaType.groupCount() >= 5) { | |||
Matcher mParams = patternParams.matcher(contentType.substring(mMediaType.end(2))); | |||
while (mParams.find()) { | |||
this.parameters.put(mParams.group(1), mParams.group(2)); | |||
} | |||
} | |||
} else { | |||
// missing media type and subtype | |||
this.type = ""; | |||
this.subType = ""; | |||
this.parameters = Collections.emptyMap(); | |||
} | |||
} | |||
// Parameters | |||
this.parameters = new HashMap<>(); | |||
// Java RegExps are unhelpful, and won't do multiple group captures | |||
// See http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#cg | |||
if (mMediaType.groupCount() >= 5) { | |||
Matcher mParams = patternParams.matcher(contentType.substring(mMediaType.end(2))); | |||
while (mParams.find()) { | |||
this.parameters.put(mParams.group(1), mParams.group(2)); | |||
} | |||
} | |||
} else { | |||
// missing media type and subtype | |||
this.type = ""; | |||
this.subType = ""; | |||
this.parameters = Collections.emptyMap(); | |||
} | |||
} | |||
/** | |||
* Returns the content type as a string, including parameters | |||
*/ | |||
@Override | |||
public final String toString() { | |||
return toString(true); | |||
} | |||
@Override | |||
public final String toString() { | |||
return toString(true); | |||
} | |||
public final String toString(boolean withParameters) { | |||
StringBuilder retVal = new StringBuilder(64); | |||
retVal.append(this.getType()); | |||
retVal.append('/'); | |||
retVal.append(this.getSubType()); | |||
public final String toString(boolean withParameters) { | |||
StringBuilder retVal = new StringBuilder(64); | |||
retVal.append(this.getType()); | |||
retVal.append('/'); | |||
retVal.append(this.getSubType()); | |||
if (withParameters) { | |||
for (Entry<String, String> me : parameters.entrySet()) { | |||
retVal.append(';'); | |||
retVal.append(me.getKey()); | |||
retVal.append('='); | |||
retVal.append(me.getValue()); | |||
} | |||
} | |||
return retVal.toString(); | |||
} | |||
if (withParameters) { | |||
for (Entry<String, String> me : parameters.entrySet()) { | |||
retVal.append(';'); | |||
retVal.append(me.getKey()); | |||
retVal.append('='); | |||
retVal.append(me.getValue()); | |||
} | |||
} | |||
return retVal.toString(); | |||
} | |||
@Override | |||
public boolean equals(Object obj) { | |||
return (!(obj instanceof ContentType)) | |||
|| (this.toString().equalsIgnoreCase(obj.toString())); | |||
} | |||
@Override | |||
public boolean equals(Object obj) { | |||
return (!(obj instanceof ContentType)) | |||
|| (this.toString().equalsIgnoreCase(obj.toString())); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(type,subType,parameters); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(type,subType,parameters); | |||
} | |||
/* Getters */ | |||
/* Getters */ | |||
/** | |||
* Get the subtype. | |||
* | |||
* @return The subtype of this content type. | |||
*/ | |||
public String getSubType() { | |||
return this.subType; | |||
} | |||
/** | |||
* Get the subtype. | |||
* | |||
* @return The subtype of this content type. | |||
*/ | |||
public String getSubType() { | |||
return this.subType; | |||
} | |||
/** | |||
* Get the type. | |||
* | |||
* @return The type of this content type. | |||
*/ | |||
public String getType() { | |||
return this.type; | |||
} | |||
/** | |||
* Get the type. | |||
* | |||
* @return The type of this content type. | |||
*/ | |||
public String getType() { | |||
return this.type; | |||
} | |||
/** | |||
* Does this content type have any parameters associated with it? | |||
*/ | |||
public boolean hasParameters() { | |||
return (parameters != null) && !parameters.isEmpty(); | |||
} | |||
/** | |||
* Does this content type have any parameters associated with it? | |||
*/ | |||
public boolean hasParameters() { | |||
return (parameters != null) && !parameters.isEmpty(); | |||
} | |||
/** | |||
* Return the parameter keys | |||
*/ | |||
public String[] getParameterKeys() { | |||
if (parameters == null) | |||
return new String[0]; | |||
return parameters.keySet().toArray(new String[0]); | |||
} | |||
/** | |||
* Return the parameter keys | |||
*/ | |||
public String[] getParameterKeys() { | |||
if (parameters == null) | |||
return new String[0]; | |||
return parameters.keySet().toArray(new String[0]); | |||
} | |||
/** | |||
* Gets the value associated to the specified key. | |||
* | |||
* @param key | |||
* The key of the key/value pair. | |||
* @return The value associated to the specified key. | |||
*/ | |||
public String getParameter(String key) { | |||
return parameters.get(key); | |||
} | |||
/** | |||
* Gets the value associated to the specified key. | |||
* | |||
* @param key | |||
* The key of the key/value pair. | |||
* @return The value associated to the specified key. | |||
*/ | |||
public String getParameter(String key) { | |||
return parameters.get(key); | |||
} | |||
} |
@@ -38,101 +38,101 @@ import org.apache.poi.util.IOUtils; | |||
*/ | |||
public final class MemoryPackagePart extends PackagePart { | |||
/** | |||
* Storage for the part data. | |||
*/ | |||
protected byte[] data; | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* The owner package. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* The content type. | |||
* @throws InvalidFormatException | |||
* If the specified URI is not OPC compliant. | |||
*/ | |||
public MemoryPackagePart(OPCPackage pack, PackagePartName partName, | |||
String contentType) throws InvalidFormatException { | |||
super(pack, partName, contentType); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* The owner package. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* The content type. | |||
* @param loadRelationships | |||
* Specify if the relationships will be loaded. | |||
* @throws InvalidFormatException | |||
* If the specified URI is not OPC compliant. | |||
*/ | |||
public MemoryPackagePart(OPCPackage pack, PackagePartName partName, | |||
String contentType, boolean loadRelationships) | |||
throws InvalidFormatException { | |||
super(pack, partName, new ContentType(contentType), loadRelationships); | |||
} | |||
@Override | |||
protected InputStream getInputStreamImpl() { | |||
// If this part has been created from scratch and/or the data buffer is | |||
// not | |||
// initialize, so we do it now. | |||
if (data == null) { | |||
data = new byte[0]; | |||
} | |||
return new ByteArrayInputStream(data); | |||
} | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
return new MemoryPackagePartOutputStream(this); | |||
} | |||
@Override | |||
public long getSize() { | |||
return data == null ? 0 : data.length; | |||
} | |||
/** | |||
* Storage for the part data. | |||
*/ | |||
protected byte[] data; | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* The owner package. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* The content type. | |||
* @throws InvalidFormatException | |||
* If the specified URI is not OPC compliant. | |||
*/ | |||
public MemoryPackagePart(OPCPackage pack, PackagePartName partName, | |||
String contentType) throws InvalidFormatException { | |||
super(pack, partName, contentType); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* The owner package. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* The content type. | |||
* @param loadRelationships | |||
* Specify if the relationships will be loaded. | |||
* @throws InvalidFormatException | |||
* If the specified URI is not OPC compliant. | |||
*/ | |||
public MemoryPackagePart(OPCPackage pack, PackagePartName partName, | |||
String contentType, boolean loadRelationships) | |||
throws InvalidFormatException { | |||
super(pack, partName, new ContentType(contentType), loadRelationships); | |||
} | |||
@Override | |||
protected InputStream getInputStreamImpl() { | |||
// If this part has been created from scratch and/or the data buffer is | |||
// not | |||
// initialize, so we do it now. | |||
if (data == null) { | |||
data = new byte[0]; | |||
} | |||
return new ByteArrayInputStream(data); | |||
} | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
return new MemoryPackagePartOutputStream(this); | |||
} | |||
@Override | |||
public long getSize() { | |||
return data == null ? 0 : data.length; | |||
} | |||
@Override | |||
public void clear() { | |||
data = null; | |||
} | |||
@Override | |||
public boolean save(OutputStream os) throws OpenXML4JException { | |||
return new ZipPartMarshaller().marshall(this, os); | |||
} | |||
@Override | |||
public boolean load(InputStream ios) throws InvalidFormatException { | |||
try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) { | |||
// Grab the data | |||
IOUtils.copy(ios, baos); | |||
// Save it | |||
data = baos.toByteArray(); | |||
} catch(IOException e) { | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
// All done | |||
return true; | |||
} | |||
@Override | |||
public void close() { | |||
// Do nothing | |||
} | |||
@Override | |||
public void flush() { | |||
// Do nothing | |||
} | |||
data = null; | |||
} | |||
@Override | |||
public boolean save(OutputStream os) throws OpenXML4JException { | |||
return new ZipPartMarshaller().marshall(this, os); | |||
} | |||
@Override | |||
public boolean load(InputStream ios) throws InvalidFormatException { | |||
try (UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) { | |||
// Grab the data | |||
IOUtils.copy(ios, baos); | |||
// Save it | |||
data = baos.toByteArray(); | |||
} catch(IOException e) { | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
// All done | |||
return true; | |||
} | |||
@Override | |||
public void close() { | |||
// Do nothing | |||
} | |||
@Override | |||
public void flush() { | |||
// Do nothing | |||
} | |||
} |
@@ -27,68 +27,68 @@ import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; | |||
*/ | |||
public final class MemoryPackagePartOutputStream extends OutputStream { | |||
private final MemoryPackagePart _part; | |||
private final UnsynchronizedByteArrayOutputStream _buff; | |||
public MemoryPackagePartOutputStream(MemoryPackagePart part) { | |||
this._part = part; | |||
_buff = new UnsynchronizedByteArrayOutputStream(); | |||
} | |||
@Override | |||
public void write(int b) { | |||
_buff.write(b); | |||
} | |||
/** | |||
* Close this stream and flush the content. | |||
* @see #flush() | |||
*/ | |||
@Override | |||
public void close() throws IOException { | |||
this.flush(); | |||
} | |||
/** | |||
* Flush this output stream. This method is called by the close() method. | |||
* Warning : don't call this method for output consistency. | |||
* @see #close() | |||
*/ | |||
@Override | |||
public void flush() throws IOException { | |||
_buff.flush(); | |||
if (_part.data != null) { | |||
byte[] newArray = new byte[_part.data.length + _buff.size()]; | |||
// copy the previous contents of part.data in newArray | |||
System.arraycopy(_part.data, 0, newArray, 0, _part.data.length); | |||
// append the newly added data | |||
byte[] buffArr = _buff.toByteArray(); | |||
System.arraycopy(buffArr, 0, newArray, _part.data.length, | |||
buffArr.length); | |||
// save the result as new data | |||
_part.data = newArray; | |||
} else { | |||
// was empty, just fill it | |||
_part.data = _buff.toByteArray(); | |||
} | |||
/* | |||
* Clear this streams buffer, in case flush() is called a second time | |||
* Fix bug 1921637 - provided by Rainer Schwarze | |||
*/ | |||
_buff.reset(); | |||
} | |||
@Override | |||
public void write(byte[] b, int off, int len) { | |||
_buff.write(b, off, len); | |||
} | |||
@Override | |||
public void write(byte[] b) throws IOException { | |||
_buff.write(b); | |||
} | |||
private final MemoryPackagePart _part; | |||
private final UnsynchronizedByteArrayOutputStream _buff; | |||
public MemoryPackagePartOutputStream(MemoryPackagePart part) { | |||
this._part = part; | |||
_buff = new UnsynchronizedByteArrayOutputStream(); | |||
} | |||
@Override | |||
public void write(int b) { | |||
_buff.write(b); | |||
} | |||
/** | |||
* Close this stream and flush the content. | |||
* @see #flush() | |||
*/ | |||
@Override | |||
public void close() throws IOException { | |||
this.flush(); | |||
} | |||
/** | |||
* Flush this output stream. This method is called by the close() method. | |||
* Warning : don't call this method for output consistency. | |||
* @see #close() | |||
*/ | |||
@Override | |||
public void flush() throws IOException { | |||
_buff.flush(); | |||
if (_part.data != null) { | |||
byte[] newArray = new byte[_part.data.length + _buff.size()]; | |||
// copy the previous contents of part.data in newArray | |||
System.arraycopy(_part.data, 0, newArray, 0, _part.data.length); | |||
// append the newly added data | |||
byte[] buffArr = _buff.toByteArray(); | |||
System.arraycopy(buffArr, 0, newArray, _part.data.length, | |||
buffArr.length); | |||
// save the result as new data | |||
_part.data = newArray; | |||
} else { | |||
// was empty, just fill it | |||
_part.data = _buff.toByteArray(); | |||
} | |||
/* | |||
* Clear this streams buffer, in case flush() is called a second time | |||
* Fix bug 1921637 - provided by Rainer Schwarze | |||
*/ | |||
_buff.reset(); | |||
} | |||
@Override | |||
public void write(byte[] b, int off, int len) { | |||
_buff.write(b, off, len); | |||
} | |||
@Override | |||
public void write(byte[] b) throws IOException { | |||
_buff.write(b); | |||
} | |||
} |
@@ -31,18 +31,18 @@ import org.apache.poi.openxml4j.opc.PackagePart; | |||
*/ | |||
public interface PartMarshaller { | |||
/** | |||
* Save the content of the package in the stream | |||
* | |||
* @param part | |||
* Part to marshall. | |||
* @param out | |||
* The output stream into which the part will be marshall. | |||
* @return <b>false</b> if any marshall error occurs, else <b>true</b> | |||
* @throws OpenXML4JException | |||
* Throws only if any other exceptions are thrown by inner | |||
* methods. | |||
*/ | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException; | |||
/** | |||
* Save the content of the package in the stream | |||
* | |||
* @param part | |||
* Part to marshall. | |||
* @param out | |||
* The output stream into which the part will be marshall. | |||
* @return <b>false</b> if any marshall error occurs, else <b>true</b> | |||
* @throws OpenXML4JException | |||
* Throws only if any other exceptions are thrown by inner | |||
* methods. | |||
*/ | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException; | |||
} |
@@ -32,14 +32,14 @@ import org.apache.poi.openxml4j.opc.internal.unmarshallers.UnmarshallContext; | |||
*/ | |||
public interface PartUnmarshaller { | |||
/** | |||
* Save the content of the package in the stream | |||
* | |||
* @param in The input stream from which the part will be read. | |||
* @return The part freshly read from the input stream. | |||
* @throws InvalidFormatException If the data can not be interpreted correctly | |||
* @throws IOException if reading from the stream fails | |||
*/ | |||
public PackagePart unmarshall(UnmarshallContext context, InputStream in) | |||
throws InvalidFormatException, IOException; | |||
/** | |||
* Save the content of the package in the stream | |||
* | |||
* @param in The input stream from which the part will be read. | |||
* @return The part freshly read from the input stream. | |||
* @throws InvalidFormatException If the data can not be interpreted correctly | |||
* @throws IOException if reading from the stream fails | |||
*/ | |||
public PackagePart unmarshall(UnmarshallContext context, InputStream in) | |||
throws InvalidFormatException, IOException; | |||
} |
@@ -39,39 +39,39 @@ import org.w3c.dom.Document; | |||
public class ZipContentTypeManager extends ContentTypeManager { | |||
private static final Logger LOG = LogManager.getLogger(ZipContentTypeManager.class); | |||
/** | |||
* Delegate constructor to the super constructor. | |||
* | |||
* @param in | |||
* The input stream to parse to fill internal content type | |||
* collections. | |||
* @throws InvalidFormatException | |||
* If the content types part content is not valid. | |||
*/ | |||
public ZipContentTypeManager(InputStream in, OPCPackage pkg) | |||
throws InvalidFormatException { | |||
super(in, pkg); | |||
} | |||
/** | |||
* Delegate constructor to the super constructor. | |||
* | |||
* @param in | |||
* The input stream to parse to fill internal content type | |||
* collections. | |||
* @throws InvalidFormatException | |||
* If the content types part content is not valid. | |||
*/ | |||
public ZipContentTypeManager(InputStream in, OPCPackage pkg) | |||
throws InvalidFormatException { | |||
super(in, pkg); | |||
} | |||
@SuppressWarnings("resource") | |||
@SuppressWarnings("resource") | |||
@Override | |||
public boolean saveImpl(Document content, OutputStream out) { | |||
final ZipArchiveOutputStream zos = (out instanceof ZipArchiveOutputStream) | |||
? (ZipArchiveOutputStream) out : new ZipArchiveOutputStream(out); | |||
public boolean saveImpl(Document content, OutputStream out) { | |||
final ZipArchiveOutputStream zos = (out instanceof ZipArchiveOutputStream) | |||
? (ZipArchiveOutputStream) out : new ZipArchiveOutputStream(out); | |||
ZipArchiveEntry partEntry = new ZipArchiveEntry(CONTENT_TYPES_PART_NAME); | |||
try { | |||
// Referenced in ZIP | |||
zos.putArchiveEntry(partEntry); | |||
try { | |||
// Saving data in the ZIP file | |||
return StreamHelper.saveXmlInStream(content, zos); | |||
} finally { | |||
zos.closeArchiveEntry(); | |||
} | |||
} catch (IOException ioe) { | |||
LOG.atError().withThrowable(ioe).log("Cannot write: " + CONTENT_TYPES_PART_NAME + " in Zip !"); | |||
return false; | |||
} | |||
} | |||
ZipArchiveEntry partEntry = new ZipArchiveEntry(CONTENT_TYPES_PART_NAME); | |||
try { | |||
// Referenced in ZIP | |||
zos.putArchiveEntry(partEntry); | |||
try { | |||
// Saving data in the ZIP file | |||
return StreamHelper.saveXmlInStream(content, zos); | |||
} finally { | |||
zos.closeArchiveEntry(); | |||
} | |||
} catch (IOException ioe) { | |||
LOG.atError().withThrowable(ioe).log("Cannot write: " + CONTENT_TYPES_PART_NAME + " in Zip !"); | |||
return false; | |||
} | |||
} | |||
} |
@@ -31,18 +31,18 @@ import org.apache.poi.openxml4j.opc.internal.PartMarshaller; | |||
*/ | |||
public final class DefaultMarshaller implements PartMarshaller { | |||
/** | |||
* Save the given part in the output stream by using the save() method of the part. | |||
* | |||
* @param part The {@link PackagePart} to store. | |||
* @param out Output stream to save this part. | |||
* @return true if the content has been successfully stored, false otherwise. | |||
* More information about errors may be logged via Log4j 2. | |||
* @throws OpenXML4JException | |||
* If any error occur. | |||
*/ | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException { | |||
return part.save(out); | |||
} | |||
/** | |||
* Save the given part in the output stream by using the save() method of the part. | |||
* | |||
* @param part The {@link PackagePart} to store. | |||
* @param out Output stream to save this part. | |||
* @return true if the content has been successfully stored, false otherwise. | |||
* More information about errors may be logged via Log4j 2. | |||
* @throws OpenXML4JException | |||
* If any error occur. | |||
*/ | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException { | |||
return part.save(out); | |||
} | |||
} |
@@ -32,30 +32,30 @@ import org.apache.poi.openxml4j.opc.internal.ZipHelper; | |||
*/ | |||
public final class ZipPackagePropertiesMarshaller extends PackagePropertiesMarshaller { | |||
@Override | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException { | |||
if (!(out instanceof ZipArchiveOutputStream)) { | |||
throw new IllegalArgumentException("ZipOutputStream expected!"); | |||
} | |||
ZipArchiveOutputStream zos = (ZipArchiveOutputStream) out; | |||
// Saving the part in the zip file | |||
ZipArchiveEntry ctEntry = new ZipArchiveEntry(ZipHelper | |||
.getZipItemNameFromOPCName(part.getPartName().getURI() | |||
.toString())); | |||
try { | |||
// Save in ZIP | |||
zos.putArchiveEntry(ctEntry); // Add entry in ZIP | |||
try { | |||
super.marshall(part, out); // Marshall the properties inside a XML | |||
// Document | |||
return StreamHelper.saveXmlInStream(xmlDoc, out); | |||
} finally { | |||
zos.closeArchiveEntry(); | |||
} | |||
} catch (IOException e) { | |||
throw new OpenXML4JException(e.getLocalizedMessage(), e); | |||
} | |||
} | |||
@Override | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException { | |||
if (!(out instanceof ZipArchiveOutputStream)) { | |||
throw new IllegalArgumentException("ZipOutputStream expected!"); | |||
} | |||
ZipArchiveOutputStream zos = (ZipArchiveOutputStream) out; | |||
// Saving the part in the zip file | |||
ZipArchiveEntry ctEntry = new ZipArchiveEntry(ZipHelper | |||
.getZipItemNameFromOPCName(part.getPartName().getURI() | |||
.toString())); | |||
try { | |||
// Save in ZIP | |||
zos.putArchiveEntry(ctEntry); // Add entry in ZIP | |||
try { | |||
super.marshall(part, out); // Marshall the properties inside a XML | |||
// Document | |||
return StreamHelper.saveXmlInStream(xmlDoc, out); | |||
} finally { | |||
zos.closeArchiveEntry(); | |||
} | |||
} catch (IOException e) { | |||
throw new OpenXML4JException(e.getLocalizedMessage(), e); | |||
} | |||
} | |||
} |
@@ -47,146 +47,146 @@ import org.w3c.dom.Element; | |||
* Zip part marshaller. This marshaller is use to save any part in a zip stream. | |||
*/ | |||
public final class ZipPartMarshaller implements PartMarshaller { | |||
private static final Logger LOG = LogManager.getLogger(ZipPartMarshaller.class); | |||
/** | |||
* Save the specified part to the given stream. | |||
* | |||
* @param part The {@link PackagePart} to save | |||
* @param os The stream to write the data to | |||
* @return true if saving was successful or there was nothing to save, | |||
* false if an error occurred. | |||
* In case of errors, logging via Log4j 2 is used to provide more information. | |||
* @throws OpenXML4JException | |||
* Throws if the stream cannot be written to or an internal exception is thrown. | |||
*/ | |||
@Override | |||
public boolean marshall(PackagePart part, OutputStream os) | |||
throws OpenXML4JException { | |||
if (!(os instanceof ZipArchiveOutputStream)) { | |||
LOG.atError().log("Unexpected class {}", os.getClass().getName()); | |||
throw new OpenXML4JException("ZipOutputStream expected !"); | |||
// Normally should happen only in development phase, so just throw | |||
// exception | |||
} | |||
// check if there is anything to save for some parts. We don't do this for all parts as some code | |||
// might depend on empty parts being saved, e.g. some unit tests verify this currently. | |||
if(part.getSize() == 0 && part.getPartName().getName().equals(XSSFRelation.SHARED_STRINGS.getDefaultFileName())) { | |||
return true; | |||
} | |||
ZipArchiveOutputStream zos = (ZipArchiveOutputStream) os; | |||
ZipArchiveEntry partEntry = new ZipArchiveEntry(ZipHelper | |||
.getZipItemNameFromOPCName(part.getPartName().getURI() | |||
.getPath())); | |||
try { | |||
// Create next zip entry | |||
zos.putArchiveEntry(partEntry); | |||
// Saving data in the ZIP file | |||
try (final InputStream ins = part.getInputStream()) { | |||
IOUtils.copy(ins, zos); | |||
} finally { | |||
zos.closeArchiveEntry(); | |||
} | |||
} catch (IOException ioe) { | |||
LOG.atError().withThrowable(ioe).log("Cannot write: {}: in ZIP", part.getPartName()); | |||
return false; | |||
} | |||
// Saving relationship part | |||
if (part.hasRelationships()) { | |||
PackagePartName relationshipPartName = PackagingURIHelper | |||
.getRelationshipPartName(part.getPartName()); | |||
marshallRelationshipPart(part.getRelationships(), | |||
relationshipPartName, zos); | |||
} | |||
return true; | |||
} | |||
/** | |||
* Save relationships into the part. | |||
* | |||
* @param rels | |||
* The relationships collection to marshall. | |||
* @param relPartName | |||
* Part name of the relationship part to marshall. | |||
* @param zos | |||
* Zip output stream in which to save the XML content of the | |||
* relationships serialization. | |||
* @return true if saving was successful, | |||
* false if an error occurred. | |||
* In case of errors, logging via Log4j 2 is used to provide more information. | |||
*/ | |||
public static boolean marshallRelationshipPart( | |||
PackageRelationshipCollection rels, PackagePartName relPartName, | |||
ZipArchiveOutputStream zos) { | |||
// Building xml | |||
Document xmlOutDoc = DocumentHelper.createDocument(); | |||
// make something like <Relationships | |||
// xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> | |||
Element root = xmlOutDoc.createElementNS(PackageNamespaces.RELATIONSHIPS, PackageRelationship.RELATIONSHIPS_TAG_NAME); | |||
private static final Logger LOG = LogManager.getLogger(ZipPartMarshaller.class); | |||
/** | |||
* Save the specified part to the given stream. | |||
* | |||
* @param part The {@link PackagePart} to save | |||
* @param os The stream to write the data to | |||
* @return true if saving was successful or there was nothing to save, | |||
* false if an error occurred. | |||
* In case of errors, logging via Log4j 2 is used to provide more information. | |||
* @throws OpenXML4JException | |||
* Throws if the stream cannot be written to or an internal exception is thrown. | |||
*/ | |||
@Override | |||
public boolean marshall(PackagePart part, OutputStream os) | |||
throws OpenXML4JException { | |||
if (!(os instanceof ZipArchiveOutputStream)) { | |||
LOG.atError().log("Unexpected class {}", os.getClass().getName()); | |||
throw new OpenXML4JException("ZipOutputStream expected !"); | |||
// Normally should happen only in development phase, so just throw | |||
// exception | |||
} | |||
// check if there is anything to save for some parts. We don't do this for all parts as some code | |||
// might depend on empty parts being saved, e.g. some unit tests verify this currently. | |||
if(part.getSize() == 0 && part.getPartName().getName().equals(XSSFRelation.SHARED_STRINGS.getDefaultFileName())) { | |||
return true; | |||
} | |||
ZipArchiveOutputStream zos = (ZipArchiveOutputStream) os; | |||
ZipArchiveEntry partEntry = new ZipArchiveEntry(ZipHelper | |||
.getZipItemNameFromOPCName(part.getPartName().getURI() | |||
.getPath())); | |||
try { | |||
// Create next zip entry | |||
zos.putArchiveEntry(partEntry); | |||
// Saving data in the ZIP file | |||
try (final InputStream ins = part.getInputStream()) { | |||
IOUtils.copy(ins, zos); | |||
} finally { | |||
zos.closeArchiveEntry(); | |||
} | |||
} catch (IOException ioe) { | |||
LOG.atError().withThrowable(ioe).log("Cannot write: {}: in ZIP", part.getPartName()); | |||
return false; | |||
} | |||
// Saving relationship part | |||
if (part.hasRelationships()) { | |||
PackagePartName relationshipPartName = PackagingURIHelper | |||
.getRelationshipPartName(part.getPartName()); | |||
marshallRelationshipPart(part.getRelationships(), | |||
relationshipPartName, zos); | |||
} | |||
return true; | |||
} | |||
/** | |||
* Save relationships into the part. | |||
* | |||
* @param rels | |||
* The relationships collection to marshall. | |||
* @param relPartName | |||
* Part name of the relationship part to marshall. | |||
* @param zos | |||
* Zip output stream in which to save the XML content of the | |||
* relationships serialization. | |||
* @return true if saving was successful, | |||
* false if an error occurred. | |||
* In case of errors, logging via Log4j 2 is used to provide more information. | |||
*/ | |||
public static boolean marshallRelationshipPart( | |||
PackageRelationshipCollection rels, PackagePartName relPartName, | |||
ZipArchiveOutputStream zos) { | |||
// Building xml | |||
Document xmlOutDoc = DocumentHelper.createDocument(); | |||
// make something like <Relationships | |||
// xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> | |||
Element root = xmlOutDoc.createElementNS(PackageNamespaces.RELATIONSHIPS, PackageRelationship.RELATIONSHIPS_TAG_NAME); | |||
xmlOutDoc.appendChild(root); | |||
// <Relationship | |||
// TargetMode="External" | |||
// Id="rIdx" | |||
// Target="http://www.custom.com/images/pic1.jpg" | |||
// Type="http://www.custom.com/external-resource"/> | |||
// <Relationship | |||
// TargetMode="External" | |||
// Id="rIdx" | |||
// Target="http://www.custom.com/images/pic1.jpg" | |||
// Type="http://www.custom.com/external-resource"/> | |||
URI sourcePartURI = PackagingURIHelper | |||
.getSourcePartUriFromRelationshipPartUri(relPartName.getURI()); | |||
URI sourcePartURI = PackagingURIHelper | |||
.getSourcePartUriFromRelationshipPartUri(relPartName.getURI()); | |||
for (PackageRelationship rel : rels) { | |||
// the relationship element | |||
for (PackageRelationship rel : rels) { | |||
// the relationship element | |||
Element relElem = xmlOutDoc.createElementNS(PackageNamespaces.RELATIONSHIPS, PackageRelationship.RELATIONSHIP_TAG_NAME); | |||
root.appendChild(relElem); | |||
// the relationship ID | |||
relElem.setAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel.getId()); | |||
// the relationship ID | |||
relElem.setAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel.getId()); | |||
// the relationship Type | |||
relElem.setAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel.getRelationshipType()); | |||
// the relationship Type | |||
relElem.setAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel.getRelationshipType()); | |||
// the relationship Target | |||
String targetValue; | |||
URI uri = rel.getTargetURI(); | |||
if (rel.getTargetMode() == TargetMode.EXTERNAL) { | |||
// Save the target as-is - we don't need to validate it, | |||
// alter it etc | |||
targetValue = uri.toString(); | |||
// the relationship Target | |||
String targetValue; | |||
URI uri = rel.getTargetURI(); | |||
if (rel.getTargetMode() == TargetMode.EXTERNAL) { | |||
// Save the target as-is - we don't need to validate it, | |||
// alter it etc | |||
targetValue = uri.toString(); | |||
// add TargetMode attribute (as it is external link external) | |||
relElem.setAttribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, "External"); | |||
} else { | |||
// add TargetMode attribute (as it is external link external) | |||
relElem.setAttribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, "External"); | |||
} else { | |||
URI targetURI = rel.getTargetURI(); | |||
targetValue = PackagingURIHelper.relativizeURI( | |||
sourcePartURI, targetURI, true).toString(); | |||
} | |||
relElem.setAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, targetValue); | |||
} | |||
xmlOutDoc.normalize(); | |||
// String schemaFilename = Configuration.getPathForXmlSchema()+ | |||
// File.separator + "opc-relationships.xsd"; | |||
// Save part in zip | |||
ZipArchiveEntry ctEntry = new ZipArchiveEntry(ZipHelper.getZipURIFromOPCName( | |||
relPartName.getURI().toASCIIString()).getPath()); | |||
try { | |||
zos.putArchiveEntry(ctEntry); | |||
try { | |||
return StreamHelper.saveXmlInStream(xmlOutDoc, zos); | |||
} finally { | |||
zos.closeArchiveEntry(); | |||
} | |||
} catch (IOException e) { | |||
LOG.atError().withThrowable(e).log("Cannot create zip entry {}", relPartName); | |||
return false; | |||
} | |||
} | |||
sourcePartURI, targetURI, true).toString(); | |||
} | |||
relElem.setAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, targetValue); | |||
} | |||
xmlOutDoc.normalize(); | |||
// String schemaFilename = Configuration.getPathForXmlSchema()+ | |||
// File.separator + "opc-relationships.xsd"; | |||
// Save part in zip | |||
ZipArchiveEntry ctEntry = new ZipArchiveEntry(ZipHelper.getZipURIFromOPCName( | |||
relPartName.getURI().toASCIIString()).getPath()); | |||
try { | |||
zos.putArchiveEntry(ctEntry); | |||
try { | |||
return StreamHelper.saveXmlInStream(xmlOutDoc, zos); | |||
} finally { | |||
zos.closeArchiveEntry(); | |||
} | |||
} catch (IOException e) { | |||
LOG.atError().withThrowable(e).log("Cannot create zip entry {}", relPartName); | |||
return false; | |||
} | |||
} | |||
} |
@@ -44,97 +44,97 @@ import org.xml.sax.SAXException; | |||
*/ | |||
public final class PackagePropertiesUnmarshaller implements PartUnmarshaller { | |||
protected static final String KEYWORD_CATEGORY = "category"; | |||
protected static final String KEYWORD_CATEGORY = "category"; | |||
protected static final String KEYWORD_CONTENT_STATUS = "contentStatus"; | |||
protected static final String KEYWORD_CONTENT_STATUS = "contentStatus"; | |||
protected static final String KEYWORD_CONTENT_TYPE = "contentType"; | |||
protected static final String KEYWORD_CONTENT_TYPE = "contentType"; | |||
protected static final String KEYWORD_CREATED = "created"; | |||
protected static final String KEYWORD_CREATED = "created"; | |||
protected static final String KEYWORD_CREATOR = "creator"; | |||
protected static final String KEYWORD_CREATOR = "creator"; | |||
protected static final String KEYWORD_DESCRIPTION = "description"; | |||
protected static final String KEYWORD_DESCRIPTION = "description"; | |||
protected static final String KEYWORD_IDENTIFIER = "identifier"; | |||
protected static final String KEYWORD_IDENTIFIER = "identifier"; | |||
protected static final String KEYWORD_KEYWORDS = "keywords"; | |||
protected static final String KEYWORD_KEYWORDS = "keywords"; | |||
protected static final String KEYWORD_LANGUAGE = "language"; | |||
protected static final String KEYWORD_LANGUAGE = "language"; | |||
protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy"; | |||
protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy"; | |||
protected static final String KEYWORD_LAST_PRINTED = "lastPrinted"; | |||
protected static final String KEYWORD_LAST_PRINTED = "lastPrinted"; | |||
protected static final String KEYWORD_MODIFIED = "modified"; | |||
protected static final String KEYWORD_MODIFIED = "modified"; | |||
protected static final String KEYWORD_REVISION = "revision"; | |||
protected static final String KEYWORD_REVISION = "revision"; | |||
protected static final String KEYWORD_SUBJECT = "subject"; | |||
protected static final String KEYWORD_SUBJECT = "subject"; | |||
protected static final String KEYWORD_TITLE = "title"; | |||
protected static final String KEYWORD_TITLE = "title"; | |||
protected static final String KEYWORD_VERSION = "version"; | |||
protected static final String KEYWORD_VERSION = "version"; | |||
// TODO Load element with XMLBeans or dynamic table | |||
// TODO Check every element/namespace for compliance | |||
public PackagePart unmarshall(UnmarshallContext context, InputStream in) | |||
throws InvalidFormatException, IOException { | |||
PackagePropertiesPart coreProps = new PackagePropertiesPart(context | |||
.getPackage(), context.getPartName()); | |||
// TODO Load element with XMLBeans or dynamic table | |||
// TODO Check every element/namespace for compliance | |||
public PackagePart unmarshall(UnmarshallContext context, InputStream in) | |||
throws InvalidFormatException, IOException { | |||
PackagePropertiesPart coreProps = new PackagePropertiesPart(context | |||
.getPackage(), context.getPartName()); | |||
// If the input stream is null then we try to get it from the | |||
// package. | |||
if (in == null) { | |||
if (context.getZipEntry() != null) { | |||
in = ((ZipPackage) context.getPackage()).getZipArchive() | |||
.getInputStream(context.getZipEntry()); | |||
} else if (context.getPackage() != null) { | |||
// Try to retrieve the part inputstream from the URI | |||
ZipArchiveEntry zipEntry = ZipHelper | |||
.getCorePropertiesZipEntry((ZipPackage) context | |||
.getPackage()); | |||
in = ((ZipPackage) context.getPackage()).getZipArchive() | |||
.getInputStream(zipEntry); | |||
} else | |||
throw new IOException( | |||
"Error while trying to get the part input stream."); | |||
} | |||
// If the input stream is null then we try to get it from the | |||
// package. | |||
if (in == null) { | |||
if (context.getZipEntry() != null) { | |||
in = ((ZipPackage) context.getPackage()).getZipArchive() | |||
.getInputStream(context.getZipEntry()); | |||
} else if (context.getPackage() != null) { | |||
// Try to retrieve the part inputstream from the URI | |||
ZipArchiveEntry zipEntry = ZipHelper | |||
.getCorePropertiesZipEntry((ZipPackage) context | |||
.getPackage()); | |||
in = ((ZipPackage) context.getPackage()).getZipArchive() | |||
.getInputStream(zipEntry); | |||
} else | |||
throw new IOException( | |||
"Error while trying to get the part input stream."); | |||
} | |||
Document xmlDoc; | |||
try { | |||
xmlDoc = DocumentHelper.readDocument(in); | |||
Document xmlDoc; | |||
try { | |||
xmlDoc = DocumentHelper.readDocument(in); | |||
/* Check OPC compliance */ | |||
/* Check OPC compliance */ | |||
// Rule M4.2, M4.3, M4.4 and M4.5/ | |||
checkElementForOPCCompliance(xmlDoc.getDocumentElement()); | |||
// Rule M4.2, M4.3, M4.4 and M4.5/ | |||
checkElementForOPCCompliance(xmlDoc.getDocumentElement()); | |||
/* End OPC compliance */ | |||
/* End OPC compliance */ | |||
} catch (SAXException e) { | |||
throw new IOException(e.getMessage()); | |||
} | |||
coreProps.setCategoryProperty(loadCategory(xmlDoc)); | |||
coreProps.setContentStatusProperty(loadContentStatus(xmlDoc)); | |||
coreProps.setContentTypeProperty(loadContentType(xmlDoc)); | |||
coreProps.setCreatedProperty(loadCreated(xmlDoc)); | |||
coreProps.setCreatorProperty(loadCreator(xmlDoc)); | |||
coreProps.setDescriptionProperty(loadDescription(xmlDoc)); | |||
coreProps.setIdentifierProperty(loadIdentifier(xmlDoc)); | |||
coreProps.setKeywordsProperty(loadKeywords(xmlDoc)); | |||
coreProps.setLanguageProperty(loadLanguage(xmlDoc)); | |||
coreProps.setLastModifiedByProperty(loadLastModifiedBy(xmlDoc)); | |||
coreProps.setLastPrintedProperty(loadLastPrinted(xmlDoc)); | |||
coreProps.setModifiedProperty(loadModified(xmlDoc)); | |||
coreProps.setRevisionProperty(loadRevision(xmlDoc)); | |||
coreProps.setSubjectProperty(loadSubject(xmlDoc)); | |||
coreProps.setTitleProperty(loadTitle(xmlDoc)); | |||
coreProps.setVersionProperty(loadVersion(xmlDoc)); | |||
return coreProps; | |||
} | |||
coreProps.setContentStatusProperty(loadContentStatus(xmlDoc)); | |||
coreProps.setContentTypeProperty(loadContentType(xmlDoc)); | |||
coreProps.setCreatedProperty(loadCreated(xmlDoc)); | |||
coreProps.setCreatorProperty(loadCreator(xmlDoc)); | |||
coreProps.setDescriptionProperty(loadDescription(xmlDoc)); | |||
coreProps.setIdentifierProperty(loadIdentifier(xmlDoc)); | |||
coreProps.setKeywordsProperty(loadKeywords(xmlDoc)); | |||
coreProps.setLanguageProperty(loadLanguage(xmlDoc)); | |||
coreProps.setLastModifiedByProperty(loadLastModifiedBy(xmlDoc)); | |||
coreProps.setLastPrintedProperty(loadLastPrinted(xmlDoc)); | |||
coreProps.setModifiedProperty(loadModified(xmlDoc)); | |||
coreProps.setRevisionProperty(loadRevision(xmlDoc)); | |||
coreProps.setSubjectProperty(loadSubject(xmlDoc)); | |||
coreProps.setTitleProperty(loadTitle(xmlDoc)); | |||
coreProps.setVersionProperty(loadVersion(xmlDoc)); | |||
return coreProps; | |||
} | |||
private String readElement(Document xmlDoc, String localName, String namespaceURI) { | |||
Element el = (Element)xmlDoc.getDocumentElement().getElementsByTagNameNS(namespaceURI, localName).item(0); | |||
@@ -144,97 +144,97 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller { | |||
return el.getTextContent(); | |||
} | |||
private String loadCategory(Document xmlDoc) { | |||
private String loadCategory(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_CATEGORY, PackageNamespaces.CORE_PROPERTIES); | |||
} | |||
} | |||
private String loadContentStatus(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_CONTENT_STATUS, PackageNamespaces.CORE_PROPERTIES); | |||
} | |||
} | |||
private String loadContentType(Document xmlDoc) { | |||
private String loadContentType(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_CONTENT_TYPE, PackageNamespaces.CORE_PROPERTIES); | |||
} | |||
} | |||
private String loadCreated(Document xmlDoc) { | |||
private String loadCreated(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_CREATED, PackageProperties.NAMESPACE_DCTERMS); | |||
} | |||
} | |||
private String loadCreator(Document xmlDoc) { | |||
private String loadCreator(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_CREATOR, PackageProperties.NAMESPACE_DC); | |||
} | |||
} | |||
private String loadDescription(Document xmlDoc) { | |||
private String loadDescription(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_DESCRIPTION, PackageProperties.NAMESPACE_DC); | |||
} | |||
} | |||
private String loadIdentifier(Document xmlDoc) { | |||
private String loadIdentifier(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_IDENTIFIER, PackageProperties.NAMESPACE_DC); | |||
} | |||
} | |||
private String loadKeywords(Document xmlDoc) { | |||
private String loadKeywords(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_KEYWORDS, PackageNamespaces.CORE_PROPERTIES); | |||
} | |||
} | |||
private String loadLanguage(Document xmlDoc) { | |||
private String loadLanguage(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_LANGUAGE, PackageProperties.NAMESPACE_DC); | |||
} | |||
} | |||
private String loadLastModifiedBy(Document xmlDoc) { | |||
private String loadLastModifiedBy(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_LAST_MODIFIED_BY, PackageNamespaces.CORE_PROPERTIES); | |||
} | |||
} | |||
private String loadLastPrinted(Document xmlDoc) { | |||
private String loadLastPrinted(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_LAST_PRINTED, PackageNamespaces.CORE_PROPERTIES); | |||
} | |||
} | |||
private String loadModified(Document xmlDoc) { | |||
private String loadModified(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_MODIFIED, PackageProperties.NAMESPACE_DCTERMS); | |||
} | |||
} | |||
private String loadRevision(Document xmlDoc) { | |||
private String loadRevision(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_REVISION, PackageNamespaces.CORE_PROPERTIES); | |||
} | |||
} | |||
private String loadSubject(Document xmlDoc) { | |||
private String loadSubject(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_SUBJECT, PackageProperties.NAMESPACE_DC); | |||
} | |||
} | |||
private String loadTitle(Document xmlDoc) { | |||
private String loadTitle(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_TITLE, PackageProperties.NAMESPACE_DC); | |||
} | |||
} | |||
private String loadVersion(Document xmlDoc) { | |||
private String loadVersion(Document xmlDoc) { | |||
return readElement(xmlDoc, KEYWORD_VERSION, PackageNamespaces.CORE_PROPERTIES); | |||
} | |||
/* OPC Compliance methods */ | |||
/** | |||
* Check the element for the following OPC compliance rules: | |||
* <p> | |||
* Rule M4.2: A format consumer shall consider the use of the Markup | |||
* Compatibility namespace to be an error. | |||
* <p> | |||
* Rule M4.3: Producers shall not create a document element that contains | |||
* refinements to the Dublin Core elements, except for the two specified in | |||
* the schema: <dcterms:created> and <dcterms:modified> Consumers shall | |||
* consider a document element that violates this constraint to be an error. | |||
* <p> | |||
* Rule M4.4: Producers shall not create a document element that contains | |||
* the xml:lang attribute. Consumers shall consider a document element that | |||
* violates this constraint to be an error. | |||
* <p> | |||
* Rule M4.5: Producers shall not create a document element that contains | |||
* the xsi:type attribute, except for a <dcterms:created> or | |||
* <dcterms:modified> element where the xsi:type attribute shall be present | |||
* and shall hold the value dcterms:W3CDTF, where dcterms is the namespace | |||
* prefix of the Dublin Core namespace. Consumers shall consider a document | |||
* element that violates this constraint to be an error. | |||
*/ | |||
public void checkElementForOPCCompliance(Element el) | |||
throws InvalidFormatException { | |||
// Check the current element | |||
} | |||
/* OPC Compliance methods */ | |||
/** | |||
* Check the element for the following OPC compliance rules: | |||
* <p> | |||
* Rule M4.2: A format consumer shall consider the use of the Markup | |||
* Compatibility namespace to be an error. | |||
* <p> | |||
* Rule M4.3: Producers shall not create a document element that contains | |||
* refinements to the Dublin Core elements, except for the two specified in | |||
* the schema: <dcterms:created> and <dcterms:modified> Consumers shall | |||
* consider a document element that violates this constraint to be an error. | |||
* <p> | |||
* Rule M4.4: Producers shall not create a document element that contains | |||
* the xml:lang attribute. Consumers shall consider a document element that | |||
* violates this constraint to be an error. | |||
* <p> | |||
* Rule M4.5: Producers shall not create a document element that contains | |||
* the xsi:type attribute, except for a <dcterms:created> or | |||
* <dcterms:modified> element where the xsi:type attribute shall be present | |||
* and shall hold the value dcterms:W3CDTF, where dcterms is the namespace | |||
* prefix of the Dublin Core namespace. Consumers shall consider a document | |||
* element that violates this constraint to be an error. | |||
*/ | |||
public void checkElementForOPCCompliance(Element el) | |||
throws InvalidFormatException { | |||
// Check the current element | |||
NamedNodeMap namedNodeMap = el.getAttributes(); | |||
int namedNodeCount = namedNodeMap.getLength(); | |||
for (int i = 0; i < namedNodeCount; i++) { | |||
@@ -249,42 +249,42 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller { | |||
} | |||
} | |||
// Rule M4.3 | |||
// Rule M4.3 | |||
String elName = el.getLocalName(); | |||
if (el.getNamespaceURI().equals(PackageProperties.NAMESPACE_DCTERMS)) | |||
if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED))) | |||
throw new InvalidFormatException( | |||
"OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: <dcterms:created> and <dcterms:modified> Consumers shall consider a document element that violates this constraint to be an error."); | |||
// Rule M4.4 | |||
if (el.getAttributeNodeNS(XMLConstants.XML_NS_URI, "lang") != null) | |||
throw new InvalidFormatException( | |||
"OPC Compliance error [M4.4]: Producers shall not create a document element that contains the xml:lang attribute. Consumers shall consider a document element that violates this constraint to be an error."); | |||
// Rule M4.5 | |||
if (el.getNamespaceURI().equals(PackageProperties.NAMESPACE_DCTERMS)) { | |||
// DCTerms namespace only use with 'created' and 'modified' elements | |||
if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED))) | |||
throw new InvalidFormatException("Namespace error : " + elName | |||
+ " shouldn't have the following naemspace -> " | |||
+ PackageProperties.NAMESPACE_DCTERMS); | |||
// Check for the 'xsi:type' attribute | |||
Attr typeAtt = el.getAttributeNodeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); | |||
if (typeAtt == null) | |||
throw new InvalidFormatException("The element '" + elName | |||
+ "' must have the 'xsi:type' attribute present !"); | |||
// Check for the attribute value => 'dcterms:W3CDTF' | |||
if (!typeAtt.getValue().equals(el.getPrefix() + ":W3CDTF")) | |||
throw new InvalidFormatException("The element '" + elName | |||
+ "' must have the 'xsi:type' attribute with the value '" + el.getPrefix() + ":W3CDTF', but had '" + typeAtt.getValue() + "' !"); | |||
} | |||
// Check its children | |||
// Rule M4.4 | |||
if (el.getAttributeNodeNS(XMLConstants.XML_NS_URI, "lang") != null) | |||
throw new InvalidFormatException( | |||
"OPC Compliance error [M4.4]: Producers shall not create a document element that contains the xml:lang attribute. Consumers shall consider a document element that violates this constraint to be an error."); | |||
// Rule M4.5 | |||
if (el.getNamespaceURI().equals(PackageProperties.NAMESPACE_DCTERMS)) { | |||
// DCTerms namespace only use with 'created' and 'modified' elements | |||
if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED))) | |||
throw new InvalidFormatException("Namespace error : " + elName | |||
+ " shouldn't have the following naemspace -> " | |||
+ PackageProperties.NAMESPACE_DCTERMS); | |||
// Check for the 'xsi:type' attribute | |||
Attr typeAtt = el.getAttributeNodeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); | |||
if (typeAtt == null) | |||
throw new InvalidFormatException("The element '" + elName | |||
+ "' must have the 'xsi:type' attribute present !"); | |||
// Check for the attribute value => 'dcterms:W3CDTF' | |||
if (!typeAtt.getValue().equals(el.getPrefix() + ":W3CDTF")) | |||
throw new InvalidFormatException("The element '" + elName | |||
+ "' must have the 'xsi:type' attribute with the value '" + el.getPrefix() + ":W3CDTF', but had '" + typeAtt.getValue() + "' !"); | |||
} | |||
// Check its children | |||
NodeList childElements = el.getElementsByTagName("*"); | |||
int childElementCount = childElements.getLength(); | |||
for (int i = 0; i < childElementCount; i++) | |||
checkElementForOPCCompliance((Element)childElements.item(i)); | |||
} | |||
} | |||
} |
@@ -28,67 +28,67 @@ import org.apache.poi.openxml4j.opc.PackagePartName; | |||
*/ | |||
public final class UnmarshallContext { | |||
private OPCPackage _package; | |||
private OPCPackage _package; | |||
private PackagePartName partName; | |||
private PackagePartName partName; | |||
private ZipArchiveEntry zipEntry; | |||
private ZipArchiveEntry zipEntry; | |||
/** | |||
* Constructor. | |||
* | |||
* @param targetPackage | |||
* Container. | |||
* @param partName | |||
* Name of the part to unmarshall. | |||
*/ | |||
public UnmarshallContext(OPCPackage targetPackage, PackagePartName partName) { | |||
this._package = targetPackage; | |||
this.partName = partName; | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param targetPackage | |||
* Container. | |||
* @param partName | |||
* Name of the part to unmarshall. | |||
*/ | |||
public UnmarshallContext(OPCPackage targetPackage, PackagePartName partName) { | |||
this._package = targetPackage; | |||
this.partName = partName; | |||
} | |||
/** | |||
* @return the container | |||
*/ | |||
OPCPackage getPackage() { | |||
return _package; | |||
} | |||
/** | |||
* @return the container | |||
*/ | |||
OPCPackage getPackage() { | |||
return _package; | |||
} | |||
/** | |||
* @param container | |||
* the container to set | |||
*/ | |||
public void setPackage(OPCPackage container) { | |||
this._package = container; | |||
} | |||
/** | |||
* @param container | |||
* the container to set | |||
*/ | |||
public void setPackage(OPCPackage container) { | |||
this._package = container; | |||
} | |||
/** | |||
* @return the partName | |||
*/ | |||
PackagePartName getPartName() { | |||
return partName; | |||
} | |||
/** | |||
* @return the partName | |||
*/ | |||
PackagePartName getPartName() { | |||
return partName; | |||
} | |||
/** | |||
* @param partName | |||
* the partName to set | |||
*/ | |||
public void setPartName(PackagePartName partName) { | |||
this.partName = partName; | |||
} | |||
/** | |||
* @param partName | |||
* the partName to set | |||
*/ | |||
public void setPartName(PackagePartName partName) { | |||
this.partName = partName; | |||
} | |||
/** | |||
* @return the zipEntry | |||
*/ | |||
ZipArchiveEntry getZipEntry() { | |||
return zipEntry; | |||
} | |||
/** | |||
* @return the zipEntry | |||
*/ | |||
ZipArchiveEntry getZipEntry() { | |||
return zipEntry; | |||
} | |||
/** | |||
* @param zipEntry | |||
* the zipEntry to set | |||
*/ | |||
public void setZipEntry(ZipArchiveEntry zipEntry) { | |||
this.zipEntry = zipEntry; | |||
} | |||
/** | |||
* @param zipEntry | |||
* the zipEntry to set | |||
*/ | |||
public void setZipEntry(ZipArchiveEntry zipEntry) { | |||
this.zipEntry = zipEntry; | |||
} | |||
} |
@@ -31,35 +31,35 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; | |||
* being annoyingly very different. | |||
*/ | |||
public interface ZipEntrySource extends Closeable { | |||
/** | |||
* Returns an Enumeration of all the Entries | |||
*/ | |||
Enumeration<? extends ZipArchiveEntry> getEntries(); | |||
/** | |||
* Returns an Enumeration of all the Entries | |||
*/ | |||
Enumeration<? extends ZipArchiveEntry> getEntries(); | |||
/** | |||
* Return an entry by its path | |||
* @param path the path in unix-notation | |||
* @return the entry or {@code null} if not found | |||
* | |||
* @since POI 4.0.0 | |||
*/ | |||
ZipArchiveEntry getEntry(String path); | |||
/** | |||
* Return an entry by its path | |||
* @param path the path in unix-notation | |||
* @return the entry or {@code null} if not found | |||
* | |||
* @since POI 4.0.0 | |||
*/ | |||
ZipArchiveEntry getEntry(String path); | |||
/** | |||
* Returns an InputStream of the decompressed | |||
* data that makes up the entry | |||
*/ | |||
InputStream getInputStream(ZipArchiveEntry entry) throws IOException; | |||
/** | |||
* Indicates we are done with reading, and | |||
* resources may be freed | |||
*/ | |||
@Override | |||
void close() throws IOException; | |||
/** | |||
* Has close been called already? | |||
*/ | |||
boolean isClosed(); | |||
/** | |||
* Returns an InputStream of the decompressed | |||
* data that makes up the entry | |||
*/ | |||
InputStream getInputStream(ZipArchiveEntry entry) throws IOException; | |||
/** | |||
* Indicates we are done with reading, and | |||
* resources may be freed | |||
*/ | |||
@Override | |||
void close() throws IOException; | |||
/** | |||
* Has close been called already? | |||
*/ | |||
boolean isClosed(); | |||
} |
@@ -34,66 +34,66 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; | |||
* done, to free up that memory! | |||
*/ | |||
public class ZipInputStreamZipEntrySource implements ZipEntrySource { | |||
private final Map<String, ZipArchiveFakeEntry> zipEntries = new HashMap<>(); | |||
private InputStream streamToClose; | |||
/** | |||
* Reads all the entries from the ZipInputStream | |||
* into memory, and don't close (since POI 4.0.1) the source stream. | |||
* We'll then eat lots of memory, but be able to | |||
* work with the entries at-will. | |||
*/ | |||
public ZipInputStreamZipEntrySource(ZipArchiveThresholdInputStream inp) throws IOException { | |||
for (;;) { | |||
final ZipArchiveEntry zipEntry = inp.getNextEntry(); | |||
if (zipEntry == null) { | |||
break; | |||
} | |||
zipEntries.put(zipEntry.getName(), new ZipArchiveFakeEntry(zipEntry, inp)); | |||
} | |||
streamToClose = inp; | |||
} | |||
@Override | |||
public Enumeration<? extends ZipArchiveEntry> getEntries() { | |||
return Collections.enumeration(zipEntries.values()); | |||
} | |||
@Override | |||
public InputStream getInputStream(ZipArchiveEntry zipEntry) { | |||
assert (zipEntry instanceof ZipArchiveFakeEntry); | |||
return ((ZipArchiveFakeEntry)zipEntry).getInputStream(); | |||
} | |||
@Override | |||
public void close() throws IOException { | |||
// Free the memory | |||
zipEntries.clear(); | |||
streamToClose.close(); | |||
} | |||
@Override | |||
public boolean isClosed() { | |||
return zipEntries.isEmpty(); | |||
} | |||
@Override | |||
public ZipArchiveEntry getEntry(final String path) { | |||
final String normalizedPath = path.replace('\\', '/'); | |||
final ZipArchiveEntry ze = zipEntries.get(normalizedPath); | |||
if (ze != null) { | |||
return ze; | |||
} | |||
for (final Map.Entry<String, ZipArchiveFakeEntry> fze : zipEntries.entrySet()) { | |||
if (normalizedPath.equalsIgnoreCase(fze.getKey())) { | |||
return fze.getValue(); | |||
} | |||
} | |||
return null; | |||
} | |||
private final Map<String, ZipArchiveFakeEntry> zipEntries = new HashMap<>(); | |||
private InputStream streamToClose; | |||
/** | |||
* Reads all the entries from the ZipInputStream | |||
* into memory, and don't close (since POI 4.0.1) the source stream. | |||
* We'll then eat lots of memory, but be able to | |||
* work with the entries at-will. | |||
*/ | |||
public ZipInputStreamZipEntrySource(ZipArchiveThresholdInputStream inp) throws IOException { | |||
for (;;) { | |||
final ZipArchiveEntry zipEntry = inp.getNextEntry(); | |||
if (zipEntry == null) { | |||
break; | |||
} | |||
zipEntries.put(zipEntry.getName(), new ZipArchiveFakeEntry(zipEntry, inp)); | |||
} | |||
streamToClose = inp; | |||
} | |||
@Override | |||
public Enumeration<? extends ZipArchiveEntry> getEntries() { | |||
return Collections.enumeration(zipEntries.values()); | |||
} | |||
@Override | |||
public InputStream getInputStream(ZipArchiveEntry zipEntry) { | |||
assert (zipEntry instanceof ZipArchiveFakeEntry); | |||
return ((ZipArchiveFakeEntry)zipEntry).getInputStream(); | |||
} | |||
@Override | |||
public void close() throws IOException { | |||
// Free the memory | |||
zipEntries.clear(); | |||
streamToClose.close(); | |||
} | |||
@Override | |||
public boolean isClosed() { | |||
return zipEntries.isEmpty(); | |||
} | |||
@Override | |||
public ZipArchiveEntry getEntry(final String path) { | |||
final String normalizedPath = path.replace('\\', '/'); | |||
final ZipArchiveEntry ze = zipEntries.get(normalizedPath); | |||
if (ze != null) { | |||
return ze; | |||
} | |||
for (final Map.Entry<String, ZipArchiveFakeEntry> fze : zipEntries.entrySet()) { | |||
if (normalizedPath.equalsIgnoreCase(fze.getKey())) { | |||
return fze.getValue(); | |||
} | |||
} | |||
return null; | |||
} | |||
} |
@@ -1,10 +1,10 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
@@ -68,7 +68,7 @@ public class XSLFComment implements Comment { | |||
final CTCommentAuthor newAuthor = list.addNewCmAuthor(); | |||
newAuthor.setName(author); | |||
newAuthor.setId(maxId+1); | |||
newAuthor.setInitials(author.replaceAll( "\\s*(\\w)\\S*", "$1").toUpperCase(LocaleUtil.getUserLocale())); | |||
newAuthor.setInitials(author.replaceAll( "\\s*(\\w)\\S*", "$1").toUpperCase(LocaleUtil.getUserLocale())); | |||
comment.setAuthorId(maxId+1); | |||
} | |||
@@ -122,7 +122,7 @@ public class XSLFGraphicFrame extends XSLFShape implements GraphicalFrame<XSLFSh | |||
*/ | |||
@Override | |||
public void setRotation(double theta){ | |||
throw new IllegalArgumentException("Operation not supported"); | |||
throw new IllegalArgumentException("Operation not supported"); | |||
} | |||
/** | |||
@@ -135,18 +135,18 @@ public class XSLFGraphicFrame extends XSLFShape implements GraphicalFrame<XSLFSh | |||
* @return rotation angle in degrees | |||
*/ | |||
@Override | |||
public double getRotation(){ | |||
return 0; | |||
public double getRotation(){ | |||
return 0; | |||
} | |||
@Override | |||
public void setFlipHorizontal(boolean flip){ | |||
throw new IllegalArgumentException("Operation not supported"); | |||
public void setFlipHorizontal(boolean flip){ | |||
throw new IllegalArgumentException("Operation not supported"); | |||
} | |||
@Override | |||
public void setFlipVertical(boolean flip){ | |||
throw new IllegalArgumentException("Operation not supported"); | |||
public void setFlipVertical(boolean flip){ | |||
throw new IllegalArgumentException("Operation not supported"); | |||
} | |||
/** | |||
@@ -155,13 +155,13 @@ public class XSLFGraphicFrame extends XSLFShape implements GraphicalFrame<XSLFSh | |||
* @return whether the shape is horizontally flipped | |||
*/ | |||
@Override | |||
public boolean getFlipHorizontal(){ | |||
return false; | |||
public boolean getFlipHorizontal(){ | |||
return false; | |||
} | |||
@Override | |||
public boolean getFlipVertical(){ | |||
return false; | |||
public boolean getFlipVertical(){ | |||
return false; | |||
} | |||
public boolean hasChart() { | |||
@@ -203,7 +203,7 @@ public class XSLFGraphicFrame extends XSLFShape implements GraphicalFrame<XSLFSh | |||
if(uri.equals("http://schemas.openxmlformats.org/drawingml/2006/diagram")){ | |||
copyDiagram(data, (XSLFGraphicFrame)sh); | |||
} if(uri.equals(DRAWINGML_CHART_URI)){ | |||
copyChart(data, (XSLFGraphicFrame)sh); | |||
copyChart(data, (XSLFGraphicFrame)sh); | |||
} else { | |||
// TODO support other types of objects | |||
@@ -80,7 +80,7 @@ implements Notes<XSLFShape,XSLFTextParagraph> { | |||
@Override | |||
public XSLFTheme getTheme(){ | |||
final XSLFNotesMaster m = getMasterSheet(); | |||
return (m != null) ? m.getTheme() : null; | |||
return (m != null) ? m.getTheme() : null; | |||
} | |||
@Override |
@@ -46,7 +46,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument; | |||
@Beta | |||
public class XSLFNotesMaster extends XSLFSheet | |||
implements MasterSheet<XSLFShape,XSLFTextParagraph> { | |||
private CTNotesMaster _slide; | |||
private CTNotesMaster _slide; | |||
XSLFNotesMaster() { | |||
super(); |
@@ -53,7 +53,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument; | |||
@Beta | |||
public class XSLFSlideMaster extends XSLFSheet | |||
implements MasterSheet<XSLFShape,XSLFTextParagraph> { | |||
private CTSlideMaster _slide; | |||
private CTSlideMaster _slide; | |||
private Map<String, XSLFSlideLayout> _layouts; | |||
/** | |||
@@ -67,9 +67,9 @@ import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument; | |||
} | |||
@Override | |||
public CTSlideMaster getXmlObject() { | |||
return _slide; | |||
} | |||
public CTSlideMaster getXmlObject() { | |||
return _slide; | |||
} | |||
@Override | |||
protected String getRootElementName(){ |
@@ -6,7 +6,7 @@ | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
@@ -61,203 +61,203 @@ import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument; | |||
*/ | |||
public class XSLFSlideShow extends POIXMLDocument { | |||
private final PresentationDocument presentationDoc; | |||
/** | |||
* The embedded OLE2 files in the OPC package | |||
*/ | |||
private final List<PackagePart> embedds; | |||
private final PresentationDocument presentationDoc; | |||
/** | |||
* The embedded OLE2 files in the OPC package | |||
*/ | |||
private final List<PackagePart> embedds; | |||
public XSLFSlideShow(OPCPackage container) throws OpenXML4JException, IOException, XmlException { | |||
super(container); | |||
public XSLFSlideShow(OPCPackage container) throws OpenXML4JException, IOException, XmlException { | |||
super(container); | |||
if(getCorePart().getContentType().equals(XSLFRelation.THEME_MANAGER.getContentType())) { | |||
rebase(getPackage()); | |||
} | |||
if(getCorePart().getContentType().equals(XSLFRelation.THEME_MANAGER.getContentType())) { | |||
rebase(getPackage()); | |||
} | |||
presentationDoc = | |||
PresentationDocument.Factory.parse(getCorePart().getInputStream(), DEFAULT_XML_OPTIONS); | |||
presentationDoc = | |||
PresentationDocument.Factory.parse(getCorePart().getInputStream(), DEFAULT_XML_OPTIONS); | |||
embedds = new LinkedList<>(); | |||
for (CTSlideIdListEntry ctSlide : getSlideReferences().getSldIdArray()) { | |||
PackagePart corePart = getCorePart(); | |||
PackagePart slidePart = corePart.getRelatedPart(corePart.getRelationship(ctSlide.getId2())); | |||
embedds = new LinkedList<>(); | |||
for (CTSlideIdListEntry ctSlide : getSlideReferences().getSldIdArray()) { | |||
PackagePart corePart = getCorePart(); | |||
PackagePart slidePart = corePart.getRelatedPart(corePart.getRelationship(ctSlide.getId2())); | |||
for(PackageRelationship rel : slidePart.getRelationshipsByType(OLE_OBJECT_REL_TYPE)) { | |||
if (TargetMode.EXTERNAL == rel.getTargetMode()) { | |||
continue; | |||
} | |||
// TODO: Add this reference to each slide as well | |||
embedds.add(slidePart.getRelatedPart(rel)); | |||
} | |||
for(PackageRelationship rel : slidePart.getRelationshipsByType(OLE_OBJECT_REL_TYPE)) { | |||
if (TargetMode.EXTERNAL == rel.getTargetMode()) { | |||
continue; | |||
} | |||
// TODO: Add this reference to each slide as well | |||
embedds.add(slidePart.getRelatedPart(rel)); | |||
} | |||
for (PackageRelationship rel : slidePart.getRelationshipsByType(PACK_OBJECT_REL_TYPE)) { | |||
embedds.add(slidePart.getRelatedPart(rel)); | |||
} | |||
} | |||
} | |||
public XSLFSlideShow(String file) throws OpenXML4JException, IOException, XmlException { | |||
this(openPackage(file)); | |||
} | |||
for (PackageRelationship rel : slidePart.getRelationshipsByType(PACK_OBJECT_REL_TYPE)) { | |||
embedds.add(slidePart.getRelatedPart(rel)); | |||
} | |||
} | |||
} | |||
public XSLFSlideShow(String file) throws OpenXML4JException, IOException, XmlException { | |||
this(openPackage(file)); | |||
} | |||
/** | |||
* Returns the low level presentation base object | |||
*/ | |||
@Internal | |||
public CTPresentation getPresentation() { | |||
return presentationDoc.getPresentation(); | |||
} | |||
/** | |||
* Returns the low level presentation base object | |||
*/ | |||
@Internal | |||
public CTPresentation getPresentation() { | |||
return presentationDoc.getPresentation(); | |||
} | |||
/** | |||
* Returns the references from the presentation to its | |||
* slides. | |||
* You'll need these to figure out the slide ordering, | |||
* and to get at the actual slides themselves | |||
*/ | |||
@Internal | |||
public CTSlideIdList getSlideReferences() { | |||
if(! getPresentation().isSetSldIdLst()) { | |||
getPresentation().setSldIdLst(CTSlideIdList.Factory.newInstance()); | |||
} | |||
return getPresentation().getSldIdLst(); | |||
} | |||
/** | |||
* Returns the references from the presentation to its | |||
* slides. | |||
* You'll need these to figure out the slide ordering, | |||
* and to get at the actual slides themselves | |||
*/ | |||
@Internal | |||
public CTSlideIdList getSlideReferences() { | |||
if(! getPresentation().isSetSldIdLst()) { | |||
getPresentation().setSldIdLst(CTSlideIdList.Factory.newInstance()); | |||
} | |||
return getPresentation().getSldIdLst(); | |||
} | |||
/** | |||
* Returns the references from the presentation to its | |||
* slide masters. | |||
* You'll need these to get at the actual slide | |||
* masters themselves | |||
*/ | |||
@Internal | |||
public CTSlideMasterIdList getSlideMasterReferences() { | |||
return getPresentation().getSldMasterIdLst(); | |||
} | |||
/** | |||
* Returns the references from the presentation to its | |||
* slide masters. | |||
* You'll need these to get at the actual slide | |||
* masters themselves | |||
*/ | |||
@Internal | |||
public CTSlideMasterIdList getSlideMasterReferences() { | |||
return getPresentation().getSldMasterIdLst(); | |||
} | |||
public PackagePart getSlideMasterPart(CTSlideMasterIdListEntry master) throws IOException, XmlException { | |||
try { | |||
PackagePart corePart = getCorePart(); | |||
return corePart.getRelatedPart( | |||
corePart.getRelationship(master.getId2()) | |||
); | |||
} catch(InvalidFormatException e) { | |||
throw new XmlException(e); | |||
} | |||
} | |||
/** | |||
* Returns the low level slide master object from | |||
* the supplied slide master reference | |||
*/ | |||
@Internal | |||
public CTSlideMaster getSlideMaster(CTSlideMasterIdListEntry master) throws IOException, XmlException { | |||
PackagePart masterPart = getSlideMasterPart(master); | |||
SldMasterDocument masterDoc = | |||
SldMasterDocument.Factory.parse(masterPart.getInputStream(), DEFAULT_XML_OPTIONS); | |||
return masterDoc.getSldMaster(); | |||
} | |||
public PackagePart getSlideMasterPart(CTSlideMasterIdListEntry master) throws IOException, XmlException { | |||
try { | |||
PackagePart corePart = getCorePart(); | |||
return corePart.getRelatedPart( | |||
corePart.getRelationship(master.getId2()) | |||
); | |||
} catch(InvalidFormatException e) { | |||
throw new XmlException(e); | |||
} | |||
} | |||
/** | |||
* Returns the low level slide master object from | |||
* the supplied slide master reference | |||
*/ | |||
@Internal | |||
public CTSlideMaster getSlideMaster(CTSlideMasterIdListEntry master) throws IOException, XmlException { | |||
PackagePart masterPart = getSlideMasterPart(master); | |||
SldMasterDocument masterDoc = | |||
SldMasterDocument.Factory.parse(masterPart.getInputStream(), DEFAULT_XML_OPTIONS); | |||
return masterDoc.getSldMaster(); | |||
} | |||
public PackagePart getSlidePart(CTSlideIdListEntry slide) throws IOException, XmlException { | |||
try { | |||
PackagePart corePart = getCorePart(); | |||
return corePart.getRelatedPart(corePart.getRelationship(slide.getId2())); | |||
} catch(InvalidFormatException e) { | |||
throw new XmlException(e); | |||
} | |||
} | |||
/** | |||
* Returns the low level slide object from | |||
* the supplied slide reference | |||
*/ | |||
@Internal | |||
public CTSlide getSlide(CTSlideIdListEntry slide) throws IOException, XmlException { | |||
PackagePart slidePart = getSlidePart(slide); | |||
SldDocument slideDoc = | |||
SldDocument.Factory.parse(slidePart.getInputStream(), DEFAULT_XML_OPTIONS); | |||
return slideDoc.getSld(); | |||
} | |||
public PackagePart getSlidePart(CTSlideIdListEntry slide) throws IOException, XmlException { | |||
try { | |||
PackagePart corePart = getCorePart(); | |||
return corePart.getRelatedPart(corePart.getRelationship(slide.getId2())); | |||
} catch(InvalidFormatException e) { | |||
throw new XmlException(e); | |||
} | |||
} | |||
/** | |||
* Returns the low level slide object from | |||
* the supplied slide reference | |||
*/ | |||
@Internal | |||
public CTSlide getSlide(CTSlideIdListEntry slide) throws IOException, XmlException { | |||
PackagePart slidePart = getSlidePart(slide); | |||
SldDocument slideDoc = | |||
SldDocument.Factory.parse(slidePart.getInputStream(), DEFAULT_XML_OPTIONS); | |||
return slideDoc.getSld(); | |||
} | |||
/** | |||
* Gets the PackagePart of the notes for the | |||
* given slide, or null if there isn't one. | |||
*/ | |||
public PackagePart getNodesPart(CTSlideIdListEntry parentSlide) throws IOException, XmlException { | |||
PackageRelationshipCollection notes; | |||
PackagePart slidePart = getSlidePart(parentSlide); | |||
/** | |||
* Gets the PackagePart of the notes for the | |||
* given slide, or null if there isn't one. | |||
*/ | |||
public PackagePart getNodesPart(CTSlideIdListEntry parentSlide) throws IOException, XmlException { | |||
PackageRelationshipCollection notes; | |||
PackagePart slidePart = getSlidePart(parentSlide); | |||
try { | |||
notes = slidePart.getRelationshipsByType(XSLFRelation.NOTES.getRelation()); | |||
} catch(InvalidFormatException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
try { | |||
notes = slidePart.getRelationshipsByType(XSLFRelation.NOTES.getRelation()); | |||
} catch(InvalidFormatException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
if(notes.size() == 0) { | |||
// No notes for this slide | |||
return null; | |||
} | |||
if(notes.size() > 1) { | |||
throw new IllegalStateException("Expecting 0 or 1 notes for a slide, but found " + notes.size()); | |||
} | |||
if(notes.size() == 0) { | |||
// No notes for this slide | |||
return null; | |||
} | |||
if(notes.size() > 1) { | |||
throw new IllegalStateException("Expecting 0 or 1 notes for a slide, but found " + notes.size()); | |||
} | |||
try { | |||
return slidePart.getRelatedPart(notes.getRelationship(0)); | |||
} catch(InvalidFormatException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
/** | |||
* Returns the low level notes object for the given | |||
* slide, as found from the supplied slide reference | |||
*/ | |||
@Internal | |||
public CTNotesSlide getNotes(CTSlideIdListEntry slide) throws IOException, XmlException { | |||
PackagePart notesPart = getNodesPart(slide); | |||
if(notesPart == null) | |||
return null; | |||
try { | |||
return slidePart.getRelatedPart(notes.getRelationship(0)); | |||
} catch(InvalidFormatException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
/** | |||
* Returns the low level notes object for the given | |||
* slide, as found from the supplied slide reference | |||
*/ | |||
@Internal | |||
public CTNotesSlide getNotes(CTSlideIdListEntry slide) throws IOException, XmlException { | |||
PackagePart notesPart = getNodesPart(slide); | |||
if(notesPart == null) | |||
return null; | |||
NotesDocument notesDoc = | |||
NotesDocument.Factory.parse(notesPart.getInputStream(), DEFAULT_XML_OPTIONS); | |||
NotesDocument notesDoc = | |||
NotesDocument.Factory.parse(notesPart.getInputStream(), DEFAULT_XML_OPTIONS); | |||
return notesDoc.getNotes(); | |||
} | |||
return notesDoc.getNotes(); | |||
} | |||
/** | |||
* Returns all the comments for the given slide | |||
*/ | |||
@Internal | |||
public CTCommentList getSlideComments(CTSlideIdListEntry slide) throws IOException, XmlException { | |||
PackageRelationshipCollection commentRels; | |||
PackagePart slidePart = getSlidePart(slide); | |||
/** | |||
* Returns all the comments for the given slide | |||
*/ | |||
@Internal | |||
public CTCommentList getSlideComments(CTSlideIdListEntry slide) throws IOException, XmlException { | |||
PackageRelationshipCollection commentRels; | |||
PackagePart slidePart = getSlidePart(slide); | |||
try { | |||
commentRels = slidePart.getRelationshipsByType(XSLFRelation.COMMENTS.getRelation()); | |||
} catch(InvalidFormatException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
try { | |||
commentRels = slidePart.getRelationshipsByType(XSLFRelation.COMMENTS.getRelation()); | |||
} catch(InvalidFormatException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
if(commentRels.size() == 0) { | |||
// No comments for this slide | |||
return null; | |||
} | |||
if(commentRels.size() > 1) { | |||
throw new IllegalStateException("Expecting 0 or 1 comments for a slide, but found " + commentRels.size()); | |||
} | |||
if(commentRels.size() == 0) { | |||
// No comments for this slide | |||
return null; | |||
} | |||
if(commentRels.size() > 1) { | |||
throw new IllegalStateException("Expecting 0 or 1 comments for a slide, but found " + commentRels.size()); | |||
} | |||
try { | |||
PackagePart cPart = slidePart.getRelatedPart( | |||
commentRels.getRelationship(0) | |||
); | |||
CmLstDocument commDoc = | |||
CmLstDocument.Factory.parse(cPart.getInputStream(), DEFAULT_XML_OPTIONS); | |||
return commDoc.getCmLst(); | |||
} catch(InvalidFormatException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
try { | |||
PackagePart cPart = slidePart.getRelatedPart( | |||
commentRels.getRelationship(0) | |||
); | |||
CmLstDocument commDoc = | |||
CmLstDocument.Factory.parse(cPart.getInputStream(), DEFAULT_XML_OPTIONS); | |||
return commDoc.getCmLst(); | |||
} catch(InvalidFormatException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
/** | |||
* Get the document's embedded files. | |||
*/ | |||
@Override | |||
public List<PackagePart> getAllEmbeddedParts() throws OpenXML4JException { | |||
return embedds; | |||
} | |||
/** | |||
* Get the document's embedded files. | |||
*/ | |||
@Override | |||
public List<PackagePart> getAllEmbeddedParts() throws OpenXML4JException { | |||
return embedds; | |||
} | |||
} |
@@ -279,50 +279,50 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow | |||
@SuppressWarnings("unused") | |||
public void mergeCells(int firstRow, int lastRow, int firstCol, int lastCol) { | |||
if(firstRow > lastRow) { | |||
throw new IllegalArgumentException( | |||
"Cannot merge, first row > last row : " | |||
+ firstRow + " > " + lastRow | |||
); | |||
} | |||
if(firstCol > lastCol) { | |||
throw new IllegalArgumentException( | |||
"Cannot merge, first column > last column : " | |||
+ firstCol + " > " + lastCol | |||
); | |||
} | |||
int rowSpan = (lastRow - firstRow) + 1; | |||
boolean mergeRowRequired = rowSpan > 1; | |||
int colSpan = (lastCol - firstCol) + 1; | |||
boolean mergeColumnRequired = colSpan > 1; | |||
for(int i = firstRow; i <= lastRow; i++) { | |||
XSLFTableRow row = _rows.get(i); | |||
for(int colPos = firstCol; colPos <= lastCol; colPos++) { | |||
XSLFTableCell cell = row.getCells().get(colPos); | |||
if(mergeRowRequired) { | |||
if(i == firstRow) { | |||
cell.setRowSpan(rowSpan); | |||
} else { | |||
cell.setVMerge(); | |||
} | |||
} | |||
if(mergeColumnRequired) { | |||
if(colPos == firstCol) { | |||
cell.setGridSpan(colSpan); | |||
} else { | |||
cell.setHMerge(); | |||
} | |||
} | |||
} | |||
} | |||
if(firstRow > lastRow) { | |||
throw new IllegalArgumentException( | |||
"Cannot merge, first row > last row : " | |||
+ firstRow + " > " + lastRow | |||
); | |||
} | |||
if(firstCol > lastCol) { | |||
throw new IllegalArgumentException( | |||
"Cannot merge, first column > last column : " | |||
+ firstCol + " > " + lastCol | |||
); | |||
} | |||
int rowSpan = (lastRow - firstRow) + 1; | |||
boolean mergeRowRequired = rowSpan > 1; | |||
int colSpan = (lastCol - firstCol) + 1; | |||
boolean mergeColumnRequired = colSpan > 1; | |||
for(int i = firstRow; i <= lastRow; i++) { | |||
XSLFTableRow row = _rows.get(i); | |||
for(int colPos = firstCol; colPos <= lastCol; colPos++) { | |||
XSLFTableCell cell = row.getCells().get(colPos); | |||
if(mergeRowRequired) { | |||
if(i == firstRow) { | |||
cell.setRowSpan(rowSpan); | |||
} else { | |||
cell.setVMerge(); | |||
} | |||
} | |||
if(mergeColumnRequired) { | |||
if(colPos == firstCol) { | |||
cell.setGridSpan(colSpan); | |||
} else { | |||
cell.setHMerge(); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** |
@@ -717,18 +717,18 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr | |||
try { | |||
cur.push(); | |||
if ((cur.toChild(nsPML, "txStyles") && cur.toChild(nsPML, defaultStyleSelector)) || | |||
(cur.pop() && cur.toChild(nsPML, "notesStyle"))) { | |||
(cur.pop() && cur.toChild(nsPML, "notesStyle"))) { | |||
while (level >= 0) { | |||
cur.push(); | |||
if (cur.toChild(XSLFRelation.NS_DRAWINGML, "lvl" +(level+1)+ "pPr")) { | |||
return (CTTextParagraphProperties)cur.getObject(); | |||
} | |||
cur.pop(); | |||
level--; | |||
if (cur.toChild(XSLFRelation.NS_DRAWINGML, "lvl" +(level+1)+ "pPr")) { | |||
return (CTTextParagraphProperties)cur.getObject(); | |||
} | |||
cur.pop(); | |||
level--; | |||
} | |||
} | |||
} finally { | |||
cur.dispose(); | |||
cur.dispose(); | |||
} | |||
} | |||
@@ -87,7 +87,7 @@ public class XSLFTheme extends POIXMLDocumentPart { | |||
public CTColor getCTColor(String name) { | |||
CTBaseStyles elems = _theme.getThemeElements(); | |||
CTColorScheme scheme = (elems == null) ? null : elems.getClrScheme(); | |||
return getMapColor(name, scheme); | |||
return getMapColor(name, scheme); | |||
} | |||
@@ -28,6 +28,6 @@ public class XLSBUnsupportedException extends UnsupportedFileFormatException { | |||
public static final String MESSAGE = ".XLSB Binary Workbooks are not supported"; | |||
public XLSBUnsupportedException() { | |||
super(MESSAGE); | |||
} | |||
super(MESSAGE); | |||
} | |||
} |
@@ -461,14 +461,14 @@ public class XSSFExportToXml implements Comparator<String>{ | |||
return indexMap.getOrDefault(withPath, -1); | |||
} | |||
private Node getNameOrRefElement(Node node) { | |||
Node returnNode = node.getAttributes().getNamedItem("ref"); | |||
private Node getNameOrRefElement(Node node) { | |||
Node returnNode = node.getAttributes().getNamedItem("ref"); | |||
if(returnNode != null) { | |||
return returnNode; | |||
} | |||
} | |||
return node.getAttributes().getNamedItem("name"); | |||
} | |||
} | |||
private Node getComplexTypeForElement(String elementName,Node xmlSchema,Node localComplexTypeRootNode) { | |||
String elementNameWithoutNamespace = removeNamespace(elementName); |
@@ -48,40 +48,40 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.MapInfoDocument; | |||
public class MapInfo extends POIXMLDocumentPart { | |||
private CTMapInfo mapInfo; | |||
private CTMapInfo mapInfo; | |||
private Map<Integer, XSSFMap> maps ; | |||
private Map<Integer, XSSFMap> maps ; | |||
public MapInfo() { | |||
super(); | |||
mapInfo = CTMapInfo.Factory.newInstance(); | |||
public MapInfo() { | |||
super(); | |||
mapInfo = CTMapInfo.Factory.newInstance(); | |||
} | |||
} | |||
/** | |||
/** | |||
* @since POI 3.14-Beta1 | |||
*/ | |||
public MapInfo(PackagePart part) throws IOException { | |||
super(part); | |||
readFrom(part.getInputStream()); | |||
public MapInfo(PackagePart part) throws IOException { | |||
super(part); | |||
readFrom(part.getInputStream()); | |||
} | |||
public void readFrom(InputStream is) throws IOException { | |||
try { | |||
MapInfoDocument doc = MapInfoDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); | |||
mapInfo = doc.getMapInfo(); | |||
public void readFrom(InputStream is) throws IOException { | |||
try { | |||
MapInfoDocument doc = MapInfoDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); | |||
mapInfo = doc.getMapInfo(); | |||
maps= new HashMap<>(); | |||
for(CTMap map :mapInfo.getMapArray()){ | |||
maps.put((int)map.getID(), new XSSFMap(map,this)); | |||
} | |||
} catch (XmlException e) { | |||
throw new IOException(e.getLocalizedMessage()); | |||
} | |||
} | |||
} catch (XmlException e) { | |||
throw new IOException(e.getLocalizedMessage()); | |||
} | |||
} | |||
/** | |||
/** | |||
* Returns the parent XSSFWorkbook | |||
* | |||
* @return the parent XSSFWorkbook | |||
@@ -90,70 +90,70 @@ public class MapInfo extends POIXMLDocumentPart { | |||
return (XSSFWorkbook)getParent(); | |||
} | |||
/** | |||
* | |||
* @return the internal data object | |||
*/ | |||
public CTMapInfo getCTMapInfo(){ | |||
return mapInfo; | |||
} | |||
/** | |||
* Gets the | |||
* @param schemaId the schema ID | |||
* @return CTSchema by it's ID | |||
*/ | |||
public CTSchema getCTSchemaById(String schemaId){ | |||
CTSchema xmlSchema = null; | |||
for(CTSchema schema: mapInfo.getSchemaArray()){ | |||
if(schema.getID().equals(schemaId)){ | |||
xmlSchema = schema; | |||
break; | |||
} | |||
} | |||
return xmlSchema; | |||
} | |||
public XSSFMap getXSSFMapById(int id){ | |||
return maps.get(id); | |||
} | |||
public XSSFMap getXSSFMapByName(String name){ | |||
XSSFMap matchedMap = null; | |||
for(XSSFMap map :maps.values()){ | |||
if(map.getCtMap().getName()!=null && map.getCtMap().getName().equals(name)){ | |||
matchedMap = map; | |||
} | |||
} | |||
return matchedMap; | |||
} | |||
/** | |||
* | |||
* @return all the mappings configured in this document | |||
*/ | |||
public Collection<XSSFMap> getAllXSSFMaps(){ | |||
return maps.values(); | |||
} | |||
protected void writeTo(OutputStream out) throws IOException { | |||
MapInfoDocument doc = MapInfoDocument.Factory.newInstance(); | |||
doc.setMapInfo(mapInfo); | |||
doc.save(out, DEFAULT_XML_OPTIONS); | |||
} | |||
@Override | |||
protected void commit() throws IOException { | |||
PackagePart part = getPackagePart(); | |||
OutputStream out = part.getOutputStream(); | |||
writeTo(out); | |||
out.close(); | |||
} | |||
/** | |||
* | |||
* @return the internal data object | |||
*/ | |||
public CTMapInfo getCTMapInfo(){ | |||
return mapInfo; | |||
} | |||
/** | |||
* Gets the | |||
* @param schemaId the schema ID | |||
* @return CTSchema by it's ID | |||
*/ | |||
public CTSchema getCTSchemaById(String schemaId){ | |||
CTSchema xmlSchema = null; | |||
for(CTSchema schema: mapInfo.getSchemaArray()){ | |||
if(schema.getID().equals(schemaId)){ | |||
xmlSchema = schema; | |||
break; | |||
} | |||
} | |||
return xmlSchema; | |||
} | |||
public XSSFMap getXSSFMapById(int id){ | |||
return maps.get(id); | |||
} | |||
public XSSFMap getXSSFMapByName(String name){ | |||
XSSFMap matchedMap = null; | |||
for(XSSFMap map :maps.values()){ | |||
if(map.getCtMap().getName()!=null && map.getCtMap().getName().equals(name)){ | |||
matchedMap = map; | |||
} | |||
} | |||
return matchedMap; | |||
} | |||
/** | |||
* | |||
* @return all the mappings configured in this document | |||
*/ | |||
public Collection<XSSFMap> getAllXSSFMaps(){ | |||
return maps.values(); | |||
} | |||
protected void writeTo(OutputStream out) throws IOException { | |||
MapInfoDocument doc = MapInfoDocument.Factory.newInstance(); | |||
doc.setMapInfo(mapInfo); | |||
doc.save(out, DEFAULT_XML_OPTIONS); | |||
} | |||
@Override | |||
protected void commit() throws IOException { | |||
PackagePart part = getPackagePart(); | |||
OutputStream out = part.getOutputStream(); | |||
writeTo(out); | |||
out.close(); | |||
} | |||
} |
@@ -43,63 +43,63 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.SingleXmlCellsDocumen | |||
public class SingleXmlCells extends POIXMLDocumentPart { | |||
private CTSingleXmlCells singleXMLCells; | |||
public SingleXmlCells() { | |||
super(); | |||
singleXMLCells = CTSingleXmlCells.Factory.newInstance(); | |||
} | |||
/** | |||
* @since POI 3.14-Beta1 | |||
*/ | |||
public SingleXmlCells(PackagePart part) throws IOException { | |||
super(part); | |||
readFrom(part.getInputStream()); | |||
} | |||
public void readFrom(InputStream is) throws IOException { | |||
try { | |||
SingleXmlCellsDocument doc = SingleXmlCellsDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); | |||
singleXMLCells = doc.getSingleXmlCells(); | |||
} catch (XmlException e) { | |||
throw new IOException(e.getLocalizedMessage()); | |||
} | |||
} | |||
public XSSFSheet getXSSFSheet(){ | |||
return (XSSFSheet) getParent(); | |||
} | |||
protected void writeTo(OutputStream out) throws IOException { | |||
SingleXmlCellsDocument doc = SingleXmlCellsDocument.Factory.newInstance(); | |||
doc.setSingleXmlCells(singleXMLCells); | |||
doc.save(out, DEFAULT_XML_OPTIONS); | |||
} | |||
@Override | |||
protected void commit() throws IOException { | |||
PackagePart part = getPackagePart(); | |||
OutputStream out = part.getOutputStream(); | |||
writeTo(out); | |||
out.close(); | |||
} | |||
public CTSingleXmlCells getCTSingleXMLCells(){ | |||
return singleXMLCells; | |||
} | |||
/** | |||
* | |||
* @return all the SimpleXmlCell contained in this SingleXmlCells element | |||
*/ | |||
public List<XSSFSingleXmlCell> getAllSimpleXmlCell(){ | |||
List<XSSFSingleXmlCell> list = new Vector<>(); | |||
for(CTSingleXmlCell singleXmlCell: singleXMLCells.getSingleXmlCellArray()){ | |||
list.add(new XSSFSingleXmlCell(singleXmlCell,this)); | |||
} | |||
return list; | |||
} | |||
private CTSingleXmlCells singleXMLCells; | |||
public SingleXmlCells() { | |||
super(); | |||
singleXMLCells = CTSingleXmlCells.Factory.newInstance(); | |||
} | |||
/** | |||
* @since POI 3.14-Beta1 | |||
*/ | |||
public SingleXmlCells(PackagePart part) throws IOException { | |||
super(part); | |||
readFrom(part.getInputStream()); | |||
} | |||
public void readFrom(InputStream is) throws IOException { | |||
try { | |||
SingleXmlCellsDocument doc = SingleXmlCellsDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); | |||
singleXMLCells = doc.getSingleXmlCells(); | |||
} catch (XmlException e) { | |||
throw new IOException(e.getLocalizedMessage()); | |||
} | |||
} | |||
public XSSFSheet getXSSFSheet(){ | |||
return (XSSFSheet) getParent(); | |||
} | |||
protected void writeTo(OutputStream out) throws IOException { | |||
SingleXmlCellsDocument doc = SingleXmlCellsDocument.Factory.newInstance(); | |||
doc.setSingleXmlCells(singleXMLCells); | |||
doc.save(out, DEFAULT_XML_OPTIONS); | |||
} | |||
@Override | |||
protected void commit() throws IOException { | |||
PackagePart part = getPackagePart(); | |||
OutputStream out = part.getOutputStream(); | |||
writeTo(out); | |||
out.close(); | |||
} | |||
public CTSingleXmlCells getCTSingleXMLCells(){ | |||
return singleXMLCells; | |||
} | |||
/** | |||
* | |||
* @return all the SimpleXmlCell contained in this SingleXmlCells element | |||
*/ | |||
public List<XSSFSingleXmlCell> getAllSimpleXmlCell(){ | |||
List<XSSFSingleXmlCell> list = new Vector<>(); | |||
for(CTSingleXmlCell singleXmlCell: singleXMLCells.getSingleXmlCellArray()){ | |||
list.add(new XSSFSingleXmlCell(singleXmlCell,this)); | |||
} | |||
return list; | |||
} | |||
} |
@@ -39,11 +39,11 @@ public class GZIPSheetDataWriter extends SheetDataWriter { | |||
public GZIPSheetDataWriter() throws IOException { | |||
super(); | |||
} | |||
/** | |||
/** | |||
* @param sharedStringsTable the shared strings table, or null if inline text is used | |||
*/ | |||
public GZIPSheetDataWriter(SharedStringsTable sharedStringsTable) throws IOException { | |||
public GZIPSheetDataWriter(SharedStringsTable sharedStringsTable) throws IOException { | |||
super(sharedStringsTable); | |||
} | |||
@@ -113,8 +113,8 @@ public final class SXSSFFormulaEvaluator extends BaseXSSFFormulaEvaluator { | |||
int lastFlushedRowNum = ((SXSSFSheet) sheet).getLastFlushedRowNum(); | |||
if (lastFlushedRowNum > -1) { | |||
if (!skipOutOfWindow) { | |||
throw new RowFlushedException(0, lastFlushedRowNum); | |||
} | |||
throw new RowFlushedException(0, lastFlushedRowNum); | |||
} | |||
LOG.atInfo().log("Rows up to {} have already been flushed, skipping", box(lastFlushedRowNum)); | |||
} |
@@ -200,7 +200,7 @@ public final class SXSSFPicture implements Picture { | |||
private float getRowHeightInPixels(int rowIndex) { | |||
// THE FOLLOWING THREE LINES ARE THE MAIN CHANGE compared to the non-streaming version: use the SXSSF sheet, | |||
// not the XSSF sheet (which never contais rows when using SXSSF) | |||
// not the XSSF sheet (which never contais rows when using SXSSF) | |||
XSSFSheet xssfSheet = getSheet(); | |||
SXSSFSheet sxSheet = _wb.getSXSSFSheet(xssfSheet); | |||
Sheet sheet = sxSheet == null ? xssfSheet : sxSheet; |
@@ -22,10 +22,10 @@ package org.apache.poi.xssf.usermodel; | |||
* Specified a list of text font alignment types | |||
*/ | |||
public enum TextFontAlign { | |||
/** | |||
* Automatic alignment | |||
*/ | |||
AUTO, | |||
/** | |||
* Automatic alignment | |||
*/ | |||
AUTO, | |||
/** | |||
* Align text to the top. | |||
*/ |
@@ -27,227 +27,227 @@ public class XSSFDataValidationConstraint implements DataValidationConstraint { | |||
/** | |||
* Excel validation constraints with static lists are delimited with optional whitespace and the Windows List Separator, | |||
* which is typically comma, but can be changed by users. POI will just assume comma. | |||
* In addition, Excel validation with static lists has a maximum size of 255 characters, including separators and excluding quotes. | |||
* In addition, Excel validation with static lists has a maximum size of 255 characters, including separators and excluding quotes. | |||
*/ | |||
private static final String LIST_SEPARATOR = ","; | |||
private static final Pattern LIST_SPLIT_REGEX = Pattern.compile("\\s*" + LIST_SEPARATOR + "\\s*"); | |||
private static final String QUOTE = "\""; | |||
private static final int MAX_EXPLICIT_LIST_LENGTH = 257; | |||
private String formula1; | |||
private String formula2; | |||
private final int validationType; | |||
private int operator = -1; | |||
private String[] explicitListOfValues; | |||
/** | |||
* list literal constructor | |||
*/ | |||
public XSSFDataValidationConstraint(String[] explicitListOfValues) { | |||
if( explicitListOfValues==null || explicitListOfValues.length==0) { | |||
throw new IllegalArgumentException("List validation with explicit values must specify at least one value"); | |||
} | |||
this.validationType = ValidationType.LIST; | |||
setExplicitListValues(explicitListOfValues); | |||
validate(); | |||
} | |||
public XSSFDataValidationConstraint(int validationType, String formula1) { | |||
super(); | |||
setFormula1(formula1); | |||
this.validationType = validationType; | |||
validate(); | |||
} | |||
public XSSFDataValidationConstraint(int validationType, int operator, String formula1) { | |||
super(); | |||
setFormula1(formula1); | |||
this.validationType = validationType; | |||
this.operator = operator; | |||
validate(); | |||
} | |||
/** | |||
* This is the constructor called using the OOXML raw data. Excel overloads formula1 to also encode explicit value lists, | |||
* so this constructor has to check for and parse that syntax. | |||
* @param formula1 Overloaded: formula1 or list of explicit values | |||
* @param formula2 (formula1 is a list of explicit values, this is ignored: use {@code null}) | |||
*/ | |||
public XSSFDataValidationConstraint(int validationType, int operator, String formula1, String formula2) { | |||
super(); | |||
//removes leading equals sign if present | |||
setFormula1(formula1); | |||
setFormula2(formula2); | |||
this.validationType = validationType; | |||
this.operator = operator; | |||
validate(); | |||
//FIXME: Need to confirm if this is not a formula. | |||
// empirical testing shows Excel saves explicit lists surrounded by double quotes, | |||
// range formula expressions can't start with quotes (I think - anyone have a creative counter example?) | |||
if ( ValidationType.LIST == validationType | |||
&& this.formula1 != null | |||
&& isQuoted(this.formula1) ) { | |||
explicitListOfValues = LIST_SPLIT_REGEX.split(unquote(this.formula1)); | |||
} | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getExplicitListValues() | |||
*/ | |||
@Override | |||
public String[] getExplicitListValues() { | |||
return explicitListOfValues; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getFormula1() | |||
*/ | |||
@Override | |||
public String getFormula1() { | |||
return formula1; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getFormula2() | |||
*/ | |||
@Override | |||
public String getFormula2() { | |||
return formula2; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getOperator() | |||
*/ | |||
@Override | |||
public int getOperator() { | |||
return operator; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getValidationType() | |||
*/ | |||
@Override | |||
public int getValidationType() { | |||
return validationType; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setExplicitListValues(java.lang.String[]) | |||
*/ | |||
@Override | |||
public void setExplicitListValues(String[] explicitListValues) { | |||
this.explicitListOfValues = explicitListValues; | |||
// for OOXML we need to set formula1 to the quoted csv list of values (doesn't appear documented, but that's where Excel puts its lists) | |||
// further, Excel has no escaping for commas in explicit lists, so we don't need to worry about that. | |||
if ( explicitListOfValues!=null && explicitListOfValues.length > 0 ) { | |||
StringBuilder builder = new StringBuilder(QUOTE); | |||
for (String string : explicitListValues) { | |||
if (builder.length() > 1) { | |||
builder.append(LIST_SEPARATOR); | |||
} | |||
builder.append(string); | |||
} | |||
builder.append(QUOTE); | |||
setFormula1(builder.toString()); | |||
} | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setFormula1(java.lang.String) | |||
*/ | |||
@Override | |||
public void setFormula1(String formula1) { | |||
this.formula1 = removeLeadingEquals(formula1); | |||
} | |||
protected static String removeLeadingEquals(String formula1) { | |||
return isFormulaEmpty(formula1) ? formula1 : formula1.charAt(0)=='=' ? formula1.substring(1) : formula1; | |||
} | |||
private static boolean isQuoted(String s) { | |||
return s.startsWith(QUOTE) && s.endsWith(QUOTE); | |||
} | |||
private static String unquote(String s) { | |||
// removes leading and trailing quotes from a quoted string | |||
if (isQuoted(s)) { | |||
return s.substring(1, s.length()-1); | |||
} | |||
return s; | |||
} | |||
protected static boolean isFormulaEmpty(String formula1) { | |||
return formula1 == null || formula1.trim().length()==0; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setFormula2(java.lang.String) | |||
*/ | |||
@Override | |||
public void setFormula2(String formula2) { | |||
this.formula2 = removeLeadingEquals(formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setOperator(int) | |||
*/ | |||
@Override | |||
public void setOperator(int operator) { | |||
this.operator = operator; | |||
} | |||
public void validate() { | |||
if (validationType==ValidationType.ANY) { | |||
return; | |||
} | |||
if (validationType==ValidationType.LIST ) { | |||
if (isFormulaEmpty(formula1)) { | |||
throw new IllegalArgumentException("A valid formula or a list of values must be specified for list validation."); | |||
} | |||
if(formula1.length() > MAX_EXPLICIT_LIST_LENGTH) { | |||
throw new IllegalArgumentException("A valid formula or a list of values must be less than or equal to 255 characters (including separators)."); | |||
} | |||
} else { | |||
if( isFormulaEmpty(formula1) ) { | |||
throw new IllegalArgumentException("Formula is not specified. Formula is required for all validation types except explicit list validation."); | |||
} | |||
if( validationType!= ValidationType.FORMULA ) { | |||
if (operator==-1) { | |||
throw new IllegalArgumentException("This validation type requires an operator to be specified."); | |||
} else if (( operator==OperatorType.BETWEEN || operator==OperatorType.NOT_BETWEEN) && isFormulaEmpty(formula2)) { | |||
throw new IllegalArgumentException("Between and not between comparisons require two formulae to be specified."); | |||
} | |||
} | |||
} | |||
} | |||
public String prettyPrint() { | |||
StringBuilder builder = new StringBuilder(); | |||
STDataValidationType.Enum vt = XSSFDataValidation.validationTypeMappings.get(validationType); | |||
Enum ot = XSSFDataValidation.operatorTypeMappings.get(operator); | |||
builder.append(vt); | |||
builder.append(' '); | |||
if (validationType!=ValidationType.ANY) { | |||
if (validationType != ValidationType.LIST | |||
&& validationType != ValidationType.FORMULA) { | |||
builder.append(LIST_SEPARATOR).append(ot).append(", "); | |||
} | |||
final String NOQUOTE = ""; | |||
if (validationType == ValidationType.LIST && explicitListOfValues != null) { | |||
builder.append(NOQUOTE).append(Arrays.asList(explicitListOfValues)).append(NOQUOTE).append(' '); | |||
} else { | |||
builder.append(NOQUOTE).append(formula1).append(NOQUOTE).append(' '); | |||
} | |||
if (formula2 != null) { | |||
builder.append(NOQUOTE).append(formula2).append(NOQUOTE).append(' '); | |||
} | |||
} | |||
return builder.toString(); | |||
} | |||
private static final int MAX_EXPLICIT_LIST_LENGTH = 257; | |||
private String formula1; | |||
private String formula2; | |||
private final int validationType; | |||
private int operator = -1; | |||
private String[] explicitListOfValues; | |||
/** | |||
* list literal constructor | |||
*/ | |||
public XSSFDataValidationConstraint(String[] explicitListOfValues) { | |||
if( explicitListOfValues==null || explicitListOfValues.length==0) { | |||
throw new IllegalArgumentException("List validation with explicit values must specify at least one value"); | |||
} | |||
this.validationType = ValidationType.LIST; | |||
setExplicitListValues(explicitListOfValues); | |||
validate(); | |||
} | |||
public XSSFDataValidationConstraint(int validationType, String formula1) { | |||
super(); | |||
setFormula1(formula1); | |||
this.validationType = validationType; | |||
validate(); | |||
} | |||
public XSSFDataValidationConstraint(int validationType, int operator, String formula1) { | |||
super(); | |||
setFormula1(formula1); | |||
this.validationType = validationType; | |||
this.operator = operator; | |||
validate(); | |||
} | |||
/** | |||
* This is the constructor called using the OOXML raw data. Excel overloads formula1 to also encode explicit value lists, | |||
* so this constructor has to check for and parse that syntax. | |||
* @param formula1 Overloaded: formula1 or list of explicit values | |||
* @param formula2 (formula1 is a list of explicit values, this is ignored: use {@code null}) | |||
*/ | |||
public XSSFDataValidationConstraint(int validationType, int operator, String formula1, String formula2) { | |||
super(); | |||
//removes leading equals sign if present | |||
setFormula1(formula1); | |||
setFormula2(formula2); | |||
this.validationType = validationType; | |||
this.operator = operator; | |||
validate(); | |||
//FIXME: Need to confirm if this is not a formula. | |||
// empirical testing shows Excel saves explicit lists surrounded by double quotes, | |||
// range formula expressions can't start with quotes (I think - anyone have a creative counter example?) | |||
if ( ValidationType.LIST == validationType | |||
&& this.formula1 != null | |||
&& isQuoted(this.formula1) ) { | |||
explicitListOfValues = LIST_SPLIT_REGEX.split(unquote(this.formula1)); | |||
} | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getExplicitListValues() | |||
*/ | |||
@Override | |||
public String[] getExplicitListValues() { | |||
return explicitListOfValues; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getFormula1() | |||
*/ | |||
@Override | |||
public String getFormula1() { | |||
return formula1; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getFormula2() | |||
*/ | |||
@Override | |||
public String getFormula2() { | |||
return formula2; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getOperator() | |||
*/ | |||
@Override | |||
public int getOperator() { | |||
return operator; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#getValidationType() | |||
*/ | |||
@Override | |||
public int getValidationType() { | |||
return validationType; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setExplicitListValues(java.lang.String[]) | |||
*/ | |||
@Override | |||
public void setExplicitListValues(String[] explicitListValues) { | |||
this.explicitListOfValues = explicitListValues; | |||
// for OOXML we need to set formula1 to the quoted csv list of values (doesn't appear documented, but that's where Excel puts its lists) | |||
// further, Excel has no escaping for commas in explicit lists, so we don't need to worry about that. | |||
if ( explicitListOfValues!=null && explicitListOfValues.length > 0 ) { | |||
StringBuilder builder = new StringBuilder(QUOTE); | |||
for (String string : explicitListValues) { | |||
if (builder.length() > 1) { | |||
builder.append(LIST_SEPARATOR); | |||
} | |||
builder.append(string); | |||
} | |||
builder.append(QUOTE); | |||
setFormula1(builder.toString()); | |||
} | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setFormula1(java.lang.String) | |||
*/ | |||
@Override | |||
public void setFormula1(String formula1) { | |||
this.formula1 = removeLeadingEquals(formula1); | |||
} | |||
protected static String removeLeadingEquals(String formula1) { | |||
return isFormulaEmpty(formula1) ? formula1 : formula1.charAt(0)=='=' ? formula1.substring(1) : formula1; | |||
} | |||
private static boolean isQuoted(String s) { | |||
return s.startsWith(QUOTE) && s.endsWith(QUOTE); | |||
} | |||
private static String unquote(String s) { | |||
// removes leading and trailing quotes from a quoted string | |||
if (isQuoted(s)) { | |||
return s.substring(1, s.length()-1); | |||
} | |||
return s; | |||
} | |||
protected static boolean isFormulaEmpty(String formula1) { | |||
return formula1 == null || formula1.trim().length()==0; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setFormula2(java.lang.String) | |||
*/ | |||
@Override | |||
public void setFormula2(String formula2) { | |||
this.formula2 = removeLeadingEquals(formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint#setOperator(int) | |||
*/ | |||
@Override | |||
public void setOperator(int operator) { | |||
this.operator = operator; | |||
} | |||
public void validate() { | |||
if (validationType==ValidationType.ANY) { | |||
return; | |||
} | |||
if (validationType==ValidationType.LIST ) { | |||
if (isFormulaEmpty(formula1)) { | |||
throw new IllegalArgumentException("A valid formula or a list of values must be specified for list validation."); | |||
} | |||
if(formula1.length() > MAX_EXPLICIT_LIST_LENGTH) { | |||
throw new IllegalArgumentException("A valid formula or a list of values must be less than or equal to 255 characters (including separators)."); | |||
} | |||
} else { | |||
if( isFormulaEmpty(formula1) ) { | |||
throw new IllegalArgumentException("Formula is not specified. Formula is required for all validation types except explicit list validation."); | |||
} | |||
if( validationType!= ValidationType.FORMULA ) { | |||
if (operator==-1) { | |||
throw new IllegalArgumentException("This validation type requires an operator to be specified."); | |||
} else if (( operator==OperatorType.BETWEEN || operator==OperatorType.NOT_BETWEEN) && isFormulaEmpty(formula2)) { | |||
throw new IllegalArgumentException("Between and not between comparisons require two formulae to be specified."); | |||
} | |||
} | |||
} | |||
} | |||
public String prettyPrint() { | |||
StringBuilder builder = new StringBuilder(); | |||
STDataValidationType.Enum vt = XSSFDataValidation.validationTypeMappings.get(validationType); | |||
Enum ot = XSSFDataValidation.operatorTypeMappings.get(operator); | |||
builder.append(vt); | |||
builder.append(' '); | |||
if (validationType!=ValidationType.ANY) { | |||
if (validationType != ValidationType.LIST | |||
&& validationType != ValidationType.FORMULA) { | |||
builder.append(LIST_SEPARATOR).append(ot).append(", "); | |||
} | |||
final String NOQUOTE = ""; | |||
if (validationType == ValidationType.LIST && explicitListOfValues != null) { | |||
builder.append(NOQUOTE).append(Arrays.asList(explicitListOfValues)).append(NOQUOTE).append(' '); | |||
} else { | |||
builder.append(NOQUOTE).append(formula1).append(NOQUOTE).append(' '); | |||
} | |||
if (formula2 != null) { | |||
builder.append(NOQUOTE).append(formula2).append(NOQUOTE).append(' '); | |||
} | |||
} | |||
return builder.toString(); | |||
} | |||
} |
@@ -31,143 +31,143 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationOpera | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType; | |||
public class XSSFDataValidationHelper implements DataValidationHelper { | |||
// Findbugs: URF_UNREAD_FIELD. Do not delete without understanding how this class works. | |||
//private XSSFSheet xssfSheet; | |||
// Findbugs: URF_UNREAD_FIELD. Do not delete without understanding how this class works. | |||
//private XSSFSheet xssfSheet; | |||
public XSSFDataValidationHelper(XSSFSheet xssfSheet) { | |||
super(); | |||
// Findbugs: URF_UNREAD_FIELD. Do not delete without understanding how this class works. | |||
//this.xssfSheet = xssfSheet; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createDateConstraint(int, java.lang.String, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createDateConstraint(int operatorType, String formula1, String formula2, String dateFormat) { | |||
return new XSSFDataValidationConstraint(ValidationType.DATE, operatorType,formula1, formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createDecimalConstraint(int, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createDecimalConstraint(int operatorType, String formula1, String formula2) { | |||
return new XSSFDataValidationConstraint(ValidationType.DECIMAL, operatorType,formula1, formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createExplicitListConstraint(java.lang.String[]) | |||
*/ | |||
public DataValidationConstraint createExplicitListConstraint(String[] listOfValues) { | |||
return new XSSFDataValidationConstraint(listOfValues); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createFormulaListConstraint(java.lang.String) | |||
*/ | |||
public DataValidationConstraint createFormulaListConstraint(String listFormula) { | |||
return new XSSFDataValidationConstraint(ValidationType.LIST, listFormula); | |||
} | |||
public DataValidationConstraint createNumericConstraint(int validationType, int operatorType, String formula1, String formula2) { | |||
if( validationType==ValidationType.INTEGER) { | |||
return createIntegerConstraint(operatorType, formula1, formula2); | |||
} else if ( validationType==ValidationType.DECIMAL) { | |||
return createDecimalConstraint(operatorType, formula1, formula2); | |||
} else if ( validationType==ValidationType.TEXT_LENGTH) { | |||
return createTextLengthConstraint(operatorType, formula1, formula2); | |||
} | |||
return null; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createIntegerConstraint(int, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createIntegerConstraint(int operatorType, String formula1, String formula2) { | |||
return new XSSFDataValidationConstraint(ValidationType.INTEGER, operatorType,formula1,formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createTextLengthConstraint(int, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createTextLengthConstraint(int operatorType, String formula1, String formula2) { | |||
return new XSSFDataValidationConstraint(ValidationType.TEXT_LENGTH, operatorType,formula1,formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createTimeConstraint(int, java.lang.String, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createTimeConstraint(int operatorType, String formula1, String formula2) { | |||
return new XSSFDataValidationConstraint(ValidationType.TIME, operatorType,formula1,formula2); | |||
} | |||
public DataValidationConstraint createCustomConstraint(String formula) { | |||
return new XSSFDataValidationConstraint(ValidationType.FORMULA, formula); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createValidation(org.apache.poi.ss.usermodel.DataValidationConstraint, org.apache.poi.ss.util.CellRangeAddressList) | |||
*/ | |||
public DataValidation createValidation(DataValidationConstraint constraint, CellRangeAddressList cellRangeAddressList) { | |||
XSSFDataValidationConstraint dataValidationConstraint = (XSSFDataValidationConstraint)constraint; | |||
CTDataValidation newDataValidation = CTDataValidation.Factory.newInstance(); | |||
int validationType = constraint.getValidationType(); | |||
switch(validationType) { | |||
case DataValidationConstraint.ValidationType.LIST: | |||
newDataValidation.setType(STDataValidationType.LIST); | |||
newDataValidation.setFormula1(constraint.getFormula1()); | |||
break; | |||
case DataValidationConstraint.ValidationType.ANY: | |||
newDataValidation.setType(STDataValidationType.NONE); | |||
break; | |||
case DataValidationConstraint.ValidationType.TEXT_LENGTH: | |||
newDataValidation.setType(STDataValidationType.TEXT_LENGTH); | |||
break; | |||
case DataValidationConstraint.ValidationType.DATE: | |||
newDataValidation.setType(STDataValidationType.DATE); | |||
break; | |||
case DataValidationConstraint.ValidationType.INTEGER: | |||
newDataValidation.setType(STDataValidationType.WHOLE); | |||
break; | |||
case DataValidationConstraint.ValidationType.DECIMAL: | |||
newDataValidation.setType(STDataValidationType.DECIMAL); | |||
break; | |||
case DataValidationConstraint.ValidationType.TIME: | |||
newDataValidation.setType(STDataValidationType.TIME); | |||
break; | |||
case DataValidationConstraint.ValidationType.FORMULA: | |||
newDataValidation.setType(STDataValidationType.CUSTOM); | |||
break; | |||
default: | |||
newDataValidation.setType(STDataValidationType.NONE); | |||
} | |||
if (validationType!=ValidationType.ANY && validationType!=ValidationType.LIST) { | |||
super(); | |||
// Findbugs: URF_UNREAD_FIELD. Do not delete without understanding how this class works. | |||
//this.xssfSheet = xssfSheet; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createDateConstraint(int, java.lang.String, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createDateConstraint(int operatorType, String formula1, String formula2, String dateFormat) { | |||
return new XSSFDataValidationConstraint(ValidationType.DATE, operatorType,formula1, formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createDecimalConstraint(int, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createDecimalConstraint(int operatorType, String formula1, String formula2) { | |||
return new XSSFDataValidationConstraint(ValidationType.DECIMAL, operatorType,formula1, formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createExplicitListConstraint(java.lang.String[]) | |||
*/ | |||
public DataValidationConstraint createExplicitListConstraint(String[] listOfValues) { | |||
return new XSSFDataValidationConstraint(listOfValues); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createFormulaListConstraint(java.lang.String) | |||
*/ | |||
public DataValidationConstraint createFormulaListConstraint(String listFormula) { | |||
return new XSSFDataValidationConstraint(ValidationType.LIST, listFormula); | |||
} | |||
public DataValidationConstraint createNumericConstraint(int validationType, int operatorType, String formula1, String formula2) { | |||
if( validationType==ValidationType.INTEGER) { | |||
return createIntegerConstraint(operatorType, formula1, formula2); | |||
} else if ( validationType==ValidationType.DECIMAL) { | |||
return createDecimalConstraint(operatorType, formula1, formula2); | |||
} else if ( validationType==ValidationType.TEXT_LENGTH) { | |||
return createTextLengthConstraint(operatorType, formula1, formula2); | |||
} | |||
return null; | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createIntegerConstraint(int, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createIntegerConstraint(int operatorType, String formula1, String formula2) { | |||
return new XSSFDataValidationConstraint(ValidationType.INTEGER, operatorType,formula1,formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createTextLengthConstraint(int, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createTextLengthConstraint(int operatorType, String formula1, String formula2) { | |||
return new XSSFDataValidationConstraint(ValidationType.TEXT_LENGTH, operatorType,formula1,formula2); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createTimeConstraint(int, java.lang.String, java.lang.String, java.lang.String) | |||
*/ | |||
public DataValidationConstraint createTimeConstraint(int operatorType, String formula1, String formula2) { | |||
return new XSSFDataValidationConstraint(ValidationType.TIME, operatorType,formula1,formula2); | |||
} | |||
public DataValidationConstraint createCustomConstraint(String formula) { | |||
return new XSSFDataValidationConstraint(ValidationType.FORMULA, formula); | |||
} | |||
/* (non-Javadoc) | |||
* @see org.apache.poi.ss.usermodel.DataValidationHelper#createValidation(org.apache.poi.ss.usermodel.DataValidationConstraint, org.apache.poi.ss.util.CellRangeAddressList) | |||
*/ | |||
public DataValidation createValidation(DataValidationConstraint constraint, CellRangeAddressList cellRangeAddressList) { | |||
XSSFDataValidationConstraint dataValidationConstraint = (XSSFDataValidationConstraint)constraint; | |||
CTDataValidation newDataValidation = CTDataValidation.Factory.newInstance(); | |||
int validationType = constraint.getValidationType(); | |||
switch(validationType) { | |||
case DataValidationConstraint.ValidationType.LIST: | |||
newDataValidation.setType(STDataValidationType.LIST); | |||
newDataValidation.setFormula1(constraint.getFormula1()); | |||
break; | |||
case DataValidationConstraint.ValidationType.ANY: | |||
newDataValidation.setType(STDataValidationType.NONE); | |||
break; | |||
case DataValidationConstraint.ValidationType.TEXT_LENGTH: | |||
newDataValidation.setType(STDataValidationType.TEXT_LENGTH); | |||
break; | |||
case DataValidationConstraint.ValidationType.DATE: | |||
newDataValidation.setType(STDataValidationType.DATE); | |||
break; | |||
case DataValidationConstraint.ValidationType.INTEGER: | |||
newDataValidation.setType(STDataValidationType.WHOLE); | |||
break; | |||
case DataValidationConstraint.ValidationType.DECIMAL: | |||
newDataValidation.setType(STDataValidationType.DECIMAL); | |||
break; | |||
case DataValidationConstraint.ValidationType.TIME: | |||
newDataValidation.setType(STDataValidationType.TIME); | |||
break; | |||
case DataValidationConstraint.ValidationType.FORMULA: | |||
newDataValidation.setType(STDataValidationType.CUSTOM); | |||
break; | |||
default: | |||
newDataValidation.setType(STDataValidationType.NONE); | |||
} | |||
if (validationType!=ValidationType.ANY && validationType!=ValidationType.LIST) { | |||
STDataValidationOperator.Enum op = XSSFDataValidation.operatorTypeMappings.get(constraint.getOperator()); | |||
if(op != null) { | |||
if(op != null) { | |||
newDataValidation.setOperator(op); | |||
} | |||
if (constraint.getFormula1() != null) { | |||
newDataValidation.setFormula1(constraint.getFormula1()); | |||
} | |||
if (constraint.getFormula2() != null) { | |||
newDataValidation.setFormula2(constraint.getFormula2()); | |||
} | |||
} | |||
CellRangeAddress[] cellRangeAddresses = cellRangeAddressList.getCellRangeAddresses(); | |||
List<String> sqref = new ArrayList<>(); | |||
for (int i = 0; i < cellRangeAddresses.length; i++) { | |||
CellRangeAddress cellRangeAddress = cellRangeAddresses[i]; | |||
sqref.add(cellRangeAddress.formatAsString()); | |||
} | |||
newDataValidation.setSqref(sqref); | |||
newDataValidation.setAllowBlank(true); | |||
newDataValidation.setErrorStyle(STDataValidationErrorStyle.STOP); | |||
return new XSSFDataValidation(dataValidationConstraint,cellRangeAddressList,newDataValidation); | |||
} | |||
if (constraint.getFormula1() != null) { | |||
newDataValidation.setFormula1(constraint.getFormula1()); | |||
} | |||
if (constraint.getFormula2() != null) { | |||
newDataValidation.setFormula2(constraint.getFormula2()); | |||
} | |||
} | |||
CellRangeAddress[] cellRangeAddresses = cellRangeAddressList.getCellRangeAddresses(); | |||
List<String> sqref = new ArrayList<>(); | |||
for (int i = 0; i < cellRangeAddresses.length; i++) { | |||
CellRangeAddress cellRangeAddress = cellRangeAddresses[i]; | |||
sqref.add(cellRangeAddress.formatAsString()); | |||
} | |||
newDataValidation.setSqref(sqref); | |||
newDataValidation.setAllowBlank(true); | |||
newDataValidation.setErrorStyle(STDataValidationErrorStyle.STOP); | |||
return new XSSFDataValidation(dataValidationConstraint,cellRangeAddressList,newDataValidation); | |||
} | |||
} |
@@ -27,79 +27,79 @@ import org.apache.poi.ss.util.CellRangeAddress; | |||
*/ | |||
final class XSSFEvaluationCell implements EvaluationCell { | |||
private final EvaluationSheet _evalSheet; | |||
private final XSSFCell _cell; | |||
private final EvaluationSheet _evalSheet; | |||
private final XSSFCell _cell; | |||
public XSSFEvaluationCell(XSSFCell cell, XSSFEvaluationSheet evaluationSheet) { | |||
_cell = cell; | |||
_evalSheet = evaluationSheet; | |||
} | |||
public XSSFEvaluationCell(XSSFCell cell, XSSFEvaluationSheet evaluationSheet) { | |||
_cell = cell; | |||
_evalSheet = evaluationSheet; | |||
} | |||
public XSSFEvaluationCell(XSSFCell cell) { | |||
this(cell, new XSSFEvaluationSheet(cell.getSheet())); | |||
} | |||
public XSSFEvaluationCell(XSSFCell cell) { | |||
this(cell, new XSSFEvaluationSheet(cell.getSheet())); | |||
} | |||
@Override | |||
public Object getIdentityKey() { | |||
// save memory by just using the cell itself as the identity key | |||
// Note - this assumes XSSFCell has not overridden hashCode and equals | |||
return _cell; | |||
} | |||
@Override | |||
public Object getIdentityKey() { | |||
// save memory by just using the cell itself as the identity key | |||
// Note - this assumes XSSFCell has not overridden hashCode and equals | |||
return _cell; | |||
} | |||
public XSSFCell getXSSFCell() { | |||
return _cell; | |||
} | |||
@Override | |||
public boolean getBooleanCellValue() { | |||
return _cell.getBooleanCellValue(); | |||
} | |||
/** | |||
* @return cell type | |||
*/ | |||
@Override | |||
public CellType getCellType() { | |||
return _cell.getCellType(); | |||
} | |||
@Override | |||
public int getColumnIndex() { | |||
return _cell.getColumnIndex(); | |||
} | |||
@Override | |||
public int getErrorCellValue() { | |||
return _cell.getErrorCellValue(); | |||
} | |||
@Override | |||
public double getNumericCellValue() { | |||
return _cell.getNumericCellValue(); | |||
} | |||
@Override | |||
public int getRowIndex() { | |||
return _cell.getRowIndex(); | |||
} | |||
@Override | |||
public EvaluationSheet getSheet() { | |||
return _evalSheet; | |||
} | |||
@Override | |||
public String getStringCellValue() { | |||
return _cell.getRichStringCellValue().getString(); | |||
} | |||
@Override | |||
public CellRangeAddress getArrayFormulaRange() { | |||
return _cell.getArrayFormulaRange(); | |||
} | |||
@Override | |||
public boolean isPartOfArrayFormulaGroup() { | |||
return _cell.isPartOfArrayFormulaGroup(); | |||
} | |||
/** | |||
* @return cell type of cached formula result | |||
*/ | |||
@Override | |||
public CellType getCachedFormulaResultType() { | |||
return _cell.getCachedFormulaResultType(); | |||
} | |||
public XSSFCell getXSSFCell() { | |||
return _cell; | |||
} | |||
@Override | |||
public boolean getBooleanCellValue() { | |||
return _cell.getBooleanCellValue(); | |||
} | |||
/** | |||
* @return cell type | |||
*/ | |||
@Override | |||
public CellType getCellType() { | |||
return _cell.getCellType(); | |||
} | |||
@Override | |||
public int getColumnIndex() { | |||
return _cell.getColumnIndex(); | |||
} | |||
@Override | |||
public int getErrorCellValue() { | |||
return _cell.getErrorCellValue(); | |||
} | |||
@Override | |||
public double getNumericCellValue() { | |||
return _cell.getNumericCellValue(); | |||
} | |||
@Override | |||
public int getRowIndex() { | |||
return _cell.getRowIndex(); | |||
} | |||
@Override | |||
public EvaluationSheet getSheet() { | |||
return _evalSheet; | |||
} | |||
@Override | |||
public String getStringCellValue() { | |||
return _cell.getRichStringCellValue().getString(); | |||
} | |||
@Override | |||
public CellRangeAddress getArrayFormulaRange() { | |||
return _cell.getArrayFormulaRange(); | |||
} | |||
@Override | |||
public boolean isPartOfArrayFormulaGroup() { | |||
return _cell.isPartOfArrayFormulaGroup(); | |||
} | |||
/** | |||
* @return cell type of cached formula result | |||
*/ | |||
@Override | |||
public CellType getCachedFormulaResultType() { | |||
return _cell.getCachedFormulaResultType(); | |||
} | |||
} |
@@ -67,14 +67,14 @@ public class XSSFEvenFooter extends XSSFHeaderFooter implements Footer{ | |||
*/ | |||
@Override | |||
public void setText(String text) { | |||
if(text == null) { | |||
getHeaderFooter().unsetEvenFooter(); | |||
if (!getHeaderFooter().isSetEvenHeader()) { | |||
getHeaderFooter().unsetDifferentOddEven(); | |||
} | |||
} else { | |||
getHeaderFooter().setEvenFooter(text); | |||
} | |||
if(text == null) { | |||
getHeaderFooter().unsetEvenFooter(); | |||
if (!getHeaderFooter().isSetEvenHeader()) { | |||
getHeaderFooter().unsetDifferentOddEven(); | |||
} | |||
} else { | |||
getHeaderFooter().setEvenFooter(text); | |||
} | |||
} | |||
} |
@@ -65,13 +65,13 @@ public class XSSFFirstFooter extends XSSFHeaderFooter implements Footer{ | |||
*/ | |||
@Override | |||
public void setText(String text) { | |||
if(text == null) { | |||
getHeaderFooter().unsetFirstFooter(); | |||
if (!getHeaderFooter().isSetFirstHeader()) { | |||
getHeaderFooter().unsetDifferentFirst(); | |||
} | |||
} else { | |||
getHeaderFooter().setFirstFooter(text); | |||
} | |||
if(text == null) { | |||
getHeaderFooter().unsetFirstFooter(); | |||
if (!getHeaderFooter().isSetFirstHeader()) { | |||
getHeaderFooter().unsetDifferentFirst(); | |||
} | |||
} else { | |||
getHeaderFooter().setFirstFooter(text); | |||
} | |||
} | |||
} |
@@ -63,14 +63,14 @@ public class XSSFFirstHeader extends XSSFHeaderFooter implements Header{ | |||
*/ | |||
@Override | |||
public void setText(String text) { | |||
if(text == null) { | |||
getHeaderFooter().unsetFirstHeader(); | |||
if (!getHeaderFooter().isSetFirstFooter()) { | |||
getHeaderFooter().unsetDifferentFirst(); | |||
} | |||
} else { | |||
getHeaderFooter().setFirstHeader(text); | |||
} | |||
if(text == null) { | |||
getHeaderFooter().unsetFirstHeader(); | |||
if (!getHeaderFooter().isSetFirstFooter()) { | |||
getHeaderFooter().unsetDifferentFirst(); | |||
} | |||
} else { | |||
getHeaderFooter().setFirstHeader(text); | |||
} | |||
} | |||
} |
@@ -41,21 +41,21 @@ import org.w3c.dom.NodeList; | |||
*/ | |||
public final class XSSFGraphicFrame extends XSSFShape { | |||
private static CTGraphicalObjectFrame prototype; | |||
private final CTGraphicalObjectFrame graphicFrame; | |||
/** | |||
* Construct a new XSSFGraphicFrame object. | |||
* | |||
* @param drawing the XSSFDrawing that owns this frame | |||
* @param ctGraphicFrame the XML bean that stores this frame content | |||
*/ | |||
protected XSSFGraphicFrame(XSSFDrawing drawing, CTGraphicalObjectFrame ctGraphicFrame) { | |||
this.drawing = drawing; // protected field on XSSFShape | |||
this.graphicFrame = ctGraphicFrame; | |||
// TODO: there may be a better way to delegate this | |||
CTGraphicalObjectData graphicData = graphicFrame.getGraphic().getGraphicData(); | |||
private static CTGraphicalObjectFrame prototype; | |||
private final CTGraphicalObjectFrame graphicFrame; | |||
/** | |||
* Construct a new XSSFGraphicFrame object. | |||
* | |||
* @param drawing the XSSFDrawing that owns this frame | |||
* @param ctGraphicFrame the XML bean that stores this frame content | |||
*/ | |||
protected XSSFGraphicFrame(XSSFDrawing drawing, CTGraphicalObjectFrame ctGraphicFrame) { | |||
this.drawing = drawing; // protected field on XSSFShape | |||
this.graphicFrame = ctGraphicFrame; | |||
// TODO: there may be a better way to delegate this | |||
CTGraphicalObjectData graphicData = graphicFrame.getGraphic().getGraphicData(); | |||
if (graphicData != null) { | |||
NodeList nodes = graphicData.getDomNode().getChildNodes(); | |||
for (int i = 0; i < nodes.getLength(); i++) { | |||
@@ -71,134 +71,134 @@ public final class XSSFGraphicFrame extends XSSFShape { | |||
} | |||
} | |||
} | |||
} | |||
@Internal | |||
public CTGraphicalObjectFrame getCTGraphicalObjectFrame() { | |||
return graphicFrame; | |||
} | |||
/** | |||
* Initialize default structure of a new graphic frame | |||
*/ | |||
protected static CTGraphicalObjectFrame prototype() { | |||
if (prototype == null) { | |||
CTGraphicalObjectFrame graphicFrame = CTGraphicalObjectFrame.Factory.newInstance(); | |||
CTGraphicalObjectFrameNonVisual nvGraphic = graphicFrame.addNewNvGraphicFramePr(); | |||
CTNonVisualDrawingProps props = nvGraphic.addNewCNvPr(); | |||
props.setId(0); | |||
props.setName("Diagramm 1"); | |||
nvGraphic.addNewCNvGraphicFramePr(); | |||
CTTransform2D transform = graphicFrame.addNewXfrm(); | |||
CTPositiveSize2D extPoint = transform.addNewExt(); | |||
CTPoint2D offPoint = transform.addNewOff(); | |||
extPoint.setCx(0); | |||
extPoint.setCy(0); | |||
offPoint.setX(0); | |||
offPoint.setY(0); | |||
/* CTGraphicalObject graphic = */ graphicFrame.addNewGraphic(); | |||
prototype = graphicFrame; | |||
} | |||
return prototype; | |||
} | |||
/** | |||
* Sets the frame macro. | |||
*/ | |||
public void setMacro(String macro) { | |||
graphicFrame.setMacro(macro); | |||
} | |||
/** | |||
* Sets the frame name. | |||
*/ | |||
public void setName(String name) { | |||
getNonVisualProperties().setName(name); | |||
} | |||
/** | |||
* Returns the frame name. | |||
* @return name of the frame | |||
*/ | |||
public String getName() { | |||
return getNonVisualProperties().getName(); | |||
} | |||
private CTNonVisualDrawingProps getNonVisualProperties() { | |||
CTGraphicalObjectFrameNonVisual nvGraphic = graphicFrame.getNvGraphicFramePr(); | |||
return nvGraphic.getCNvPr(); | |||
} | |||
/** | |||
* Attaches frame to an anchor. | |||
*/ | |||
protected void setAnchor(XSSFClientAnchor anchor) { | |||
this.anchor = anchor; | |||
} | |||
/** | |||
* Returns the frame anchor. | |||
* @return the XSSFClientAnchor anchor this frame is attached to | |||
*/ | |||
@Override | |||
} | |||
@Internal | |||
public CTGraphicalObjectFrame getCTGraphicalObjectFrame() { | |||
return graphicFrame; | |||
} | |||
/** | |||
* Initialize default structure of a new graphic frame | |||
*/ | |||
protected static CTGraphicalObjectFrame prototype() { | |||
if (prototype == null) { | |||
CTGraphicalObjectFrame graphicFrame = CTGraphicalObjectFrame.Factory.newInstance(); | |||
CTGraphicalObjectFrameNonVisual nvGraphic = graphicFrame.addNewNvGraphicFramePr(); | |||
CTNonVisualDrawingProps props = nvGraphic.addNewCNvPr(); | |||
props.setId(0); | |||
props.setName("Diagramm 1"); | |||
nvGraphic.addNewCNvGraphicFramePr(); | |||
CTTransform2D transform = graphicFrame.addNewXfrm(); | |||
CTPositiveSize2D extPoint = transform.addNewExt(); | |||
CTPoint2D offPoint = transform.addNewOff(); | |||
extPoint.setCx(0); | |||
extPoint.setCy(0); | |||
offPoint.setX(0); | |||
offPoint.setY(0); | |||
/* CTGraphicalObject graphic = */ graphicFrame.addNewGraphic(); | |||
prototype = graphicFrame; | |||
} | |||
return prototype; | |||
} | |||
/** | |||
* Sets the frame macro. | |||
*/ | |||
public void setMacro(String macro) { | |||
graphicFrame.setMacro(macro); | |||
} | |||
/** | |||
* Sets the frame name. | |||
*/ | |||
public void setName(String name) { | |||
getNonVisualProperties().setName(name); | |||
} | |||
/** | |||
* Returns the frame name. | |||
* @return name of the frame | |||
*/ | |||
public String getName() { | |||
return getNonVisualProperties().getName(); | |||
} | |||
private CTNonVisualDrawingProps getNonVisualProperties() { | |||
CTGraphicalObjectFrameNonVisual nvGraphic = graphicFrame.getNvGraphicFramePr(); | |||
return nvGraphic.getCNvPr(); | |||
} | |||
/** | |||
* Attaches frame to an anchor. | |||
*/ | |||
protected void setAnchor(XSSFClientAnchor anchor) { | |||
this.anchor = anchor; | |||
} | |||
/** | |||
* Returns the frame anchor. | |||
* @return the XSSFClientAnchor anchor this frame is attached to | |||
*/ | |||
@Override | |||
public XSSFClientAnchor getAnchor() { | |||
return (XSSFClientAnchor) anchor; | |||
} | |||
/** | |||
* Assign a DrawingML chart to the graphic frame. | |||
*/ | |||
protected void setChart(XSSFChart chart, String relId) { | |||
CTGraphicalObjectData data = graphicFrame.getGraphic().addNewGraphicData(); | |||
appendChartElement(data, relId); | |||
chart.setGraphicFrame(this); | |||
} | |||
/** | |||
* Gets the frame id. | |||
*/ | |||
public long getId() { | |||
return graphicFrame.getNvGraphicFramePr().getCNvPr().getId(); | |||
} | |||
/** | |||
* Sets the frame id. | |||
*/ | |||
protected void setId(long id) { | |||
graphicFrame.getNvGraphicFramePr().getCNvPr().setId(id); | |||
} | |||
/** | |||
* The low level code to insert {@code <c:chart>} tag into | |||
* {@code <a:graphicData>}. | |||
* | |||
* Here is the schema (ECMA-376): | |||
* <pre> | |||
* {@code | |||
* <complexType name="CT_GraphicalObjectData"> | |||
* <sequence> | |||
* <any minOccurs="0" maxOccurs="unbounded" processContents="strict"/> | |||
* </sequence> | |||
* <attribute name="uri" type="xsd:token"/> | |||
* </complexType> | |||
* } | |||
* </pre> | |||
*/ | |||
private void appendChartElement(CTGraphicalObjectData data, String id) { | |||
String r_namespaceUri = STRelationshipId.type.getName().getNamespaceURI(); | |||
String c_namespaceUri = XSSFDrawing.NAMESPACE_C; | |||
XmlCursor cursor = data.newCursor(); | |||
cursor.toNextToken(); | |||
cursor.beginElement(new QName(c_namespaceUri, "chart", "c")); | |||
cursor.insertAttributeWithValue(new QName(r_namespaceUri, "id", "r"), id); | |||
cursor.dispose(); | |||
data.setUri(c_namespaceUri); | |||
} | |||
return (XSSFClientAnchor) anchor; | |||
} | |||
/** | |||
* Assign a DrawingML chart to the graphic frame. | |||
*/ | |||
protected void setChart(XSSFChart chart, String relId) { | |||
CTGraphicalObjectData data = graphicFrame.getGraphic().addNewGraphicData(); | |||
appendChartElement(data, relId); | |||
chart.setGraphicFrame(this); | |||
} | |||
/** | |||
* Gets the frame id. | |||
*/ | |||
public long getId() { | |||
return graphicFrame.getNvGraphicFramePr().getCNvPr().getId(); | |||
} | |||
/** | |||
* Sets the frame id. | |||
*/ | |||
protected void setId(long id) { | |||
graphicFrame.getNvGraphicFramePr().getCNvPr().setId(id); | |||
} | |||
/** | |||
* The low level code to insert {@code <c:chart>} tag into | |||
* {@code <a:graphicData>}. | |||
* | |||
* Here is the schema (ECMA-376): | |||
* <pre> | |||
* {@code | |||
* <complexType name="CT_GraphicalObjectData"> | |||
* <sequence> | |||
* <any minOccurs="0" maxOccurs="unbounded" processContents="strict"/> | |||
* </sequence> | |||
* <attribute name="uri" type="xsd:token"/> | |||
* </complexType> | |||
* } | |||
* </pre> | |||
*/ | |||
private void appendChartElement(CTGraphicalObjectData data, String id) { | |||
String r_namespaceUri = STRelationshipId.type.getName().getNamespaceURI(); | |||
String c_namespaceUri = XSSFDrawing.NAMESPACE_C; | |||
XmlCursor cursor = data.newCursor(); | |||
cursor.toNextToken(); | |||
cursor.beginElement(new QName(c_namespaceUri, "chart", "c")); | |||
cursor.insertAttributeWithValue(new QName(r_namespaceUri, "id", "r"), id); | |||
cursor.dispose(); | |||
data.setUri(c_namespaceUri); | |||
} | |||
@Override | |||
protected CTShapeProperties getShapeProperties(){ |
@@ -29,85 +29,85 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; | |||
* </p> | |||
*/ | |||
public class XSSFHeaderFooterProperties { | |||
private final CTHeaderFooter headerFooter; | |||
private final CTHeaderFooter headerFooter; | |||
/** | |||
* Create an instance of XSSFHeaderFooterProperties from the supplied XML bean | |||
*/ | |||
public XSSFHeaderFooterProperties(CTHeaderFooter headerFooter) { | |||
/** | |||
* Create an instance of XSSFHeaderFooterProperties from the supplied XML bean | |||
*/ | |||
public XSSFHeaderFooterProperties(CTHeaderFooter headerFooter) { | |||
this.headerFooter = headerFooter; | |||
} | |||
} | |||
/** | |||
* Returns the underlying CTHeaderFooter xml bean | |||
* | |||
* @return the underlying CTHeaderFooter xml bean | |||
*/ | |||
/** | |||
* Returns the underlying CTHeaderFooter xml bean | |||
* | |||
* @return the underlying CTHeaderFooter xml bean | |||
*/ | |||
@Internal | |||
public CTHeaderFooter getHeaderFooter() { | |||
return this.headerFooter; | |||
} | |||
public CTHeaderFooter getHeaderFooter() { | |||
return this.headerFooter; | |||
} | |||
/** | |||
* returns alignWithMargins attribute | |||
*/ | |||
public boolean getAlignWithMargins() { | |||
return getHeaderFooter().isSetAlignWithMargins() && getHeaderFooter().getAlignWithMargins(); | |||
} | |||
/** | |||
* returns differentFirst attribute | |||
*/ | |||
public boolean getDifferentFirst() { | |||
return getHeaderFooter().isSetDifferentFirst() && getHeaderFooter().getDifferentFirst(); | |||
} | |||
/** | |||
* returns differentOddEven attribute | |||
*/ | |||
public boolean getDifferentOddEven() { | |||
return getHeaderFooter().isSetDifferentOddEven() && getHeaderFooter().getDifferentOddEven(); | |||
} | |||
/** | |||
* returns alignWithMargins attribute | |||
*/ | |||
public boolean getAlignWithMargins() { | |||
return getHeaderFooter().isSetAlignWithMargins() && getHeaderFooter().getAlignWithMargins(); | |||
} | |||
/** | |||
* returns differentFirst attribute | |||
*/ | |||
public boolean getDifferentFirst() { | |||
return getHeaderFooter().isSetDifferentFirst() && getHeaderFooter().getDifferentFirst(); | |||
} | |||
/** | |||
* returns differentOddEven attribute | |||
*/ | |||
public boolean getDifferentOddEven() { | |||
return getHeaderFooter().isSetDifferentOddEven() && getHeaderFooter().getDifferentOddEven(); | |||
} | |||
/** | |||
* returns scaleWithDoc attribute | |||
*/ | |||
public boolean getScaleWithDoc() { | |||
return getHeaderFooter().isSetScaleWithDoc() && getHeaderFooter().getScaleWithDoc(); | |||
} | |||
/** | |||
* set alignWithMargins attribute | |||
*/ | |||
public void setAlignWithMargins(boolean flag) { | |||
getHeaderFooter().setAlignWithMargins(flag); | |||
} | |||
* returns scaleWithDoc attribute | |||
*/ | |||
public boolean getScaleWithDoc() { | |||
return getHeaderFooter().isSetScaleWithDoc() && getHeaderFooter().getScaleWithDoc(); | |||
} | |||
/** | |||
* set alignWithMargins attribute | |||
*/ | |||
public void setAlignWithMargins(boolean flag) { | |||
getHeaderFooter().setAlignWithMargins(flag); | |||
} | |||
/** | |||
* set differentFirst attribute | |||
*/ | |||
public void setDifferentFirst(boolean flag) { | |||
public void setDifferentFirst(boolean flag) { | |||
getHeaderFooter().setDifferentFirst(flag); | |||
} | |||
/** | |||
* set differentOddEven attribute | |||
*/ | |||
public void setDifferentOddEven(boolean flag) { | |||
public void setDifferentOddEven(boolean flag) { | |||
getHeaderFooter().setDifferentOddEven(flag); | |||
} | |||
/** | |||
* set scaleWithDoc attribute | |||
*/ | |||
public void setScaleWithDoc(boolean flag) { | |||
public void setScaleWithDoc(boolean flag) { | |||
getHeaderFooter().setScaleWithDoc(flag); | |||
} | |||
/** | |||
* remove alignWithMargins attribute | |||
*/ | |||
public void removeAlignWithMargins() { | |||
public void removeAlignWithMargins() { | |||
if (getHeaderFooter().isSetAlignWithMargins()) { | |||
getHeaderFooter().unsetAlignWithMargins(); | |||
} | |||
@@ -116,7 +116,7 @@ public class XSSFHeaderFooterProperties { | |||
/** | |||
* remove differentFirst attribute | |||
*/ | |||
public void removeDifferentFirst() { | |||
public void removeDifferentFirst() { | |||
if (getHeaderFooter().isSetDifferentFirst()) { | |||
getHeaderFooter().unsetDifferentFirst(); | |||
} | |||
@@ -125,7 +125,7 @@ public class XSSFHeaderFooterProperties { | |||
/** | |||
* remove differentOddEven attribute | |||
*/ | |||
public void removeDifferentOddEven() { | |||
public void removeDifferentOddEven() { | |||
if (getHeaderFooter().isSetDifferentOddEven()) { | |||
getHeaderFooter().unsetDifferentOddEven(); | |||
} | |||
@@ -134,7 +134,7 @@ public class XSSFHeaderFooterProperties { | |||
/** | |||
* remove scaleWithDoc attribute | |||
*/ | |||
public void removeScaleWithDoc() { | |||
public void removeScaleWithDoc() { | |||
if (getHeaderFooter().isSetScaleWithDoc()) { | |||
getHeaderFooter().unsetScaleWithDoc(); | |||
} |
@@ -360,7 +360,7 @@ public class XSSFHyperlink implements Hyperlink { | |||
@Override | |||
public void setLastRow(int row) { | |||
setFirstRow(row); | |||
} | |||
} | |||
/** | |||
* @return additional text to help the user understand more about the hyperlink |
@@ -53,10 +53,10 @@ public class XSSFOddFooter extends XSSFHeaderFooter implements Footer{ | |||
*/ | |||
@Override | |||
public void setText(String text) { | |||
if(text == null) { | |||
getHeaderFooter().unsetOddFooter(); | |||
} else { | |||
getHeaderFooter().setOddFooter(text); | |||
} | |||
if(text == null) { | |||
getHeaderFooter().unsetOddFooter(); | |||
} else { | |||
getHeaderFooter().setOddFooter(text); | |||
} | |||
} | |||
} |
@@ -53,10 +53,10 @@ public class XSSFOddHeader extends XSSFHeaderFooter implements Header{ | |||
*/ | |||
@Override | |||
public void setText(String text) { | |||
if(text == null) { | |||
getHeaderFooter().unsetOddHeader(); | |||
} else { | |||
getHeaderFooter().setOddHeader(text); | |||
} | |||
if(text == null) { | |||
getHeaderFooter().unsetOddHeader(); | |||
} else { | |||
getHeaderFooter().setOddHeader(text); | |||
} | |||
} | |||
} |
@@ -60,7 +60,7 @@ public class XSSFPivotCache extends POIXMLDocumentPart { | |||
@Beta | |||
protected void readFrom(InputStream is) throws IOException { | |||
try { | |||
try { | |||
XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); | |||
//Removing root element | |||
options.setLoadReplaceDocumentElement(null); |
@@ -70,7 +70,7 @@ public class XSSFPivotCacheDefinition extends POIXMLDocumentPart{ | |||
@Beta | |||
public void readFrom(InputStream is) throws IOException { | |||
try { | |||
try { | |||
XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); | |||
//Removing root element | |||
options.setLoadReplaceDocumentElement(null); |
@@ -57,7 +57,7 @@ public class XSSFPivotCacheRecords extends POIXMLDocumentPart { | |||
@Beta | |||
protected void readFrom(InputStream is) throws IOException { | |||
try { | |||
try { | |||
XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); | |||
//Removing root element | |||
options.setLoadReplaceDocumentElement(null); |
@@ -100,7 +100,7 @@ public class XSSFPivotTable extends POIXMLDocumentPart { | |||
@Beta | |||
public void readFrom(InputStream is) throws IOException { | |||
try { | |||
try { | |||
XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); | |||
//Removing root element | |||
options.setLoadReplaceDocumentElement(null); |
@@ -56,16 +56,16 @@ public class XSSFSheetConditionalFormatting implements SheetConditionalFormattin | |||
* TODO - formulas containing cell references are currently not parsed properly | |||
* | |||
* @param comparisonOperation - a constant value from | |||
* {@code {@link org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator}}: | |||
* {@code {@link org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator}}: | |||
* <ul> | |||
* <li>BETWEEN</li> | |||
* <li>NOT_BETWEEN</li> | |||
* <li>EQUAL</li> | |||
* <li>NOT_EQUAL</li> | |||
* <li>GT</li> | |||
* <li>LT</li> | |||
* <li>GE</li> | |||
* <li>LE</li> | |||
* <li>BETWEEN</li> | |||
* <li>NOT_BETWEEN</li> | |||
* <li>EQUAL</li> | |||
* <li>NOT_EQUAL</li> | |||
* <li>GT</li> | |||
* <li>LT</li> | |||
* <li>GE</li> | |||
* <li>LE</li> | |||
* </ul> | |||
* | |||
* @param formula1 - formula for the valued, compared with the cell | |||
@@ -266,7 +266,7 @@ public class XSSFSheetConditionalFormatting implements SheetConditionalFormattin | |||
* gets Conditional Formatting object at a particular index | |||
* | |||
* @param index | |||
* of the Conditional Formatting object to fetch | |||
* of the Conditional Formatting object to fetch | |||
* @return Conditional Formatting object | |||
*/ | |||
@Override |
@@ -111,7 +111,7 @@ public class XSSFTextRun { | |||
*/ | |||
public double getFontSize(){ | |||
double scale = 1; | |||
double size = XSSFFont.DEFAULT_FONT_SIZE; // default font size | |||
double size = XSSFFont.DEFAULT_FONT_SIZE; // default font size | |||
CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTxBody().getBodyPr().getNormAutofit(); | |||
if(afit != null) scale = (double)afit.getFontScale() / 100000; | |||
@@ -192,11 +192,11 @@ public class XSSFCellAlignment { | |||
} | |||
public boolean getShrinkToFit() { | |||
return cellAlignement.getShrinkToFit(); | |||
return cellAlignement.getShrinkToFit(); | |||
} | |||
public void setShrinkToFit(boolean shrink) { | |||
cellAlignement.setShrinkToFit(shrink); | |||
cellAlignement.setShrinkToFit(shrink); | |||
} | |||
/** |
@@ -121,124 +121,124 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; | |||
* | |||
*/ | |||
public abstract class XSSFHeaderFooter implements HeaderFooter { | |||
private final HeaderFooterHelper helper; | |||
private final CTHeaderFooter headerFooter; | |||
private final HeaderFooterHelper helper; | |||
private final CTHeaderFooter headerFooter; | |||
private boolean stripFields; | |||
private boolean stripFields; | |||
/** | |||
* Create an instance of XSSFAbstractHeaderFooter from the supplied XML bean | |||
*/ | |||
public XSSFHeaderFooter(CTHeaderFooter headerFooter) { | |||
/** | |||
* Create an instance of XSSFAbstractHeaderFooter from the supplied XML bean | |||
*/ | |||
public XSSFHeaderFooter(CTHeaderFooter headerFooter) { | |||
this.headerFooter = headerFooter; | |||
this.helper = new HeaderFooterHelper(); | |||
} | |||
/** | |||
* Returns the underlying CTHeaderFooter xml bean | |||
* | |||
* @return the underlying CTHeaderFooter xml bean | |||
*/ | |||
this.helper = new HeaderFooterHelper(); | |||
} | |||
/** | |||
* Returns the underlying CTHeaderFooter xml bean | |||
* | |||
* @return the underlying CTHeaderFooter xml bean | |||
*/ | |||
@Internal | |||
public CTHeaderFooter getHeaderFooter() { | |||
return this.headerFooter; | |||
} | |||
public CTHeaderFooter getHeaderFooter() { | |||
return this.headerFooter; | |||
} | |||
/** | |||
* Returns the value of the header or footer. | |||
* | |||
* @return the value of the header or footer. | |||
*/ | |||
public String getValue() { | |||
String value = getText(); | |||
if (value == null) | |||
return ""; | |||
return value; | |||
} | |||
/** | |||
* Are fields currently being stripped from the text that this | |||
* XSSFHeaderFooter returns? Default is false, but can be changed | |||
*/ | |||
public boolean areFieldsStripped() { | |||
return stripFields; | |||
} | |||
/** | |||
* Should fields (eg macros) be stripped from the text that this class | |||
* returns? Default is not to strip. | |||
*/ | |||
public void setAreFieldsStripped(boolean stripFields) { | |||
this.stripFields = stripFields; | |||
} | |||
/** | |||
* Removes any fields (eg macros, page markers etc) from the string. | |||
* Normally used to make some text suitable for showing to humans, and the | |||
* resultant text should not normally be saved back into the document! | |||
*/ | |||
public static String stripFields(String text) { | |||
return org.apache.poi.hssf.usermodel.HeaderFooter.stripFields(text); | |||
} | |||
public abstract String getText(); | |||
protected abstract void setText(String text); | |||
/** | |||
* get the text representing the center part of this element | |||
*/ | |||
@Override | |||
public String getCenter() { | |||
String text = helper.getCenterSection(getText()); | |||
if (stripFields) | |||
return stripFields(text); | |||
return text; | |||
} | |||
/** | |||
* get the text representing the left part of this element | |||
*/ | |||
@Override | |||
public String getLeft() { | |||
String text = helper.getLeftSection(getText()); | |||
if (stripFields) | |||
return stripFields(text); | |||
return text; | |||
} | |||
/** | |||
* get the text representing the right part of this element | |||
*/ | |||
@Override | |||
public String getRight() { | |||
String text = helper.getRightSection(getText()); | |||
if (stripFields) | |||
return stripFields(text); | |||
return text; | |||
} | |||
/** | |||
* set a centered string value for this element | |||
*/ | |||
@Override | |||
public void setCenter(String newCenter) { | |||
setText(helper.setCenterSection(getText(), newCenter)); | |||
} | |||
/** | |||
* set a left string value for this element | |||
*/ | |||
@Override | |||
public void setLeft(String newLeft) { | |||
setText(helper.setLeftSection(getText(), newLeft)); | |||
} | |||
/** | |||
* set a right string value for this element | |||
*/ | |||
@Override | |||
public void setRight(String newRight) { | |||
setText(helper.setRightSection(getText(), newRight)); | |||
} | |||
public String getValue() { | |||
String value = getText(); | |||
if (value == null) | |||
return ""; | |||
return value; | |||
} | |||
/** | |||
* Are fields currently being stripped from the text that this | |||
* XSSFHeaderFooter returns? Default is false, but can be changed | |||
*/ | |||
public boolean areFieldsStripped() { | |||
return stripFields; | |||
} | |||
/** | |||
* Should fields (eg macros) be stripped from the text that this class | |||
* returns? Default is not to strip. | |||
*/ | |||
public void setAreFieldsStripped(boolean stripFields) { | |||
this.stripFields = stripFields; | |||
} | |||
/** | |||
* Removes any fields (eg macros, page markers etc) from the string. | |||
* Normally used to make some text suitable for showing to humans, and the | |||
* resultant text should not normally be saved back into the document! | |||
*/ | |||
public static String stripFields(String text) { | |||
return org.apache.poi.hssf.usermodel.HeaderFooter.stripFields(text); | |||
} | |||
public abstract String getText(); | |||
protected abstract void setText(String text); | |||
/** | |||
* get the text representing the center part of this element | |||
*/ | |||
@Override | |||
public String getCenter() { | |||
String text = helper.getCenterSection(getText()); | |||
if (stripFields) | |||
return stripFields(text); | |||
return text; | |||
} | |||
/** | |||
* get the text representing the left part of this element | |||
*/ | |||
@Override | |||
public String getLeft() { | |||
String text = helper.getLeftSection(getText()); | |||
if (stripFields) | |||
return stripFields(text); | |||
return text; | |||
} | |||
/** | |||
* get the text representing the right part of this element | |||
*/ | |||
@Override | |||
public String getRight() { | |||
String text = helper.getRightSection(getText()); | |||
if (stripFields) | |||
return stripFields(text); | |||
return text; | |||
} | |||
/** | |||
* set a centered string value for this element | |||
*/ | |||
@Override | |||
public void setCenter(String newCenter) { | |||
setText(helper.setCenterSection(getText(), newCenter)); | |||
} | |||
/** | |||
* set a left string value for this element | |||
*/ | |||
@Override | |||
public void setLeft(String newLeft) { | |||
setText(helper.setLeftSection(getText(), newLeft)); | |||
} | |||
/** | |||
* set a right string value for this element | |||
*/ | |||
@Override | |||
public void setRight(String newRight) { | |||
setText(helper.setRightSection(getText(), newRight)); | |||
} | |||
} |
@@ -20,7 +20,7 @@ package org.apache.poi.xssf.usermodel.helpers; | |||
public class HeaderFooterHelper { | |||
// Note - XmlBeans handles entity encoding for us, | |||
// so these should be & forms, not the & ones! | |||
// so these should be & forms, not the & ones! | |||
private static final String HeaderFooterEntity_L = "&L"; | |||
private static final String HeaderFooterEntity_C = "&C"; | |||
private static final String HeaderFooterEntity_R = "&R"; | |||
@@ -32,28 +32,28 @@ public class HeaderFooterHelper { | |||
public static final String HeaderFooterEntity_Time = "&T"; | |||
public String getLeftSection(String string) { | |||
return getParts(string)[0]; | |||
return getParts(string)[0]; | |||
} | |||
public String getCenterSection(String string) { | |||
return getParts(string)[1]; | |||
return getParts(string)[1]; | |||
} | |||
public String getRightSection(String string) { | |||
return getParts(string)[2]; | |||
return getParts(string)[2]; | |||
} | |||
public String setLeftSection(String string, String newLeft) { | |||
String[] parts = getParts(string); | |||
parts[0] = newLeft; | |||
String[] parts = getParts(string); | |||
parts[0] = newLeft; | |||
return joinParts(parts); | |||
} | |||
public String setCenterSection(String string, String newCenter) { | |||
String[] parts = getParts(string); | |||
parts[1] = newCenter; | |||
String[] parts = getParts(string); | |||
parts[1] = newCenter; | |||
return joinParts(parts); | |||
} | |||
public String setRightSection(String string, String newRight) { | |||
String[] parts = getParts(string); | |||
parts[2] = newRight; | |||
String[] parts = getParts(string); | |||
parts[2] = newRight; | |||
return joinParts(parts); | |||
} | |||
@@ -61,59 +61,59 @@ public class HeaderFooterHelper { | |||
* Split into left, center, right | |||
*/ | |||
private String[] getParts(String string) { | |||
String[] parts = new String[] { "", "", "" }; | |||
if(string == null) | |||
return parts; | |||
// They can come in any order, which is just nasty | |||
// Work backwards from the end, picking the last | |||
// on off each time as we go | |||
int lAt = 0; | |||
int cAt = 0; | |||
int rAt = 0; | |||
while( | |||
// Ensure all indicies get updated, then -1 tested | |||
(lAt = string.indexOf(HeaderFooterEntity_L)) > -2 && | |||
(cAt = string.indexOf(HeaderFooterEntity_C)) > -2 && | |||
(rAt = string.indexOf(HeaderFooterEntity_R)) > -2 && | |||
(lAt > -1 || cAt > -1 || rAt > -1) | |||
) { | |||
// Pick off the last one | |||
if(rAt > cAt && rAt > lAt) { | |||
parts[2] = string.substring(rAt + HeaderFooterEntity_R.length()); | |||
string = string.substring(0, rAt); | |||
} else if(cAt > rAt && cAt > lAt) { | |||
parts[1] = string.substring(cAt + HeaderFooterEntity_C.length()); | |||
string = string.substring(0, cAt); | |||
} else { | |||
parts[0] = string.substring(lAt + HeaderFooterEntity_L.length()); | |||
string = string.substring(0, lAt); | |||
} | |||
} | |||
return parts; | |||
String[] parts = new String[] { "", "", "" }; | |||
if(string == null) | |||
return parts; | |||
// They can come in any order, which is just nasty | |||
// Work backwards from the end, picking the last | |||
// on off each time as we go | |||
int lAt = 0; | |||
int cAt = 0; | |||
int rAt = 0; | |||
while( | |||
// Ensure all indicies get updated, then -1 tested | |||
(lAt = string.indexOf(HeaderFooterEntity_L)) > -2 && | |||
(cAt = string.indexOf(HeaderFooterEntity_C)) > -2 && | |||
(rAt = string.indexOf(HeaderFooterEntity_R)) > -2 && | |||
(lAt > -1 || cAt > -1 || rAt > -1) | |||
) { | |||
// Pick off the last one | |||
if(rAt > cAt && rAt > lAt) { | |||
parts[2] = string.substring(rAt + HeaderFooterEntity_R.length()); | |||
string = string.substring(0, rAt); | |||
} else if(cAt > rAt && cAt > lAt) { | |||
parts[1] = string.substring(cAt + HeaderFooterEntity_C.length()); | |||
string = string.substring(0, cAt); | |||
} else { | |||
parts[0] = string.substring(lAt + HeaderFooterEntity_L.length()); | |||
string = string.substring(0, lAt); | |||
} | |||
} | |||
return parts; | |||
} | |||
private String joinParts(String[] parts) { | |||
return joinParts(parts[0], parts[1], parts[2]); | |||
return joinParts(parts[0], parts[1], parts[2]); | |||
} | |||
private String joinParts(String l, String c, String r) { | |||
StringBuilder ret = new StringBuilder(64); | |||
StringBuilder ret = new StringBuilder(64); | |||
// Join as c, l, r | |||
if(c.length() > 0) { | |||
ret.append(HeaderFooterEntity_C); | |||
ret.append(c); | |||
} | |||
if(l.length() > 0) { | |||
ret.append(HeaderFooterEntity_L); | |||
ret.append(l); | |||
} | |||
if(r.length() > 0) { | |||
ret.append(HeaderFooterEntity_R); | |||
ret.append(r); | |||
} | |||
return ret.toString(); | |||
// Join as c, l, r | |||
if(c.length() > 0) { | |||
ret.append(HeaderFooterEntity_C); | |||
ret.append(c); | |||
} | |||
if(l.length() > 0) { | |||
ret.append(HeaderFooterEntity_L); | |||
ret.append(l); | |||
} | |||
if(r.length() > 0) { | |||
ret.append(HeaderFooterEntity_R); | |||
ret.append(r); | |||
} | |||
return ret.toString(); | |||
} | |||
} |
@@ -32,53 +32,53 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlPr; | |||
*/ | |||
public class XSSFSingleXmlCell { | |||
private CTSingleXmlCell singleXmlCell; | |||
private SingleXmlCells parent; | |||
private CTSingleXmlCell singleXmlCell; | |||
private SingleXmlCells parent; | |||
public XSSFSingleXmlCell(CTSingleXmlCell singleXmlCell, SingleXmlCells parent){ | |||
this.singleXmlCell = singleXmlCell; | |||
this.parent = parent; | |||
} | |||
public XSSFSingleXmlCell(CTSingleXmlCell singleXmlCell, SingleXmlCells parent){ | |||
this.singleXmlCell = singleXmlCell; | |||
this.parent = parent; | |||
} | |||
/** | |||
* Gets the XSSFCell referenced by the R attribute or creates a new one if cell doesn't exists | |||
* @return the referenced XSSFCell, null if the cell reference is invalid | |||
*/ | |||
public XSSFCell getReferencedCell(){ | |||
XSSFCell cell = null; | |||
/** | |||
* Gets the XSSFCell referenced by the R attribute or creates a new one if cell doesn't exists | |||
* @return the referenced XSSFCell, null if the cell reference is invalid | |||
*/ | |||
public XSSFCell getReferencedCell(){ | |||
XSSFCell cell = null; | |||
CellReference cellReference = new CellReference(singleXmlCell.getR()); | |||
CellReference cellReference = new CellReference(singleXmlCell.getR()); | |||
XSSFRow row = parent.getXSSFSheet().getRow(cellReference.getRow()); | |||
if(row==null){ | |||
row = parent.getXSSFSheet().createRow(cellReference.getRow()); | |||
} | |||
XSSFRow row = parent.getXSSFSheet().getRow(cellReference.getRow()); | |||
if(row==null){ | |||
row = parent.getXSSFSheet().createRow(cellReference.getRow()); | |||
} | |||
cell = row.getCell(cellReference.getCol()); | |||
if(cell==null){ | |||
cell = row.createCell(cellReference.getCol()); | |||
} | |||
cell = row.getCell(cellReference.getCol()); | |||
if(cell==null){ | |||
cell = row.createCell(cellReference.getCol()); | |||
} | |||
return cell; | |||
} | |||
return cell; | |||
} | |||
public String getXpath(){ | |||
CTXmlCellPr xmlCellPr = singleXmlCell.getXmlCellPr(); | |||
CTXmlPr xmlPr = xmlCellPr.getXmlPr(); | |||
public String getXpath(){ | |||
CTXmlCellPr xmlCellPr = singleXmlCell.getXmlCellPr(); | |||
CTXmlPr xmlPr = xmlCellPr.getXmlPr(); | |||
return xmlPr.getXpath(); | |||
} | |||
} | |||
public long getMapId(){ | |||
return singleXmlCell.getXmlCellPr().getXmlPr().getMapId(); | |||
} | |||
public long getMapId(){ | |||
return singleXmlCell.getXmlCellPr().getXmlPr().getMapId(); | |||
} | |||
public String getXmlDataType() { | |||
CTXmlCellPr xmlCellPr = singleXmlCell.getXmlCellPr(); | |||
CTXmlPr xmlPr = xmlCellPr.getXmlPr(); | |||
return xmlPr.getXmlDataType(); | |||
} | |||
public String getXmlDataType() { | |||
CTXmlCellPr xmlCellPr = singleXmlCell.getXmlCellPr(); | |||
CTXmlPr xmlPr = xmlCellPr.getXmlPr(); | |||
return xmlPr.getXmlDataType(); | |||
} | |||
} |
@@ -241,14 +241,14 @@ public class XWPFHeaderFooterPolicy { | |||
} | |||
private CTHdrFtr buildFtr(Enum type, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) { | |||
//CTHdrFtr ftr = buildHdrFtr(pStyle, pars); // MB 24 May 2010 | |||
//CTHdrFtr ftr = buildHdrFtr(pStyle, pars); // MB 24 May 2010 | |||
CTHdrFtr ftr = buildHdrFtr(pars, wrapper); // MB 24 May 2010 | |||
setFooterReference(type, wrapper); | |||
return ftr; | |||
} | |||
private CTHdrFtr buildHdr(Enum type, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) { | |||
//CTHdrFtr hdr = buildHdrFtr(pStyle, pars); // MB 24 May 2010 | |||
//CTHdrFtr hdr = buildHdrFtr(pStyle, pars); // MB 24 May 2010 | |||
CTHdrFtr hdr = buildHdrFtr(pars, wrapper); // MB 24 May 2010 | |||
setHeaderReference(type, wrapper); | |||
return hdr; |
@@ -109,7 +109,7 @@ public class XWPFSettings extends POIXMLDocumentPart { | |||
zoom.setPercent(BigInteger.valueOf(zoomPercent)); | |||
} | |||
/** | |||
/** | |||
* Verifies the documentProtection tag inside settings.xml file <br> | |||
* if the protection is enforced (w:enforcement="1") <br> | |||
* <p> | |||
@@ -122,7 +122,7 @@ public class XWPFSettings extends POIXMLDocumentPart { | |||
* | |||
* @return true if documentProtection is enforced with option any | |||
*/ | |||
public boolean isEnforcedWith() { | |||
public boolean isEnforcedWith() { | |||
CTDocProtect ctDocProtect = ctSettings.getDocumentProtection(); | |||
return ctDocProtect != null && POIXMLUnits.parseOnOff(ctDocProtect.xgetEnforcement()); | |||
@@ -42,30 +42,30 @@ import org.junit.jupiter.params.provider.CsvSource; | |||
@SuppressWarnings("deprecation") | |||
class TestDetectAsOOXML { | |||
@Test | |||
void testOpensProperly() throws IOException, InvalidFormatException { | |||
try (InputStream is = openSampleFileStream("sample.xlsx"); | |||
OPCPackage pkg = OPCPackage.open(is)) { | |||
assertNotNull(pkg); | |||
} | |||
} | |||
void testOpensProperly() throws IOException, InvalidFormatException { | |||
try (InputStream is = openSampleFileStream("sample.xlsx"); | |||
OPCPackage pkg = OPCPackage.open(is)) { | |||
assertNotNull(pkg); | |||
} | |||
} | |||
@ParameterizedTest | |||
@CsvSource({"SampleSS.xlsx, OOXML", "SampleSS.xls, OLE2", "SampleSS.txt, UNKNOWN"}) | |||
void testDetectAsPOIFS(String file, FileMagic fm) throws IOException { | |||
try (InputStream is = FileMagic.prepareToCheckMagic(openSampleFileStream(file))) { | |||
FileMagic act = FileMagic.valueOf(is); | |||
@CsvSource({"SampleSS.xlsx, OOXML", "SampleSS.xls, OLE2", "SampleSS.txt, UNKNOWN"}) | |||
void testDetectAsPOIFS(String file, FileMagic fm) throws IOException { | |||
try (InputStream is = FileMagic.prepareToCheckMagic(openSampleFileStream(file))) { | |||
FileMagic act = FileMagic.valueOf(is); | |||
assertEquals(act == FileMagic.OOXML, DocumentFactoryHelper.hasOOXMLHeader(is), | |||
"OOXML files should be detected, others not"); | |||
assertEquals(act == FileMagic.OOXML, DocumentFactoryHelper.hasOOXMLHeader(is), | |||
"OOXML files should be detected, others not"); | |||
assertEquals(fm, act, "file magic failed for " + file); | |||
} | |||
} | |||
assertEquals(fm, act, "file magic failed for " + file); | |||
} | |||
} | |||
@Test | |||
void testFileCorruption() throws Exception { | |||
// create test InputStream | |||
byte[] testData = { 1, 2, 3 }; | |||
// create test InputStream | |||
byte[] testData = { 1, 2, 3 }; | |||
ByteArrayInputStream testInput = new ByteArrayInputStream(testData); | |||
InputStream is = FileMagic.prepareToCheckMagic(testInput); | |||
@@ -77,5 +77,5 @@ class TestDetectAsOOXML { | |||
assertArrayEquals(testData, act); | |||
assertEquals(-1, is.read()); | |||
is.close(); | |||
} | |||
} | |||
} |
@@ -36,42 +36,42 @@ import org.junit.jupiter.api.Test; | |||
* Class to test that we handle embeded bits in OOXML files properly | |||
*/ | |||
class TestEmbedded { | |||
@Test | |||
void testExcel() throws Exception { | |||
POIXMLDocument doc = new XSSFWorkbook( | |||
@Test | |||
void testExcel() throws Exception { | |||
POIXMLDocument doc = new XSSFWorkbook( | |||
POIDataSamples.getSpreadSheetInstance().openResourceAsStream("ExcelWithAttachments.xlsm") | |||
); | |||
test(doc, 4); | |||
} | |||
test(doc, 4); | |||
} | |||
@Test | |||
void testWord() throws Exception { | |||
POIXMLDocument doc = new XWPFDocument( | |||
@Test | |||
void testWord() throws Exception { | |||
POIXMLDocument doc = new XWPFDocument( | |||
POIDataSamples.getDocumentInstance().openResourceAsStream("WordWithAttachments.docx") | |||
); | |||
test(doc, 5); | |||
} | |||
test(doc, 5); | |||
} | |||
@Test | |||
void testPowerPoint() throws Exception { | |||
POIXMLDocument doc = new XSLFSlideShow(OPCPackage.open( | |||
@Test | |||
void testPowerPoint() throws Exception { | |||
POIXMLDocument doc = new XSLFSlideShow(OPCPackage.open( | |||
POIDataSamples.getSlideShowInstance().openResourceAsStream("PPTWithAttachments.pptm")) | |||
); | |||
test(doc, 4); | |||
} | |||
test(doc, 4); | |||
} | |||
private void test(POIXMLDocument doc, int expectedCount) throws Exception { | |||
assertNotNull(doc.getAllEmbeddedParts()); | |||
assertEquals(expectedCount, doc.getAllEmbeddedParts().size()); | |||
private void test(POIXMLDocument doc, int expectedCount) throws Exception { | |||
assertNotNull(doc.getAllEmbeddedParts()); | |||
assertEquals(expectedCount, doc.getAllEmbeddedParts().size()); | |||
for(int i=0; i<doc.getAllEmbeddedParts().size(); i++) { | |||
PackagePart pp = doc.getAllEmbeddedParts().get(i); | |||
assertNotNull(pp); | |||
for(int i=0; i<doc.getAllEmbeddedParts().size(); i++) { | |||
PackagePart pp = doc.getAllEmbeddedParts().get(i); | |||
assertNotNull(pp); | |||
byte[] b = IOUtils.toByteArray(pp.getInputStream()); | |||
assertTrue(b.length > 0); | |||
} | |||
byte[] b = IOUtils.toByteArray(pp.getInputStream()); | |||
assertTrue(b.length > 0); | |||
} | |||
doc.close(); | |||
} | |||
doc.close(); | |||
} | |||
} |
@@ -34,74 +34,74 @@ public final class TestXMLPropertiesTextExtractor { | |||
private static final POIDataSamples _ssSamples = POIDataSamples.getSpreadSheetInstance(); | |||
private static final POIDataSamples _slSamples = POIDataSamples.getSlideShowInstance(); | |||
@Test | |||
void testGetFromMainExtractor() throws Exception { | |||
OPCPackage pkg = PackageHelper.open(_ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm")); | |||
@Test | |||
void testGetFromMainExtractor() throws Exception { | |||
OPCPackage pkg = PackageHelper.open(_ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm")); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||
XSSFExcelExtractor ext = new XSSFExcelExtractor(wb); | |||
POIXMLPropertiesTextExtractor textExt = ext.getMetadataTextExtractor(); | |||
XSSFExcelExtractor ext = new XSSFExcelExtractor(wb); | |||
POIXMLPropertiesTextExtractor textExt = ext.getMetadataTextExtractor(); | |||
// Check basics | |||
assertNotNull(textExt); | |||
assertTrue(textExt.getText().length() > 0); | |||
// Check basics | |||
assertNotNull(textExt); | |||
assertTrue(textExt.getText().length() > 0); | |||
// Check some of the content | |||
String text = textExt.getText(); | |||
String cText = textExt.getCorePropertiesText(); | |||
// Check some of the content | |||
String text = textExt.getText(); | |||
String cText = textExt.getCorePropertiesText(); | |||
assertContains(text, "LastModifiedBy = Yury Batrakov"); | |||
assertContains(cText, "LastModifiedBy = Yury Batrakov"); | |||
assertContains(text, "LastModifiedBy = Yury Batrakov"); | |||
assertContains(cText, "LastModifiedBy = Yury Batrakov"); | |||
textExt.close(); | |||
ext.close(); | |||
} | |||
textExt.close(); | |||
ext.close(); | |||
} | |||
@Test | |||
void testCore() throws Exception { | |||
OPCPackage pkg = PackageHelper.open( | |||
@Test | |||
void testCore() throws Exception { | |||
OPCPackage pkg = PackageHelper.open( | |||
_ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm") | |||
); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||
); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||
POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb); | |||
ext.getText(); | |||
POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb); | |||
ext.getText(); | |||
// Now check | |||
String text = ext.getText(); | |||
String cText = ext.getCorePropertiesText(); | |||
// Now check | |||
String text = ext.getText(); | |||
String cText = ext.getCorePropertiesText(); | |||
assertContains(text, "LastModifiedBy = Yury Batrakov"); | |||
assertContains(cText, "LastModifiedBy = Yury Batrakov"); | |||
assertContains(text, "LastModifiedBy = Yury Batrakov"); | |||
assertContains(cText, "LastModifiedBy = Yury Batrakov"); | |||
ext.close(); | |||
} | |||
ext.close(); | |||
} | |||
@Test | |||
void testExtended() throws Exception { | |||
OPCPackage pkg = OPCPackage.open( | |||
@Test | |||
void testExtended() throws Exception { | |||
OPCPackage pkg = OPCPackage.open( | |||
_ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm") | |||
); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||
); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||
POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb); | |||
ext.getText(); | |||
POIXMLPropertiesTextExtractor ext = new POIXMLPropertiesTextExtractor(wb); | |||
ext.getText(); | |||
// Now check | |||
String text = ext.getText(); | |||
String eText = ext.getExtendedPropertiesText(); | |||
// Now check | |||
String text = ext.getText(); | |||
String eText = ext.getExtendedPropertiesText(); | |||
assertContains(text, "Application = Microsoft Excel"); | |||
assertContains(text, "Company = Mera"); | |||
assertContains(eText, "Application = Microsoft Excel"); | |||
assertContains(eText, "Company = Mera"); | |||
assertContains(text, "Application = Microsoft Excel"); | |||
assertContains(text, "Company = Mera"); | |||
assertContains(eText, "Application = Microsoft Excel"); | |||
assertContains(eText, "Company = Mera"); | |||
ext.close(); | |||
} | |||
ext.close(); | |||
} | |||
@Test | |||
void testCustom() throws Exception { | |||
@Test | |||
void testCustom() throws Exception { | |||
OPCPackage pkg = OPCPackage.open( | |||
_ssSamples.openResourceAsStream("ExcelWithAttachments.xlsm") | |||
); | |||
@@ -118,14 +118,14 @@ public final class TestXMLPropertiesTextExtractor { | |||
assertContains(cText, "description = another value"); | |||
ext.close(); | |||
} | |||
/** | |||
* Bug #49386 - some properties, especially | |||
* dates can be null | |||
*/ | |||
@Test | |||
void testWithSomeNulls() throws Exception { | |||
} | |||
/** | |||
* Bug #49386 - some properties, especially | |||
* dates can be null | |||
*/ | |||
@Test | |||
void testWithSomeNulls() throws Exception { | |||
OPCPackage pkg = OPCPackage.open( | |||
_slSamples.openResourceAsStream("49386-null_dates.pptx") | |||
); | |||
@@ -140,5 +140,5 @@ public final class TestXMLPropertiesTextExtractor { | |||
assertContains(text, "LastModifiedBy = IT Client Services"); | |||
ext.close(); | |||
} | |||
} | |||
} |
@@ -30,23 +30,23 @@ import java.io.IOException; | |||
public final class OpenXML4JTestDataSamples { | |||
private static final POIDataSamples _samples = POIDataSamples.getOpenXML4JInstance(); | |||
private OpenXML4JTestDataSamples() { | |||
// no instances of this class | |||
} | |||
public static InputStream openSampleStream(String sampleFileName) { | |||
return _samples.openResourceAsStream(sampleFileName); | |||
} | |||
public static String getSampleFileName(String sampleFileName) { | |||
return getSampleFile(sampleFileName).getAbsolutePath(); | |||
} | |||
public static File getSampleFile(String sampleFileName) { | |||
return _samples.getFile(sampleFileName); | |||
} | |||
public static File getOutputFile(String outputFileName) throws IOException { | |||
int idx = outputFileName.lastIndexOf('.'); | |||
private OpenXML4JTestDataSamples() { | |||
// no instances of this class | |||
} | |||
public static InputStream openSampleStream(String sampleFileName) { | |||
return _samples.openResourceAsStream(sampleFileName); | |||
} | |||
public static String getSampleFileName(String sampleFileName) { | |||
return getSampleFile(sampleFileName).getAbsolutePath(); | |||
} | |||
public static File getSampleFile(String sampleFileName) { | |||
return _samples.getFile(sampleFileName); | |||
} | |||
public static File getOutputFile(String outputFileName) throws IOException { | |||
int idx = outputFileName.lastIndexOf('.'); | |||
return TempFile.createTempFile(outputFileName.substring(0,idx), outputFileName.substring(idx)); | |||
} | |||
} | |||
} |
@@ -30,27 +30,27 @@ import org.junit.jupiter.api.Test; | |||
*/ | |||
public final class TestFileHelper { | |||
/** | |||
* TODO - use simple JDK methods on {@link File} instead:<br> | |||
* {@link File#getParentFile()} instead of {@link FileHelper#getDirectory(File) | |||
* {@link File#getName()} instead of {@link FileHelper#getFilename(File) | |||
*/ | |||
/** | |||
* TODO - use simple JDK methods on {@link File} instead:<br> | |||
* {@link File#getParentFile()} instead of {@link FileHelper#getDirectory(File) | |||
* {@link File#getName()} instead of {@link FileHelper#getFilename(File) | |||
*/ | |||
@Test | |||
void testGetDirectory() { | |||
TreeMap<String, String> expectedValue = new TreeMap<>(); | |||
expectedValue.put("/dir1/test.doc", "/dir1"); | |||
expectedValue.put("/dir1/dir2/test.doc.xml", "/dir1/dir2"); | |||
for (String filename : expectedValue.keySet()) { | |||
File f1 = new File(expectedValue.get(filename)); | |||
File f2 = FileHelper.getDirectory(new File(filename)); | |||
// if (false) { | |||
// // YK: The original version asserted expected values against File#getAbsolutePath(): | |||
// assertTrue(expectedValue.get(filename).equalsIgnoreCase(f2.getAbsolutePath())); | |||
// // This comparison is platform dependent. A better approach is below | |||
// } | |||
assertEquals(f1, f2); | |||
} | |||
} | |||
void testGetDirectory() { | |||
TreeMap<String, String> expectedValue = new TreeMap<>(); | |||
expectedValue.put("/dir1/test.doc", "/dir1"); | |||
expectedValue.put("/dir1/dir2/test.doc.xml", "/dir1/dir2"); | |||
for (String filename : expectedValue.keySet()) { | |||
File f1 = new File(expectedValue.get(filename)); | |||
File f2 = FileHelper.getDirectory(new File(filename)); | |||
// if (false) { | |||
// // YK: The original version asserted expected values against File#getAbsolutePath(): | |||
// assertTrue(expectedValue.get(filename).equalsIgnoreCase(f2.getAbsolutePath())); | |||
// // This comparison is platform dependent. A better approach is below | |||
// } | |||
assertEquals(f1, f2); | |||
} | |||
} | |||
} |
@@ -34,71 +34,71 @@ import org.junit.jupiter.api.Test; | |||
public final class TestListParts { | |||
private static final Logger LOG = LogManager.getLogger(TestListParts.class); | |||
private TreeMap<PackagePartName, String> expectedValues; | |||
private TreeMap<PackagePartName, String> expectedValues; | |||
private TreeMap<PackagePartName, String> values; | |||
private TreeMap<PackagePartName, String> values; | |||
@BeforeEach | |||
void setUp() throws Exception { | |||
values = new TreeMap<>(); | |||
@BeforeEach | |||
void setUp() throws Exception { | |||
values = new TreeMap<>(); | |||
// Expected values | |||
expectedValues = new TreeMap<>(); | |||
expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"), | |||
"application/vnd.openxmlformats-package.relationships+xml"); | |||
// Expected values | |||
expectedValues = new TreeMap<>(); | |||
expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"), | |||
"application/vnd.openxmlformats-package.relationships+xml"); | |||
expectedValues | |||
.put(PackagingURIHelper.createPartName("/docProps/app.xml"), | |||
"application/vnd.openxmlformats-officedocument.extended-properties+xml"); | |||
expectedValues.put(PackagingURIHelper | |||
.createPartName("/docProps/core.xml"), | |||
"application/vnd.openxmlformats-package.core-properties+xml"); | |||
expectedValues.put(PackagingURIHelper | |||
.createPartName("/word/_rels/document.xml.rels"), | |||
"application/vnd.openxmlformats-package.relationships+xml"); | |||
expectedValues | |||
.put( | |||
PackagingURIHelper.createPartName("/word/document.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); | |||
expectedValues | |||
.put(PackagingURIHelper.createPartName("/word/fontTable.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"); | |||
expectedValues.put(PackagingURIHelper | |||
.createPartName("/word/media/image1.gif"), "image/gif"); | |||
expectedValues | |||
.put(PackagingURIHelper.createPartName("/word/settings.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"); | |||
expectedValues | |||
.put(PackagingURIHelper.createPartName("/word/styles.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"); | |||
expectedValues.put(PackagingURIHelper | |||
.createPartName("/word/theme/theme1.xml"), | |||
"application/vnd.openxmlformats-officedocument.theme+xml"); | |||
expectedValues | |||
.put( | |||
PackagingURIHelper | |||
.createPartName("/word/webSettings.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"); | |||
} | |||
expectedValues | |||
.put(PackagingURIHelper.createPartName("/docProps/app.xml"), | |||
"application/vnd.openxmlformats-officedocument.extended-properties+xml"); | |||
expectedValues.put(PackagingURIHelper | |||
.createPartName("/docProps/core.xml"), | |||
"application/vnd.openxmlformats-package.core-properties+xml"); | |||
expectedValues.put(PackagingURIHelper | |||
.createPartName("/word/_rels/document.xml.rels"), | |||
"application/vnd.openxmlformats-package.relationships+xml"); | |||
expectedValues | |||
.put( | |||
PackagingURIHelper.createPartName("/word/document.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); | |||
expectedValues | |||
.put(PackagingURIHelper.createPartName("/word/fontTable.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"); | |||
expectedValues.put(PackagingURIHelper | |||
.createPartName("/word/media/image1.gif"), "image/gif"); | |||
expectedValues | |||
.put(PackagingURIHelper.createPartName("/word/settings.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"); | |||
expectedValues | |||
.put(PackagingURIHelper.createPartName("/word/styles.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"); | |||
expectedValues.put(PackagingURIHelper | |||
.createPartName("/word/theme/theme1.xml"), | |||
"application/vnd.openxmlformats-officedocument.theme+xml"); | |||
expectedValues | |||
.put( | |||
PackagingURIHelper | |||
.createPartName("/word/webSettings.xml"), | |||
"application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"); | |||
} | |||
/** | |||
* List all parts of a package. | |||
*/ | |||
@Test | |||
void testListParts() throws InvalidFormatException, IOException { | |||
try (InputStream is = OpenXML4JTestDataSamples.openSampleStream("sample.docx"); | |||
OPCPackage p = OPCPackage.open(is)) { | |||
/** | |||
* List all parts of a package. | |||
*/ | |||
@Test | |||
void testListParts() throws InvalidFormatException, IOException { | |||
try (InputStream is = OpenXML4JTestDataSamples.openSampleStream("sample.docx"); | |||
OPCPackage p = OPCPackage.open(is)) { | |||
for (PackagePart part : p.getParts()) { | |||
values.put(part.getPartName(), part.getContentType()); | |||
LOG.atDebug().log(part.getPartName()); | |||
} | |||
for (PackagePart part : p.getParts()) { | |||
values.put(part.getPartName(), part.getContentType()); | |||
LOG.atDebug().log(part.getPartName()); | |||
} | |||
// Compare expected values with values return by the package | |||
for (PackagePartName partName : expectedValues.keySet()) { | |||
assertNotNull(values.get(partName)); | |||
assertEquals(expectedValues.get(partName), values.get(partName)); | |||
} | |||
} | |||
} | |||
// Compare expected values with values return by the package | |||
for (PackagePartName partName : expectedValues.keySet()) { | |||
assertNotNull(values.get(partName)); | |||
assertEquals(expectedValues.get(partName), values.get(partName)); | |||
} | |||
} | |||
} | |||
} |
@@ -47,38 +47,38 @@ import org.junit.jupiter.api.Test; | |||
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty; | |||
public final class TestPackageCoreProperties { | |||
/** | |||
* Test package core properties getters. | |||
*/ | |||
/** | |||
* Test package core properties getters. | |||
*/ | |||
@Test | |||
void testGetProperties() throws Exception { | |||
// Open the package | |||
@SuppressWarnings("resource") | |||
void testGetProperties() throws Exception { | |||
// Open the package | |||
@SuppressWarnings("resource") | |||
OPCPackage p = OPCPackage.open(openSampleStream("TestPackageCoreProperiesGetters.docx")); | |||
compareProperties(p); | |||
p.revert(); | |||
} | |||
compareProperties(p); | |||
p.revert(); | |||
} | |||
/** | |||
* Test package core properties setters. | |||
*/ | |||
/** | |||
* Test package core properties setters. | |||
*/ | |||
@Test | |||
void testSetProperties() throws Exception { | |||
String inputPath = getSampleFileName("TestPackageCoreProperiesSetters.docx"); | |||
String inputPath = getSampleFileName("TestPackageCoreProperiesSetters.docx"); | |||
File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageCoreProperiesSettersOUTPUT.docx"); | |||
File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageCoreProperiesSettersOUTPUT.docx"); | |||
// Open package | |||
@SuppressWarnings("resource") | |||
// Open package | |||
@SuppressWarnings("resource") | |||
OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE); | |||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT); | |||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT); | |||
df.setTimeZone(LocaleUtil.TIMEZONE_UTC); | |||
Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0)); | |||
Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0)); | |||
SimpleDateFormat msdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT); | |||
msdf.setTimeZone(LocaleUtil.TIMEZONE_UTC); | |||
PackageProperties props = p.getPackageProperties(); | |||
PackageProperties props = p.getPackageProperties(); | |||
//test various date formats | |||
props.setCreatedProperty("2007-05-12T08:00:00Z"); | |||
@@ -106,59 +106,59 @@ public final class TestPackageCoreProperties { | |||
assertEquals(msdf.parse("2007-05-12T08:00:00.123Z"), props.getCreatedProperty().orElse(null)); | |||
props.setCategoryProperty("MyCategory"); | |||
props.setContentStatusProperty("MyContentStatus"); | |||
props.setContentTypeProperty("MyContentType"); | |||
props.setCreatorProperty("MyCreator"); | |||
props.setDescriptionProperty("MyDescription"); | |||
props.setIdentifierProperty("MyIdentifier"); | |||
props.setKeywordsProperty("MyKeywords"); | |||
props.setLanguageProperty("MyLanguage"); | |||
props.setLastModifiedByProperty("Julien Chable"); | |||
props.setLastPrintedProperty(Optional.of(dateToInsert)); | |||
props.setModifiedProperty(Optional.of(dateToInsert)); | |||
props.setRevisionProperty("2"); | |||
props.setTitleProperty("MyTitle"); | |||
props.setSubjectProperty("MySubject"); | |||
props.setVersionProperty("2"); | |||
// Save the package in the output directory | |||
p.save(outputFile); | |||
props.setContentStatusProperty("MyContentStatus"); | |||
props.setContentTypeProperty("MyContentType"); | |||
props.setCreatorProperty("MyCreator"); | |||
props.setDescriptionProperty("MyDescription"); | |||
props.setIdentifierProperty("MyIdentifier"); | |||
props.setKeywordsProperty("MyKeywords"); | |||
props.setLanguageProperty("MyLanguage"); | |||
props.setLastModifiedByProperty("Julien Chable"); | |||
props.setLastPrintedProperty(Optional.of(dateToInsert)); | |||
props.setModifiedProperty(Optional.of(dateToInsert)); | |||
props.setRevisionProperty("2"); | |||
props.setTitleProperty("MyTitle"); | |||
props.setSubjectProperty("MySubject"); | |||
props.setVersionProperty("2"); | |||
// Save the package in the output directory | |||
p.save(outputFile); | |||
p.revert(); | |||
// Open the newly created file to check core properties saved values. | |||
@SuppressWarnings("resource") | |||
// Open the newly created file to check core properties saved values. | |||
@SuppressWarnings("resource") | |||
OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ); | |||
compareProperties(p2); | |||
p2.revert(); | |||
assertTrue(outputFile.delete()); | |||
} | |||
private void compareProperties(OPCPackage p) throws InvalidFormatException { | |||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT); | |||
df.setTimeZone(LocaleUtil.TIMEZONE_UTC); | |||
Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0)); | |||
// Gets the core properties | |||
PackageProperties props = p.getPackageProperties(); | |||
assertEquals("MyCategory", props.getCategoryProperty().orElse(null)); | |||
assertEquals("MyContentStatus", props.getContentStatusProperty().orElse(null)); | |||
assertEquals("MyContentType", props.getContentTypeProperty().orElse(null)); | |||
assertEquals(expectedDate, props.getCreatedProperty().orElse(null)); | |||
assertEquals("MyCreator", props.getCreatorProperty().orElse(null)); | |||
assertEquals("MyDescription", props.getDescriptionProperty().orElse(null)); | |||
assertEquals("MyIdentifier", props.getIdentifierProperty().orElse(null)); | |||
assertEquals("MyKeywords", props.getKeywordsProperty().orElse(null)); | |||
assertEquals("MyLanguage", props.getLanguageProperty().orElse(null)); | |||
assertEquals("Julien Chable", props.getLastModifiedByProperty().orElse(null)); | |||
assertEquals(expectedDate, props.getLastPrintedProperty().orElse(null)); | |||
assertEquals(expectedDate, props.getModifiedProperty().orElse(null)); | |||
assertEquals("2", props.getRevisionProperty().orElse(null)); | |||
assertEquals("MySubject", props.getSubjectProperty().orElse(null)); | |||
assertEquals("MyTitle", props.getTitleProperty().orElse(null)); | |||
assertEquals("2", props.getVersionProperty().orElse(null)); | |||
} | |||
@Test | |||
void testCoreProperties_bug51374() throws Exception { | |||
compareProperties(p2); | |||
p2.revert(); | |||
assertTrue(outputFile.delete()); | |||
} | |||
private void compareProperties(OPCPackage p) throws InvalidFormatException { | |||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT); | |||
df.setTimeZone(LocaleUtil.TIMEZONE_UTC); | |||
Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0)); | |||
// Gets the core properties | |||
PackageProperties props = p.getPackageProperties(); | |||
assertEquals("MyCategory", props.getCategoryProperty().orElse(null)); | |||
assertEquals("MyContentStatus", props.getContentStatusProperty().orElse(null)); | |||
assertEquals("MyContentType", props.getContentTypeProperty().orElse(null)); | |||
assertEquals(expectedDate, props.getCreatedProperty().orElse(null)); | |||
assertEquals("MyCreator", props.getCreatorProperty().orElse(null)); | |||
assertEquals("MyDescription", props.getDescriptionProperty().orElse(null)); | |||
assertEquals("MyIdentifier", props.getIdentifierProperty().orElse(null)); | |||
assertEquals("MyKeywords", props.getKeywordsProperty().orElse(null)); | |||
assertEquals("MyLanguage", props.getLanguageProperty().orElse(null)); | |||
assertEquals("Julien Chable", props.getLastModifiedByProperty().orElse(null)); | |||
assertEquals(expectedDate, props.getLastPrintedProperty().orElse(null)); | |||
assertEquals(expectedDate, props.getModifiedProperty().orElse(null)); | |||
assertEquals("2", props.getRevisionProperty().orElse(null)); | |||
assertEquals("MySubject", props.getSubjectProperty().orElse(null)); | |||
assertEquals("MyTitle", props.getTitleProperty().orElse(null)); | |||
assertEquals("2", props.getVersionProperty().orElse(null)); | |||
} | |||
@Test | |||
void testCoreProperties_bug51374() throws Exception { | |||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT); | |||
df.setTimeZone(LocaleUtil.TIMEZONE_UTC); | |||
String strDate = "2007-05-12T08:00:00Z"; | |||
@@ -214,8 +214,8 @@ public final class TestPackageCoreProperties { | |||
} | |||
} | |||
@Test | |||
void testGetPropertiesLO() throws Exception { | |||
@Test | |||
void testGetPropertiesLO() throws Exception { | |||
UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream(); | |||
// Open the package | |||
try (OPCPackage pkg1 = OPCPackage.open(openSampleStream("51444.xlsx"))) { | |||
@@ -231,8 +231,8 @@ public final class TestPackageCoreProperties { | |||
} | |||
} | |||
@Test | |||
void testEntitiesInCoreProps_56164() throws Exception { | |||
@Test | |||
void testEntitiesInCoreProps_56164() throws Exception { | |||
try (InputStream is = openSampleStream("CorePropertiesHasEntities.ooxml"); | |||
OPCPackage p = OPCPackage.open(is)) { | |||
@@ -263,8 +263,8 @@ public final class TestPackageCoreProperties { | |||
} | |||
} | |||
@Test | |||
void testListOfCustomProperties() throws Exception { | |||
@Test | |||
void testListOfCustomProperties() throws Exception { | |||
File inp = POIDataSamples.getSpreadSheetInstance().getFile("ExcelWithAttachments.xlsm"); | |||
try (OPCPackage pkg = OPCPackage.open(inp, PackageAccess.READ); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg)) { | |||
@@ -278,8 +278,8 @@ public final class TestPackageCoreProperties { | |||
} | |||
} | |||
@Test | |||
void testAlternateCorePropertyTimezones() throws Exception { | |||
@Test | |||
void testAlternateCorePropertyTimezones() throws Exception { | |||
// We need predictable dates for testing! | |||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT); | |||
df.setTimeZone(LocaleUtil.TIMEZONE_UTC); | |||
@@ -329,5 +329,5 @@ public final class TestPackageCoreProperties { | |||
// CoreProperties are stored as xs:dateTime -> no milliseconds are saved! | |||
assertEquals("2007-06-21T09:59:00.000Z", df.format(props2.getModifiedProperty().orElse(null))); | |||
} | |||
} | |||
} | |||
} |
@@ -23,14 +23,14 @@ import org.junit.jupiter.api.Test; | |||
public final class TestPackagePartName { | |||
/** | |||
* Test method getExtension(). | |||
*/ | |||
@Test | |||
void testGetExtension() throws Exception{ | |||
PackagePartName name1 = PackagingURIHelper.createPartName("/doc/props/document.xml"); | |||
PackagePartName name2 = PackagingURIHelper.createPartName("/root/document"); | |||
assertEquals("xml", name1.getExtension()); | |||
assertEquals("", name2.getExtension()); | |||
} | |||
/** | |||
* Test method getExtension(). | |||
*/ | |||
@Test | |||
void testGetExtension() throws Exception{ | |||
PackagePartName name1 = PackagingURIHelper.createPartName("/doc/props/document.xml"); | |||
PackagePartName name2 = PackagingURIHelper.createPartName("/root/document"); | |||
assertEquals("xml", name1.getExtension()); | |||
assertEquals("", name2.getExtension()); | |||
} | |||
} |
@@ -31,31 +31,31 @@ import org.junit.jupiter.api.Test; | |||
*/ | |||
public final class TestPackageThumbnail { | |||
/** | |||
* Test package addThumbnail() method. | |||
*/ | |||
@Test | |||
void testSetProperties() throws Exception { | |||
String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageThumbnail.docx"); | |||
String imagePath = OpenXML4JTestDataSamples.getSampleFileName("thumbnail.jpg"); | |||
File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageThumbnailOUTPUT.docx"); | |||
// Open package | |||
try (OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE)) { | |||
p.addThumbnail(imagePath); | |||
// Save the package in the output directory | |||
p.save(outputFile); | |||
// Open the newly created file to check core properties saved values. | |||
try (OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ)) { | |||
assertNotEquals(0, p2.getRelationshipsByType(PackageRelationshipTypes.THUMBNAIL).size(), | |||
"Thumbnail not added to the package !"); | |||
p2.revert(); | |||
} | |||
p.revert(); | |||
} | |||
assertTrue(outputFile.delete()); | |||
} | |||
/** | |||
* Test package addThumbnail() method. | |||
*/ | |||
@Test | |||
void testSetProperties() throws Exception { | |||
String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageThumbnail.docx"); | |||
String imagePath = OpenXML4JTestDataSamples.getSampleFileName("thumbnail.jpg"); | |||
File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageThumbnailOUTPUT.docx"); | |||
// Open package | |||
try (OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE)) { | |||
p.addThumbnail(imagePath); | |||
// Save the package in the output directory | |||
p.save(outputFile); | |||
// Open the newly created file to check core properties saved values. | |||
try (OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ)) { | |||
assertNotEquals(0, p2.getRelationshipsByType(PackageRelationshipTypes.THUMBNAIL).size(), | |||
"Thumbnail not added to the package !"); | |||
p2.revert(); | |||
} | |||
p.revert(); | |||
} | |||
assertTrue(outputFile.delete()); | |||
} | |||
} |
@@ -36,12 +36,12 @@ import org.junit.jupiter.api.Test; | |||
class TestRelationships { | |||
private static final String HYPERLINK_REL_TYPE = | |||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; | |||
private static final String COMMENTS_REL_TYPE = | |||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; | |||
private static final String SHEET_WITH_COMMENTS = | |||
"/xl/worksheets/sheet1.xml"; | |||
private static final String HYPERLINK_REL_TYPE = | |||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; | |||
private static final String COMMENTS_REL_TYPE = | |||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; | |||
private static final String SHEET_WITH_COMMENTS = | |||
"/xl/worksheets/sheet1.xml"; | |||
private static final Logger LOG = LogManager.getLogger(TestPackageCoreProperties.class); | |||
@@ -155,72 +155,72 @@ class TestRelationships { | |||
*/ | |||
@Test | |||
void testCreateExcelHyperlinkRelations() throws Exception { | |||
String filepath = OpenXML4JTestDataSamples.getSampleFileName("ExcelWithHyperlinks.xlsx"); | |||
OPCPackage pkg = OPCPackage.open(filepath, PackageAccess.READ_WRITE); | |||
PackagePart sheet = pkg.getPart( | |||
PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); | |||
assertNotNull(sheet); | |||
String filepath = OpenXML4JTestDataSamples.getSampleFileName("ExcelWithHyperlinks.xlsx"); | |||
OPCPackage pkg = OPCPackage.open(filepath, PackageAccess.READ_WRITE); | |||
PackagePart sheet = pkg.getPart( | |||
PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); | |||
assertNotNull(sheet); | |||
assertEquals(3, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); | |||
assertEquals(3, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); | |||
// Add three new ones | |||
PackageRelationship openxml4j = | |||
sheet.addExternalRelationship("http://www.openxml4j.org/", HYPERLINK_REL_TYPE); | |||
PackageRelationship sf = | |||
sheet.addExternalRelationship("http://openxml4j.sf.net/", HYPERLINK_REL_TYPE); | |||
PackageRelationship file = | |||
sheet.addExternalRelationship("MyDocument.docx", HYPERLINK_REL_TYPE); | |||
// Add three new ones | |||
PackageRelationship openxml4j = | |||
sheet.addExternalRelationship("http://www.openxml4j.org/", HYPERLINK_REL_TYPE); | |||
PackageRelationship sf = | |||
sheet.addExternalRelationship("http://openxml4j.sf.net/", HYPERLINK_REL_TYPE); | |||
PackageRelationship file = | |||
sheet.addExternalRelationship("MyDocument.docx", HYPERLINK_REL_TYPE); | |||
// Check they were added properly | |||
assertNotNull(openxml4j); | |||
assertNotNull(sf); | |||
assertNotNull(file); | |||
// Check they were added properly | |||
assertNotNull(openxml4j); | |||
assertNotNull(sf); | |||
assertNotNull(file); | |||
assertEquals(6, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); | |||
assertEquals(6, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); | |||
assertEquals("http://www.openxml4j.org/", openxml4j.getTargetURI().toString()); | |||
assertEquals("/xl/worksheets/sheet1.xml", openxml4j.getSourceURI().toString()); | |||
assertEquals(HYPERLINK_REL_TYPE, openxml4j.getRelationshipType()); | |||
assertEquals("http://www.openxml4j.org/", openxml4j.getTargetURI().toString()); | |||
assertEquals("/xl/worksheets/sheet1.xml", openxml4j.getSourceURI().toString()); | |||
assertEquals(HYPERLINK_REL_TYPE, openxml4j.getRelationshipType()); | |||
assertEquals("http://openxml4j.sf.net/", sf.getTargetURI().toString()); | |||
assertEquals("/xl/worksheets/sheet1.xml", sf.getSourceURI().toString()); | |||
assertEquals(HYPERLINK_REL_TYPE, sf.getRelationshipType()); | |||
assertEquals("http://openxml4j.sf.net/", sf.getTargetURI().toString()); | |||
assertEquals("/xl/worksheets/sheet1.xml", sf.getSourceURI().toString()); | |||
assertEquals(HYPERLINK_REL_TYPE, sf.getRelationshipType()); | |||
assertEquals("MyDocument.docx", file.getTargetURI().toString()); | |||
assertEquals("/xl/worksheets/sheet1.xml", file.getSourceURI().toString()); | |||
assertEquals(HYPERLINK_REL_TYPE, file.getRelationshipType()); | |||
assertEquals("MyDocument.docx", file.getTargetURI().toString()); | |||
assertEquals("/xl/worksheets/sheet1.xml", file.getSourceURI().toString()); | |||
assertEquals(HYPERLINK_REL_TYPE, file.getRelationshipType()); | |||
// Will get ids 7, 8 and 9, as we already have 1-6 | |||
assertEquals("rId7", openxml4j.getId()); | |||
assertEquals("rId8", sf.getId()); | |||
assertEquals("rId9", file.getId()); | |||
// Will get ids 7, 8 and 9, as we already have 1-6 | |||
assertEquals("rId7", openxml4j.getId()); | |||
assertEquals("rId8", sf.getId()); | |||
assertEquals("rId9", file.getId()); | |||
// Write out and re-load | |||
UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); | |||
pkg.save(baos); | |||
// Write out and re-load | |||
UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); | |||
pkg.save(baos); | |||
// use revert to not re-write the input file | |||
// use revert to not re-write the input file | |||
pkg.revert(); | |||
pkg = OPCPackage.open(baos.toInputStream()); | |||
// Check again | |||
sheet = pkg.getPart(PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); | |||
pkg = OPCPackage.open(baos.toInputStream()); | |||
assertEquals(6, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); | |||
// Check again | |||
sheet = pkg.getPart(PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); | |||
assertEquals("http://poi.apache.org/", | |||
sheet.getRelationship("rId1").getTargetURI().toString()); | |||
assertEquals("mailto:dev@poi.apache.org?subject=XSSF%20Hyperlinks", | |||
sheet.getRelationship("rId3").getTargetURI().toString()); | |||
assertEquals(6, sheet.getRelationshipsByType(HYPERLINK_REL_TYPE).size()); | |||
assertEquals("http://www.openxml4j.org/", | |||
sheet.getRelationship("rId7").getTargetURI().toString()); | |||
assertEquals("http://openxml4j.sf.net/", | |||
sheet.getRelationship("rId8").getTargetURI().toString()); | |||
assertEquals("MyDocument.docx", | |||
sheet.getRelationship("rId9").getTargetURI().toString()); | |||
assertEquals("http://poi.apache.org/", | |||
sheet.getRelationship("rId1").getTargetURI().toString()); | |||
assertEquals("mailto:dev@poi.apache.org?subject=XSSF%20Hyperlinks", | |||
sheet.getRelationship("rId3").getTargetURI().toString()); | |||
assertEquals("http://www.openxml4j.org/", | |||
sheet.getRelationship("rId7").getTargetURI().toString()); | |||
assertEquals("http://openxml4j.sf.net/", | |||
sheet.getRelationship("rId8").getTargetURI().toString()); | |||
assertEquals("MyDocument.docx", | |||
sheet.getRelationship("rId9").getTargetURI().toString()); | |||
} | |||
@Test | |||
@@ -352,9 +352,9 @@ class TestRelationships { | |||
@Test | |||
void testSelfRelations_bug51187() throws Exception { | |||
UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); | |||
UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); | |||
PackageRelationship rel1; | |||
try (OPCPackage pkg = OPCPackage.create(baos)) { | |||
try (OPCPackage pkg = OPCPackage.create(baos)) { | |||
PackagePart partA = | |||
pkg.createPart(PackagingURIHelper.createPartName("/partA"), "text/plain"); | |||
@@ -367,7 +367,7 @@ class TestRelationships { | |||
// Save, and re-load | |||
} | |||
try (OPCPackage pkg = OPCPackage.open(baos.toInputStream())) { | |||
try (OPCPackage pkg = OPCPackage.open(baos.toInputStream())) { | |||
PackagePart partA = pkg.getPart(PackagingURIHelper.createPartName("/partA")); | |||
@@ -174,12 +174,12 @@ class TestSignatureInfo { | |||
private KeyPair keyPair; | |||
private X509Certificate x509; | |||
@BeforeAll | |||
public static void setUpClass() { | |||
POITestCase.setImageIOCacheDir(); | |||
} | |||
@BeforeAll | |||
public static void setUpClass() { | |||
POITestCase.setImageIOCacheDir(); | |||
} | |||
@AfterAll | |||
@AfterAll | |||
public static void removeUserLocale() { | |||
LocaleUtil.resetUserLocale(); | |||
} | |||
@@ -748,13 +748,13 @@ class TestSignatureInfo { | |||
void bug65214() throws Exception { | |||
initKeyPair(); | |||
UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream(); | |||
try (XWPFDocument doc = new XWPFDocument()) { | |||
UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream(); | |||
try (XWPFDocument doc = new XWPFDocument()) { | |||
XWPFHyperlinkRun r = doc.createParagraph().createHyperlinkRun("http://poi.apache.org"); | |||
r.setText("Hyperlink"); | |||
r.setUnderline(UnderlinePatterns.SINGLE); | |||
r.setUnderlineColor("0000FF"); | |||
doc.write(bos); | |||
r.setText("Hyperlink"); | |||
r.setUnderline(UnderlinePatterns.SINGLE); | |||
r.setUnderlineColor("0000FF"); | |||
doc.write(bos); | |||
} | |||
SignatureConfig signatureConfig = new SignatureConfig(); | |||
@@ -966,7 +966,7 @@ class TestSignatureInfo { | |||
try (OPCPackage pkg = OPCPackage.open(signDoc, PackageAccess.READ)) { | |||
SignatureLine line2 = sup.get(); | |||
try (POIXMLDocument doc = reinit.init(line2, pkg)) { | |||
assertNotNull(doc); | |||
assertNotNull(doc); | |||
line2.parse(); | |||
assertEquals(line.getSuggestedSigner(), line2.getSuggestedSigner()); |
@@ -24,7 +24,7 @@ import org.apache.poi.xssf.XSSFITestDataProvider; | |||
* Tests XSSFFormulaEvaluator for its handling of cell formula circular references. | |||
*/ | |||
public final class TestXSSFCircularReferences extends BaseTestCircularReferences { | |||
public TestXSSFCircularReferences() { | |||
public TestXSSFCircularReferences() { | |||
super(XSSFITestDataProvider.instance); | |||
} | |||
} |
@@ -48,94 +48,94 @@ class TestXSLFSlideShow { | |||
@BeforeEach | |||
void setUp() throws Exception { | |||
pack = OPCPackage.open(slTests.openResourceAsStream("sample.pptx")); | |||
} | |||
pack = OPCPackage.open(slTests.openResourceAsStream("sample.pptx")); | |||
} | |||
@AfterEach | |||
void tearDown() throws IOException { | |||
pack.close(); | |||
} | |||
@AfterEach | |||
void tearDown() throws IOException { | |||
pack.close(); | |||
} | |||
@Test | |||
void testContainsMainContentType() throws Exception { | |||
boolean found = false; | |||
for(PackagePart part : pack.getParts()) { | |||
if(part.getContentType().equals(XSLFRelation.MAIN.getContentType())) { | |||
found = true; | |||
} | |||
} | |||
assertTrue(found); | |||
} | |||
void testContainsMainContentType() throws Exception { | |||
boolean found = false; | |||
for(PackagePart part : pack.getParts()) { | |||
if(part.getContentType().equals(XSLFRelation.MAIN.getContentType())) { | |||
found = true; | |||
} | |||
} | |||
assertTrue(found); | |||
} | |||
@Test | |||
void testOpen() throws IOException, OpenXML4JException, XmlException { | |||
// With the finalized uri, should be fine | |||
XSLFSlideShow xml = new XSLFSlideShow(pack); | |||
// Check the core | |||
assertNotNull(xml.getPresentation()); | |||
void testOpen() throws IOException, OpenXML4JException, XmlException { | |||
// With the finalized uri, should be fine | |||
XSLFSlideShow xml = new XSLFSlideShow(pack); | |||
// Check the core | |||
assertNotNull(xml.getPresentation()); | |||
// Check it has some slides | |||
assertNotEquals(0, xml.getSlideReferences().sizeOfSldIdArray()); | |||
assertNotEquals(0, xml.getSlideMasterReferences().sizeOfSldMasterIdArray()); | |||
// Check it has some slides | |||
assertNotEquals(0, xml.getSlideReferences().sizeOfSldIdArray()); | |||
assertNotEquals(0, xml.getSlideMasterReferences().sizeOfSldMasterIdArray()); | |||
xml.close(); | |||
} | |||
xml.close(); | |||
} | |||
@Test | |||
void testSlideBasics() throws IOException, OpenXML4JException, XmlException { | |||
XSLFSlideShow xml = new XSLFSlideShow(pack); | |||
void testSlideBasics() throws IOException, OpenXML4JException, XmlException { | |||
XSLFSlideShow xml = new XSLFSlideShow(pack); | |||
// Should have 1 master | |||
assertEquals(1, xml.getSlideMasterReferences().sizeOfSldMasterIdArray()); | |||
// Should have 1 master | |||
assertEquals(1, xml.getSlideMasterReferences().sizeOfSldMasterIdArray()); | |||
// Should have three sheets | |||
assertEquals(2, xml.getSlideReferences().sizeOfSldIdArray()); | |||
// Should have three sheets | |||
assertEquals(2, xml.getSlideReferences().sizeOfSldIdArray()); | |||
// Check they're as expected | |||
CTSlideIdListEntry[] slides = xml.getSlideReferences().getSldIdArray(); | |||
// Check they're as expected | |||
CTSlideIdListEntry[] slides = xml.getSlideReferences().getSldIdArray(); | |||
assertEquals(256, slides[0].getId()); | |||
assertEquals(257, slides[1].getId()); | |||
assertEquals("rId2", slides[0].getId2()); | |||
assertEquals("rId3", slides[1].getId2()); | |||
assertEquals(256, slides[0].getId()); | |||
assertEquals(257, slides[1].getId()); | |||
assertEquals("rId2", slides[0].getId2()); | |||
assertEquals("rId3", slides[1].getId2()); | |||
// Now get those objects | |||
assertNotNull(xml.getSlide(slides[0])); | |||
assertNotNull(xml.getSlide(slides[1])); | |||
// Now get those objects | |||
assertNotNull(xml.getSlide(slides[0])); | |||
assertNotNull(xml.getSlide(slides[1])); | |||
// And check they have notes as expected | |||
assertNotNull(xml.getNotes(slides[0])); | |||
assertNotNull(xml.getNotes(slides[1])); | |||
// And check they have notes as expected | |||
assertNotNull(xml.getNotes(slides[0])); | |||
assertNotNull(xml.getNotes(slides[1])); | |||
// And again for the master | |||
CTSlideMasterIdListEntry[] masters = xml.getSlideMasterReferences().getSldMasterIdArray(); | |||
// And again for the master | |||
CTSlideMasterIdListEntry[] masters = xml.getSlideMasterReferences().getSldMasterIdArray(); | |||
// see SlideAtom.USES_MASTER_SLIDE_ID | |||
assertEquals(0x80000000L, masters[0].getId()); | |||
assertEquals("rId1", masters[0].getId2()); | |||
assertNotNull(xml.getSlideMaster(masters[0])); | |||
// see SlideAtom.USES_MASTER_SLIDE_ID | |||
assertEquals(0x80000000L, masters[0].getId()); | |||
assertEquals("rId1", masters[0].getId2()); | |||
assertNotNull(xml.getSlideMaster(masters[0])); | |||
xml.close(); | |||
} | |||
xml.close(); | |||
} | |||
@Test | |||
void testMetadataBasics() throws IOException, OpenXML4JException, XmlException { | |||
XSLFSlideShow xml = new XSLFSlideShow(pack); | |||
void testMetadataBasics() throws IOException, OpenXML4JException, XmlException { | |||
XSLFSlideShow xml = new XSLFSlideShow(pack); | |||
assertNotNull(xml.getProperties().getCoreProperties()); | |||
assertNotNull(xml.getProperties().getExtendedProperties()); | |||
assertNotNull(xml.getProperties().getCoreProperties()); | |||
assertNotNull(xml.getProperties().getExtendedProperties()); | |||
CTProperties props = xml.getProperties().getExtendedProperties().getUnderlyingProperties(); | |||
assertEquals("Microsoft Office PowerPoint", props.getApplication()); | |||
assertEquals(0, props.getCharacters()); | |||
assertEquals(0, props.getLines()); | |||
CTProperties props = xml.getProperties().getExtendedProperties().getUnderlyingProperties(); | |||
assertEquals("Microsoft Office PowerPoint", props.getApplication()); | |||
assertEquals(0, props.getCharacters()); | |||
assertEquals(0, props.getLines()); | |||
CoreProperties cprops = xml.getProperties().getCoreProperties(); | |||
assertNull(cprops.getTitle()); | |||
assertFalse(cprops.getUnderlyingProperties().getSubjectProperty().isPresent()); | |||
CoreProperties cprops = xml.getProperties().getCoreProperties(); | |||
assertNull(cprops.getTitle()); | |||
assertFalse(cprops.getUnderlyingProperties().getSubjectProperty().isPresent()); | |||
xml.close(); | |||
} | |||
xml.close(); | |||
} | |||
@Test | |||
void testMasterBackground() throws IOException { |
@@ -42,9 +42,9 @@ import org.junit.jupiter.api.Test; | |||
class TestXSLFPowerPointExtractor { | |||
private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); | |||
/** | |||
* Get text out of the simple file | |||
*/ | |||
/** | |||
* Get text out of the simple file | |||
*/ | |||
@Test | |||
void testGetSimpleText() throws IOException { | |||
try (XMLSlideShow xmlA = openPPTX("sample.pptx"); | |||
@@ -155,7 +155,7 @@ class TestXSLFPowerPointExtractor { | |||
text = extractor.getText(); | |||
assertEquals("\n1\n\n2\n", text); | |||
} | |||
} | |||
} | |||
@Test | |||
void testGetComments() throws IOException { | |||
@@ -176,8 +176,8 @@ class TestXSLFPowerPointExtractor { | |||
} | |||
@Test | |||
void testGetMasterText() throws Exception { | |||
try (XMLSlideShow xml = openPPTX("WithMaster.pptx"); | |||
void testGetMasterText() throws Exception { | |||
try (XMLSlideShow xml = openPPTX("WithMaster.pptx"); | |||
SlideShowExtractor<XSLFShape, XSLFTextParagraph> extractor = new SlideShowExtractor<>(xml)) { | |||
extractor.setSlidesByDefault(true); | |||
extractor.setNotesByDefault(false); | |||
@@ -210,10 +210,10 @@ class TestXSLFPowerPointExtractor { | |||
"This text comes from the Master Slide\n"; | |||
assertEquals(wholeText, text); | |||
} | |||
} | |||
} | |||
@Test | |||
void testTable() throws Exception { | |||
@Test | |||
void testTable() throws Exception { | |||
try (XMLSlideShow xml = openPPTX("present1.pptx"); | |||
SlideShowExtractor<XSLFShape, XSLFTextParagraph> extractor = new SlideShowExtractor<>(xml)) { | |||
@@ -147,22 +147,22 @@ class TestXSLFChart { | |||
pptx.close(); | |||
} | |||
private void fillChartData(XSLFChart chart, XDDFChartData data) { | |||
final int numOfPoints = 3; | |||
private void fillChartData(XSLFChart chart, XDDFChartData data) { | |||
final int numOfPoints = 3; | |||
final String[] categories = {"First", "Second", "Third"}; | |||
final Integer[] values = {1, 3, 4}; | |||
final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0)); | |||
final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1)); | |||
final XDDFChartData.Series series = data.getSeries(0); | |||
final XDDFDataSource<?> categoryData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange); | |||
final XDDFChartData.Series series = data.getSeries(0); | |||
final XDDFDataSource<?> categoryData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange); | |||
final XDDFNumericalDataSource<Integer> valuesData = XDDFDataSourcesFactory.fromArray(values, valuesDataRange); | |||
series.replaceData(categoryData, valuesData); | |||
final String title = "Apache POI"; | |||
series.setTitle(title, chart.setSheetTitle(title, 0)); | |||
chart.plot(data); | |||
} | |||
} | |||
private XSLFChart findChart(XSLFSlide slide) { | |||
// find chart in the slide | |||
@@ -188,147 +188,147 @@ class TestXSLFChart { | |||
assertEquals(1, data.size()); | |||
XDDFChartData firstSeries = data.get(0); | |||
assertNotNull(firstSeries); | |||
if (firstSeries instanceof XDDFScatterChartData) { | |||
assertNotNull(firstSeries); | |||
if (firstSeries instanceof XDDFScatterChartData) { | |||
assertNull(firstSeries.getCategoryAxis()); | |||
assertEquals(2, firstSeries.getValueAxes().size()); | |||
checkAxisOperations(firstSeries.getValueAxes().get(0)); | |||
checkAxisOperations(firstSeries.getValueAxes().get(1)); | |||
} else if (!(firstSeries instanceof XDDFPieChartData)) { | |||
assertNotNull(firstSeries.getCategoryAxis()); | |||
assertEquals(1, firstSeries.getValueAxes().size()); | |||
checkAxisOperations(firstSeries.getValueAxes().get(0)); | |||
} | |||
} else if (!(firstSeries instanceof XDDFPieChartData)) { | |||
assertNotNull(firstSeries.getCategoryAxis()); | |||
assertEquals(1, firstSeries.getValueAxes().size()); | |||
checkAxisOperations(firstSeries.getValueAxes().get(0)); | |||
} | |||
return data; | |||
} | |||
private void checkLegendOperations(XSLFChart chart) { | |||
XDDFChartLegend legend = chart.getOrAddLegend(); | |||
private void checkLegendOperations(XSLFChart chart) { | |||
XDDFChartLegend legend = chart.getOrAddLegend(); | |||
assertFalse(legend.isOverlay()); | |||
legend.setOverlay(true); | |||
legend.setOverlay(true); | |||
assertTrue(legend.isOverlay()); | |||
legend.setPosition(LegendPosition.TOP_RIGHT); | |||
assertEquals(LegendPosition.TOP_RIGHT, legend.getPosition()); | |||
XDDFManualLayout layout = legend.getOrAddManualLayout(); | |||
assertNotNull(layout.getTarget()); | |||
assertNotNull(layout.getXMode()); | |||
assertNotNull(layout.getYMode()); | |||
assertNotNull(layout.getHeightMode()); | |||
assertNotNull(layout.getWidthMode()); | |||
/* | |||
* According to interface, 0.0 should be returned for | |||
* uninitialized double properties. | |||
*/ | |||
legend.setPosition(LegendPosition.TOP_RIGHT); | |||
assertEquals(LegendPosition.TOP_RIGHT, legend.getPosition()); | |||
XDDFManualLayout layout = legend.getOrAddManualLayout(); | |||
assertNotNull(layout.getTarget()); | |||
assertNotNull(layout.getXMode()); | |||
assertNotNull(layout.getYMode()); | |||
assertNotNull(layout.getHeightMode()); | |||
assertNotNull(layout.getWidthMode()); | |||
/* | |||
* According to interface, 0.0 should be returned for | |||
* uninitialized double properties. | |||
*/ | |||
assertEquals(0.0, layout.getX(), 0.0); | |||
assertEquals(0.0, layout.getY(), 0.0); | |||
assertEquals(0.0, layout.getWidthRatio(), 0.0); | |||
assertEquals(0.0, layout.getHeightRatio(), 0.0); | |||
final double newRatio = 1.1; | |||
final double newCoordinate = 0.3; | |||
final LayoutMode nonDefaultMode = LayoutMode.FACTOR; | |||
final LayoutTarget nonDefaultTarget = LayoutTarget.OUTER; | |||
final double newRatio = 1.1; | |||
final double newCoordinate = 0.3; | |||
final LayoutMode nonDefaultMode = LayoutMode.FACTOR; | |||
final LayoutTarget nonDefaultTarget = LayoutTarget.OUTER; | |||
layout.setWidthRatio(newRatio); | |||
layout.setWidthRatio(newRatio); | |||
assertEquals(layout.getWidthRatio(), newRatio, 0.0); | |||
layout.setHeightRatio(newRatio); | |||
layout.setHeightRatio(newRatio); | |||
assertEquals(layout.getHeightRatio(), newRatio, 0.0); | |||
layout.setX(newCoordinate); | |||
layout.setX(newCoordinate); | |||
assertEquals(layout.getX(), newCoordinate, 0.0); | |||
layout.setY(newCoordinate); | |||
layout.setY(newCoordinate); | |||
assertEquals(layout.getY(), newCoordinate, 0.0); | |||
layout.setXMode(nonDefaultMode); | |||
layout.setXMode(nonDefaultMode); | |||
assertSame(layout.getXMode(), nonDefaultMode); | |||
layout.setYMode(nonDefaultMode); | |||
layout.setYMode(nonDefaultMode); | |||
assertSame(layout.getYMode(), nonDefaultMode); | |||
layout.setWidthMode(nonDefaultMode); | |||
layout.setWidthMode(nonDefaultMode); | |||
assertSame(layout.getWidthMode(), nonDefaultMode); | |||
layout.setHeightMode(nonDefaultMode); | |||
layout.setHeightMode(nonDefaultMode); | |||
assertSame(layout.getHeightMode(), nonDefaultMode); | |||
layout.setTarget(nonDefaultTarget); | |||
layout.setTarget(nonDefaultTarget); | |||
assertSame(layout.getTarget(), nonDefaultTarget); | |||
} | |||
} | |||
private void checkAxisOperations(XDDFValueAxis axis) { | |||
axis.setCrossBetween(AxisCrossBetween.MIDPOINT_CATEGORY); | |||
assertEquals(AxisCrossBetween.MIDPOINT_CATEGORY, axis.getCrossBetween()); | |||
private void checkAxisOperations(XDDFValueAxis axis) { | |||
axis.setCrossBetween(AxisCrossBetween.MIDPOINT_CATEGORY); | |||
assertEquals(AxisCrossBetween.MIDPOINT_CATEGORY, axis.getCrossBetween()); | |||
axis.setCrosses(AxisCrosses.AUTO_ZERO); | |||
assertEquals(AxisCrosses.AUTO_ZERO, axis.getCrosses()); | |||
axis.setCrosses(AxisCrosses.AUTO_ZERO); | |||
assertEquals(AxisCrosses.AUTO_ZERO, axis.getCrosses()); | |||
final String numberFormat = "General"; | |||
axis.setNumberFormat(numberFormat); | |||
assertEquals(numberFormat, axis.getNumberFormat()); | |||
final String numberFormat = "General"; | |||
axis.setNumberFormat(numberFormat); | |||
assertEquals(numberFormat, axis.getNumberFormat()); | |||
axis.setPosition(AxisPosition.BOTTOM); | |||
assertEquals(AxisPosition.BOTTOM, axis.getPosition()); | |||
axis.setPosition(AxisPosition.BOTTOM); | |||
assertEquals(AxisPosition.BOTTOM, axis.getPosition()); | |||
axis.setMajorTickMark(AxisTickMark.NONE); | |||
assertEquals(AxisTickMark.NONE, axis.getMajorTickMark()); | |||
axis.setMajorTickMark(AxisTickMark.NONE); | |||
assertEquals(AxisTickMark.NONE, axis.getMajorTickMark()); | |||
axis.setMajorTickMark(AxisTickMark.IN); | |||
assertEquals(AxisTickMark.IN, axis.getMajorTickMark()); | |||
axis.setMajorTickMark(AxisTickMark.IN); | |||
assertEquals(AxisTickMark.IN, axis.getMajorTickMark()); | |||
axis.setMajorTickMark(AxisTickMark.OUT); | |||
assertEquals(AxisTickMark.OUT, axis.getMajorTickMark()); | |||
axis.setMajorTickMark(AxisTickMark.OUT); | |||
assertEquals(AxisTickMark.OUT, axis.getMajorTickMark()); | |||
axis.setMajorTickMark(AxisTickMark.CROSS); | |||
assertEquals(AxisTickMark.CROSS, axis.getMajorTickMark()); | |||
axis.setMajorTickMark(AxisTickMark.CROSS); | |||
assertEquals(AxisTickMark.CROSS, axis.getMajorTickMark()); | |||
axis.setMinorTickMark(AxisTickMark.NONE); | |||
assertEquals(AxisTickMark.NONE, axis.getMinorTickMark()); | |||
axis.setMinorTickMark(AxisTickMark.NONE); | |||
assertEquals(AxisTickMark.NONE, axis.getMinorTickMark()); | |||
axis.setMinorTickMark(AxisTickMark.IN); | |||
assertEquals(AxisTickMark.IN, axis.getMinorTickMark()); | |||
axis.setMinorTickMark(AxisTickMark.IN); | |||
assertEquals(AxisTickMark.IN, axis.getMinorTickMark()); | |||
axis.setMinorTickMark(AxisTickMark.OUT); | |||
assertEquals(AxisTickMark.OUT, axis.getMinorTickMark()); | |||
axis.setMinorTickMark(AxisTickMark.OUT); | |||
assertEquals(AxisTickMark.OUT, axis.getMinorTickMark()); | |||
axis.setMinorTickMark(AxisTickMark.CROSS); | |||
assertEquals(AxisTickMark.CROSS, axis.getMinorTickMark()); | |||
axis.setMinorTickMark(AxisTickMark.CROSS); | |||
assertEquals(AxisTickMark.CROSS, axis.getMinorTickMark()); | |||
axis.setVisible(true); | |||
assertTrue(axis.isVisible()); | |||
axis.setVisible(true); | |||
assertTrue(axis.isVisible()); | |||
axis.setVisible(false); | |||
assertFalse(axis.isVisible()); | |||
axis.setVisible(false); | |||
assertFalse(axis.isVisible()); | |||
final double EPSILON = 1E-7; | |||
axis.setLogBase(Math.E); | |||
assertTrue(Math.abs(axis.getLogBase() - Math.E) < EPSILON); | |||
final double EPSILON = 1E-7; | |||
axis.setLogBase(Math.E); | |||
assertTrue(Math.abs(axis.getLogBase() - Math.E) < EPSILON); | |||
final double newValue = 10.0; | |||
final double newValue = 10.0; | |||
axis.setMinimum(newValue); | |||
assertTrue(Math.abs(axis.getMinimum() - newValue) < EPSILON); | |||
axis.setMinimum(newValue); | |||
assertTrue(Math.abs(axis.getMinimum() - newValue) < EPSILON); | |||
axis.setMaximum(newValue); | |||
assertTrue(Math.abs(axis.getMaximum() - newValue) < EPSILON); | |||
axis.setMaximum(newValue); | |||
assertTrue(Math.abs(axis.getMaximum() - newValue) < EPSILON); | |||
IllegalArgumentException iae = null; | |||
try { | |||
axis.setLogBase(0.0); | |||
} catch (IllegalArgumentException e) { | |||
iae = e; | |||
} | |||
assertNotNull(iae); | |||
IllegalArgumentException iae = null; | |||
try { | |||
axis.setLogBase(0.0); | |||
} catch (IllegalArgumentException e) { | |||
iae = e; | |||
} | |||
assertNotNull(iae); | |||
iae = null; | |||
try { | |||
axis.setLogBase(30000.0); | |||
} catch (IllegalArgumentException e) { | |||
iae = e; | |||
} | |||
assertNotNull(iae); | |||
} | |||
iae = null; | |||
try { | |||
axis.setLogBase(30000.0); | |||
} catch (IllegalArgumentException e) { | |||
iae = e; | |||
} | |||
assertNotNull(iae); | |||
} | |||
} |
@@ -28,266 +28,266 @@ import static org.junit.jupiter.api.Assertions.assertFalse; | |||
import static org.junit.jupiter.api.Assertions.assertTrue; | |||
class TestSheetProtection { | |||
private XSSFWorkbook workbook; | |||
private XSSFSheet sheet; | |||
private XSSFWorkbook workbook; | |||
private XSSFSheet sheet; | |||
@BeforeEach | |||
void setUp() { | |||
workbook = XSSFTestDataSamples.openSampleWorkbook("sheetProtection_not_protected.xlsx"); | |||
sheet = workbook.getSheetAt(0); | |||
} | |||
@BeforeEach | |||
void setUp() { | |||
workbook = XSSFTestDataSamples.openSampleWorkbook("sheetProtection_not_protected.xlsx"); | |||
sheet = workbook.getSheetAt(0); | |||
} | |||
@AfterEach | |||
void tearDown() throws IOException { | |||
workbook.close(); | |||
} | |||
@AfterEach | |||
void tearDown() throws IOException { | |||
workbook.close(); | |||
} | |||
@Test | |||
void testShouldReadWorkbookProtection() throws IOException { | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
assertFalse(sheet.isSortLocked()); | |||
assertFalse(sheet.isObjectsLocked()); | |||
assertFalse(sheet.isScenariosLocked()); | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
assertFalse(sheet.isSheetLocked()); | |||
@Test | |||
void testShouldReadWorkbookProtection() throws IOException { | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
assertFalse(sheet.isSortLocked()); | |||
assertFalse(sheet.isObjectsLocked()); | |||
assertFalse(sheet.isScenariosLocked()); | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
assertFalse(sheet.isSheetLocked()); | |||
try (XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("sheetProtection_allLocked.xlsx")) { | |||
sheet = workbook.getSheetAt(0); | |||
try (XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("sheetProtection_allLocked.xlsx")) { | |||
sheet = workbook.getSheetAt(0); | |||
assertTrue(sheet.isAutoFilterLocked()); | |||
assertTrue(sheet.isDeleteColumnsLocked()); | |||
assertTrue(sheet.isDeleteRowsLocked()); | |||
assertTrue(sheet.isFormatCellsLocked()); | |||
assertTrue(sheet.isFormatColumnsLocked()); | |||
assertTrue(sheet.isFormatRowsLocked()); | |||
assertTrue(sheet.isInsertColumnsLocked()); | |||
assertTrue(sheet.isInsertHyperlinksLocked()); | |||
assertTrue(sheet.isInsertRowsLocked()); | |||
assertTrue(sheet.isPivotTablesLocked()); | |||
assertTrue(sheet.isSortLocked()); | |||
assertTrue(sheet.isObjectsLocked()); | |||
assertTrue(sheet.isScenariosLocked()); | |||
assertTrue(sheet.isSelectLockedCellsLocked()); | |||
assertTrue(sheet.isSelectUnlockedCellsLocked()); | |||
assertTrue(sheet.isSheetLocked()); | |||
} | |||
} | |||
assertTrue(sheet.isAutoFilterLocked()); | |||
assertTrue(sheet.isDeleteColumnsLocked()); | |||
assertTrue(sheet.isDeleteRowsLocked()); | |||
assertTrue(sheet.isFormatCellsLocked()); | |||
assertTrue(sheet.isFormatColumnsLocked()); | |||
assertTrue(sheet.isFormatRowsLocked()); | |||
assertTrue(sheet.isInsertColumnsLocked()); | |||
assertTrue(sheet.isInsertHyperlinksLocked()); | |||
assertTrue(sheet.isInsertRowsLocked()); | |||
assertTrue(sheet.isPivotTablesLocked()); | |||
assertTrue(sheet.isSortLocked()); | |||
assertTrue(sheet.isObjectsLocked()); | |||
assertTrue(sheet.isScenariosLocked()); | |||
assertTrue(sheet.isSelectLockedCellsLocked()); | |||
assertTrue(sheet.isSelectUnlockedCellsLocked()); | |||
assertTrue(sheet.isSheetLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteAutoFilter() { | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
sheet.lockAutoFilter(true); | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isAutoFilterLocked()); | |||
sheet.lockAutoFilter(false); | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
} | |||
@Test | |||
void testWriteAutoFilter() { | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
sheet.lockAutoFilter(true); | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isAutoFilterLocked()); | |||
sheet.lockAutoFilter(false); | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
} | |||
@Test | |||
void testWriteDeleteColumns() { | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
sheet.lockDeleteColumns(true); | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isDeleteColumnsLocked()); | |||
sheet.lockDeleteColumns(false); | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
} | |||
@Test | |||
void testWriteDeleteColumns() { | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
sheet.lockDeleteColumns(true); | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isDeleteColumnsLocked()); | |||
sheet.lockDeleteColumns(false); | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
} | |||
@Test | |||
void testWriteDeleteRows() { | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
sheet.lockDeleteRows(true); | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isDeleteRowsLocked()); | |||
@Test | |||
void testWriteDeleteRows() { | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
sheet.lockDeleteRows(true); | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isDeleteRowsLocked()); | |||
sheet.lockDeleteRows(false); | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteFormatCells() { | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
sheet.lockFormatCells(true); | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isFormatCellsLocked()); | |||
@Test | |||
void testWriteFormatCells() { | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
sheet.lockFormatCells(true); | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isFormatCellsLocked()); | |||
sheet.lockFormatCells(false); | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteFormatColumns() { | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
sheet.lockFormatColumns(true); | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isFormatColumnsLocked()); | |||
@Test | |||
void testWriteFormatColumns() { | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
sheet.lockFormatColumns(true); | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isFormatColumnsLocked()); | |||
sheet.lockFormatColumns(false); | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteFormatRows() { | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
sheet.lockFormatRows(true); | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isFormatRowsLocked()); | |||
@Test | |||
void testWriteFormatRows() { | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
sheet.lockFormatRows(true); | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isFormatRowsLocked()); | |||
sheet.lockFormatRows(false); | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteInsertColumns() { | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
sheet.lockInsertColumns(true); | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isInsertColumnsLocked()); | |||
@Test | |||
void testWriteInsertColumns() { | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
sheet.lockInsertColumns(true); | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isInsertColumnsLocked()); | |||
sheet.lockInsertColumns(false); | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteInsertHyperlinks() { | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
sheet.lockInsertHyperlinks(true); | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isInsertHyperlinksLocked()); | |||
@Test | |||
void testWriteInsertHyperlinks() { | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
sheet.lockInsertHyperlinks(true); | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isInsertHyperlinksLocked()); | |||
sheet.lockInsertHyperlinks(false); | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteInsertRows() { | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
sheet.lockInsertRows(true); | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isInsertRowsLocked()); | |||
@Test | |||
void testWriteInsertRows() { | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
sheet.lockInsertRows(true); | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isInsertRowsLocked()); | |||
sheet.lockInsertRows(false); | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWritePivotTables() { | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
sheet.lockPivotTables(true); | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isPivotTablesLocked()); | |||
@Test | |||
void testWritePivotTables() { | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
sheet.lockPivotTables(true); | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isPivotTablesLocked()); | |||
sheet.lockPivotTables(false); | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteSort() { | |||
assertFalse(sheet.isSortLocked()); | |||
sheet.lockSort(true); | |||
assertFalse(sheet.isSortLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isSortLocked()); | |||
@Test | |||
void testWriteSort() { | |||
assertFalse(sheet.isSortLocked()); | |||
sheet.lockSort(true); | |||
assertFalse(sheet.isSortLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isSortLocked()); | |||
sheet.lockSort(false); | |||
assertFalse(sheet.isSortLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteObjects() { | |||
assertFalse(sheet.isObjectsLocked()); | |||
sheet.lockObjects(true); | |||
assertFalse(sheet.isObjectsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isObjectsLocked()); | |||
@Test | |||
void testWriteObjects() { | |||
assertFalse(sheet.isObjectsLocked()); | |||
sheet.lockObjects(true); | |||
assertFalse(sheet.isObjectsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isObjectsLocked()); | |||
sheet.lockObjects(false); | |||
assertFalse(sheet.isObjectsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteScenarios() { | |||
assertFalse(sheet.isScenariosLocked()); | |||
sheet.lockScenarios(true); | |||
assertFalse(sheet.isScenariosLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isScenariosLocked()); | |||
@Test | |||
void testWriteScenarios() { | |||
assertFalse(sheet.isScenariosLocked()); | |||
sheet.lockScenarios(true); | |||
assertFalse(sheet.isScenariosLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isScenariosLocked()); | |||
sheet.lockScenarios(false); | |||
assertFalse(sheet.isScenariosLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteSelectLockedCells() { | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
sheet.lockSelectLockedCells(true); | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isSelectLockedCellsLocked()); | |||
@Test | |||
void testWriteSelectLockedCells() { | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
sheet.lockSelectLockedCells(true); | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isSelectLockedCellsLocked()); | |||
sheet.lockSelectLockedCells(false); | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteSelectUnlockedCells() { | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
sheet.lockSelectUnlockedCells(true); | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isSelectUnlockedCellsLocked()); | |||
@Test | |||
void testWriteSelectUnlockedCells() { | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
sheet.lockSelectUnlockedCells(true); | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
sheet.enableLocking(); | |||
assertTrue(sheet.isSelectUnlockedCellsLocked()); | |||
sheet.lockSelectUnlockedCells(false); | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
} | |||
} | |||
@Test | |||
void testWriteSelectEnableLocking() throws IOException { | |||
try (XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("sheetProtection_allLocked.xlsx")) { | |||
sheet = workbook.getSheetAt(0); | |||
@Test | |||
void testWriteSelectEnableLocking() throws IOException { | |||
try (XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("sheetProtection_allLocked.xlsx")) { | |||
sheet = workbook.getSheetAt(0); | |||
assertTrue(sheet.isAutoFilterLocked()); | |||
assertTrue(sheet.isDeleteColumnsLocked()); | |||
assertTrue(sheet.isDeleteRowsLocked()); | |||
assertTrue(sheet.isFormatCellsLocked()); | |||
assertTrue(sheet.isFormatColumnsLocked()); | |||
assertTrue(sheet.isFormatRowsLocked()); | |||
assertTrue(sheet.isInsertColumnsLocked()); | |||
assertTrue(sheet.isInsertHyperlinksLocked()); | |||
assertTrue(sheet.isInsertRowsLocked()); | |||
assertTrue(sheet.isPivotTablesLocked()); | |||
assertTrue(sheet.isSortLocked()); | |||
assertTrue(sheet.isObjectsLocked()); | |||
assertTrue(sheet.isScenariosLocked()); | |||
assertTrue(sheet.isSelectLockedCellsLocked()); | |||
assertTrue(sheet.isSelectUnlockedCellsLocked()); | |||
assertTrue(sheet.isSheetLocked()); | |||
assertTrue(sheet.isAutoFilterLocked()); | |||
assertTrue(sheet.isDeleteColumnsLocked()); | |||
assertTrue(sheet.isDeleteRowsLocked()); | |||
assertTrue(sheet.isFormatCellsLocked()); | |||
assertTrue(sheet.isFormatColumnsLocked()); | |||
assertTrue(sheet.isFormatRowsLocked()); | |||
assertTrue(sheet.isInsertColumnsLocked()); | |||
assertTrue(sheet.isInsertHyperlinksLocked()); | |||
assertTrue(sheet.isInsertRowsLocked()); | |||
assertTrue(sheet.isPivotTablesLocked()); | |||
assertTrue(sheet.isSortLocked()); | |||
assertTrue(sheet.isObjectsLocked()); | |||
assertTrue(sheet.isScenariosLocked()); | |||
assertTrue(sheet.isSelectLockedCellsLocked()); | |||
assertTrue(sheet.isSelectUnlockedCellsLocked()); | |||
assertTrue(sheet.isSheetLocked()); | |||
sheet.disableLocking(); | |||
sheet.disableLocking(); | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
assertFalse(sheet.isSortLocked()); | |||
assertFalse(sheet.isObjectsLocked()); | |||
assertFalse(sheet.isScenariosLocked()); | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
assertFalse(sheet.isSheetLocked()); | |||
} | |||
} | |||
assertFalse(sheet.isAutoFilterLocked()); | |||
assertFalse(sheet.isDeleteColumnsLocked()); | |||
assertFalse(sheet.isDeleteRowsLocked()); | |||
assertFalse(sheet.isFormatCellsLocked()); | |||
assertFalse(sheet.isFormatColumnsLocked()); | |||
assertFalse(sheet.isFormatRowsLocked()); | |||
assertFalse(sheet.isInsertColumnsLocked()); | |||
assertFalse(sheet.isInsertHyperlinksLocked()); | |||
assertFalse(sheet.isInsertRowsLocked()); | |||
assertFalse(sheet.isPivotTablesLocked()); | |||
assertFalse(sheet.isSortLocked()); | |||
assertFalse(sheet.isObjectsLocked()); | |||
assertFalse(sheet.isScenariosLocked()); | |||
assertFalse(sheet.isSelectLockedCellsLocked()); | |||
assertFalse(sheet.isSelectUnlockedCellsLocked()); | |||
assertFalse(sheet.isSheetLocked()); | |||
} | |||
} | |||
} |
@@ -42,7 +42,7 @@ public final class TestReadOnlySharedStringsTable { | |||
@Test | |||
void testParse() throws Exception { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("SampleSS.xlsx"))) { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("SampleSS.xlsx"))) { | |||
List<PackagePart> parts = pkg.getPartsByName(Pattern.compile("/xl/sharedStrings.xml")); | |||
assertEquals(1, parts.size()); | |||
@@ -60,11 +60,11 @@ public final class TestReadOnlySharedStringsTable { | |||
assertEquals(i1.getString(), i2.getString()); | |||
} | |||
} | |||
} | |||
} | |||
//51519 | |||
//51519 | |||
@Test | |||
void testPhoneticRuns() throws Exception { | |||
void testPhoneticRuns() throws Exception { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("51519.xlsx"))) { | |||
List < PackagePart > parts = pkg.getPartsByName(Pattern.compile("/xl/sharedStrings.xml")); | |||
assertEquals(1, parts.size()); |
@@ -61,7 +61,7 @@ public final class TestXSSFReader { | |||
@Test | |||
void testGetBits() throws Exception { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("SampleSS.xlsx"))) { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("SampleSS.xlsx"))) { | |||
XSSFReader r = new XSSFReader(pkg); | |||
@@ -72,11 +72,11 @@ public final class TestXSSFReader { | |||
assertNotNull(r.getSharedStringsTable()); | |||
assertNotNull(r.getStylesTable()); | |||
} | |||
} | |||
} | |||
@Test | |||
void testStyles() throws Exception { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("SampleSS.xlsx"))) { | |||
void testStyles() throws Exception { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("SampleSS.xlsx"))) { | |||
XSSFReader r = new XSSFReader(pkg); | |||
@@ -90,10 +90,10 @@ public final class TestXSSFReader { | |||
assertNotNull(r.getStylesData()); | |||
assertNotNull(r.getThemesData()); | |||
} | |||
} | |||
} | |||
@Test | |||
void testStrings() throws Exception { | |||
void testStrings() throws Exception { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("SampleSS.xlsx"))) { | |||
XSSFReader r = new XSSFReader(pkg); | |||
@@ -101,10 +101,10 @@ public final class TestXSSFReader { | |||
assertEquals(11, r.getSharedStringsTable().getSharedStringItems().size()); | |||
assertEquals("Test spreadsheet", r.getSharedStringsTable().getItemAt(0).toString()); | |||
} | |||
} | |||
} | |||
@Test | |||
void testSheets() throws Exception { | |||
void testSheets() throws Exception { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("SampleSS.xlsx"))) { | |||
XSSFReader r = new XSSFReader(pkg); | |||
@@ -131,14 +131,14 @@ public final class TestXSSFReader { | |||
} | |||
assertEquals(3, count); | |||
} | |||
} | |||
} | |||
/** | |||
* Check that the sheet iterator returns sheets in the logical order | |||
* (as they are defined in the workbook.xml) | |||
*/ | |||
/** | |||
* Check that the sheet iterator returns sheets in the logical order | |||
* (as they are defined in the workbook.xml) | |||
*/ | |||
@Test | |||
void testOrderOfSheets() throws Exception { | |||
void testOrderOfSheets() throws Exception { | |||
try (OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("reordered_sheets.xlsx"))) { | |||
XSSFReader r = new XSSFReader(pkg); | |||
@@ -157,10 +157,10 @@ public final class TestXSSFReader { | |||
} | |||
assertEquals(4, count); | |||
} | |||
} | |||
} | |||
@Test | |||
void testComments() throws Exception { | |||
void testComments() throws Exception { | |||
try (OPCPackage pkg = XSSFTestDataSamples.openSamplePackage("comments.xlsx")) { | |||
XSSFReader r = new XSSFReader(pkg); | |||
XSSFReader.SheetIterator it = (XSSFReader.SheetIterator) r.getSheetsData(); | |||
@@ -182,7 +182,7 @@ public final class TestXSSFReader { | |||
} | |||
assertEquals(3, count); | |||
} | |||
} | |||
} | |||
/** | |||
* Iterating over a workbook with chart sheets in it, using the |
@@ -71,10 +71,10 @@ class TestXSSFBEventBasedExcelExtractor { | |||
"Nunc\t999\n"; | |||
String CHUNK2 = | |||
"The quick brown fox jumps over the lazy dog\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n"; | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n"; | |||
assertEquals( | |||
CHUNK1 + | |||
"at\t4995\n" + |
@@ -39,92 +39,92 @@ import org.junit.jupiter.api.Test; | |||
* Tests for {@link XSSFEventBasedExcelExtractor} | |||
*/ | |||
class TestXSSFEventBasedExcelExtractor { | |||
protected XSSFEventBasedExcelExtractor getExtractor(String sampleName) throws Exception { | |||
protected XSSFEventBasedExcelExtractor getExtractor(String sampleName) throws Exception { | |||
return new XSSFEventBasedExcelExtractor(XSSFTestDataSamples. | |||
openSamplePackage(sampleName)); | |||
} | |||
/** | |||
* Get text out of the simple file | |||
*/ | |||
@Test | |||
void testGetSimpleText() throws Exception { | |||
// a very simple file | |||
XSSFEventBasedExcelExtractor extractor = getExtractor("sample.xlsx"); | |||
extractor.getText(); | |||
String text = extractor.getText(); | |||
assertTrue(text.length() > 0); | |||
// Check sheet names | |||
assertStartsWith(text, "Sheet1"); | |||
assertEndsWith(text, "Sheet3\n"); | |||
// Now without, will have text | |||
extractor.setIncludeSheetNames(false); | |||
text = extractor.getText(); | |||
String CHUNK1 = | |||
"Lorem\t111\n" + | |||
"ipsum\t222\n" + | |||
"dolor\t333\n" + | |||
"sit\t444\n" + | |||
"amet\t555\n" + | |||
"consectetuer\t666\n" + | |||
"adipiscing\t777\n" + | |||
"elit\t888\n" + | |||
"Nunc\t999\n"; | |||
String CHUNK2 = | |||
"The quick brown fox jumps over the lazy dog\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n"; | |||
assertEquals( | |||
CHUNK1 + | |||
"at\t4995\n" + | |||
CHUNK2 | |||
, text); | |||
// Now get formulas not their values | |||
extractor.setFormulasNotResults(true); | |||
text = extractor.getText(); | |||
assertEquals( | |||
CHUNK1 + | |||
"at\tSUM(B1:B9)\n" + | |||
CHUNK2, text); | |||
// With sheet names too | |||
extractor.setIncludeSheetNames(true); | |||
text = extractor.getText(); | |||
assertEquals( | |||
"Sheet1\n" + | |||
CHUNK1 + | |||
"at\tSUM(B1:B9)\n" + | |||
"rich test\n" + | |||
CHUNK2 + | |||
"Sheet3\n" | |||
, text); | |||
extractor.close(); | |||
} | |||
} | |||
/** | |||
* Get text out of the simple file | |||
*/ | |||
@Test | |||
void testGetComplexText() throws Exception { | |||
// A fairly complex file | |||
XSSFEventBasedExcelExtractor extractor = getExtractor("AverageTaxRates.xlsx"); | |||
extractor.getText(); | |||
void testGetSimpleText() throws Exception { | |||
// a very simple file | |||
XSSFEventBasedExcelExtractor extractor = getExtractor("sample.xlsx"); | |||
extractor.getText(); | |||
String text = extractor.getText(); | |||
assertTrue(text.length() > 0); | |||
// Check sheet names | |||
assertStartsWith(text, "Sheet1"); | |||
assertEndsWith(text, "Sheet3\n"); | |||
// Now without, will have text | |||
extractor.setIncludeSheetNames(false); | |||
text = extractor.getText(); | |||
String CHUNK1 = | |||
"Lorem\t111\n" + | |||
"ipsum\t222\n" + | |||
"dolor\t333\n" + | |||
"sit\t444\n" + | |||
"amet\t555\n" + | |||
"consectetuer\t666\n" + | |||
"adipiscing\t777\n" + | |||
"elit\t888\n" + | |||
"Nunc\t999\n"; | |||
String CHUNK2 = | |||
"The quick brown fox jumps over the lazy dog\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n"; | |||
assertEquals( | |||
CHUNK1 + | |||
"at\t4995\n" + | |||
CHUNK2 | |||
, text); | |||
// Now get formulas not their values | |||
extractor.setFormulasNotResults(true); | |||
text = extractor.getText(); | |||
assertEquals( | |||
CHUNK1 + | |||
"at\tSUM(B1:B9)\n" + | |||
CHUNK2, text); | |||
// With sheet names too | |||
extractor.setIncludeSheetNames(true); | |||
text = extractor.getText(); | |||
assertEquals( | |||
"Sheet1\n" + | |||
CHUNK1 + | |||
"at\tSUM(B1:B9)\n" + | |||
"rich test\n" + | |||
CHUNK2 + | |||
"Sheet3\n" | |||
, text); | |||
extractor.close(); | |||
} | |||
String text = extractor.getText(); | |||
assertTrue(text.length() > 0); | |||
@Test | |||
void testGetComplexText() throws Exception { | |||
// A fairly complex file | |||
XSSFEventBasedExcelExtractor extractor = getExtractor("AverageTaxRates.xlsx"); | |||
extractor.getText(); | |||
String text = extractor.getText(); | |||
assertTrue(text.length() > 0); | |||
// Might not have all formatting it should do! | |||
assertStartsWith(text, | |||
"Avgtxfull\n" + | |||
"(iii) AVERAGE TAX RATES ON ANNUAL" | |||
); | |||
// Might not have all formatting it should do! | |||
assertStartsWith(text, | |||
"Avgtxfull\n" + | |||
"(iii) AVERAGE TAX RATES ON ANNUAL" | |||
); | |||
extractor.close(); | |||
} | |||
extractor.close(); | |||
} | |||
@Test | |||
void testInlineStrings() throws Exception { | |||
@@ -141,44 +141,44 @@ class TestXSSFEventBasedExcelExtractor { | |||
assertContains(text, "Long Text"); | |||
// Inline Strings | |||
assertContains(text, "1st Inline String"); | |||
assertContains(text, "And More"); | |||
assertContains(text, "1st Inline String"); | |||
assertContains(text, "And More"); | |||
// Formulas | |||
assertContains(text, "A2"); | |||
assertContains(text, "A5-A$2"); | |||
assertContains(text, "A2"); | |||
assertContains(text, "A5-A$2"); | |||
extractor.close(); | |||
} | |||
/** | |||
* Test that we return pretty much the same as | |||
* ExcelExtractor does, when we're both passed | |||
* the same file, just saved as xls and xlsx | |||
*/ | |||
/** | |||
* Test that we return pretty much the same as | |||
* ExcelExtractor does, when we're both passed | |||
* the same file, just saved as xls and xlsx | |||
*/ | |||
@Test | |||
void testComparedToOLE2() throws Exception { | |||
// A fairly simple file - ooxml | |||
XSSFEventBasedExcelExtractor ooxmlExtractor = getExtractor("SampleSS.xlsx"); | |||
// A fairly simple file - ooxml | |||
XSSFEventBasedExcelExtractor ooxmlExtractor = getExtractor("SampleSS.xlsx"); | |||
ExcelExtractor ole2Extractor = | |||
new ExcelExtractor(HSSFTestDataSamples.openSampleWorkbook("SampleSS.xls")); | |||
ExcelExtractor ole2Extractor = | |||
new ExcelExtractor(HSSFTestDataSamples.openSampleWorkbook("SampleSS.xls")); | |||
POITextExtractor[] extractors = | |||
new POITextExtractor[] { ooxmlExtractor, ole2Extractor }; | |||
for (POITextExtractor extractor : extractors) { | |||
POITextExtractor[] extractors = | |||
new POITextExtractor[] { ooxmlExtractor, ole2Extractor }; | |||
for (POITextExtractor extractor : extractors) { | |||
String text = extractor.getText().replaceAll("[\r\t]", ""); | |||
assertStartsWith(text, "First Sheet\nTest spreadsheet\n2nd row2nd row 2nd column\n"); | |||
Pattern pattern = Pattern.compile(".*13(\\.0+)?\\s+Sheet3.*", Pattern.DOTALL); | |||
Matcher m = pattern.matcher(text); | |||
assertTrue(m.matches()); | |||
} | |||
assertStartsWith(text, "First Sheet\nTest spreadsheet\n2nd row2nd row 2nd column\n"); | |||
Pattern pattern = Pattern.compile(".*13(\\.0+)?\\s+Sheet3.*", Pattern.DOTALL); | |||
Matcher m = pattern.matcher(text); | |||
assertTrue(m.matches()); | |||
} | |||
ole2Extractor.close(); | |||
ooxmlExtractor.close(); | |||
} | |||
ole2Extractor.close(); | |||
ooxmlExtractor.close(); | |||
} | |||
/** Test text extraction from text box using getShapes() */ | |||
/** Test text extraction from text box using getShapes() */ | |||
@Test | |||
void testShapes() throws Exception{ | |||
@@ -320,35 +320,35 @@ class TestXSSFEventBasedExcelExtractor { | |||
} | |||
@Test | |||
void test59021() throws Exception { | |||
XSSFEventBasedExcelExtractor ex = | |||
new XSSFEventBasedExcelExtractor( | |||
XSSFTestDataSamples.openSamplePackage("59021.xlsx")); | |||
String text = ex.getText(); | |||
assertContains(text, "Abkhazia - Fixed"); | |||
assertContains(text, "10/02/2016"); | |||
ex.close(); | |||
} | |||
@Test | |||
void test51519() throws Exception { | |||
//default behavior: include phonetic runs | |||
XSSFEventBasedExcelExtractor ex = | |||
new XSSFEventBasedExcelExtractor( | |||
XSSFTestDataSamples.openSamplePackage("51519.xlsx")); | |||
String text = ex.getText(); | |||
assertContains(text, "\u65E5\u672C\u30AA\u30E9\u30AF\u30EB \u30CB\u30DB\u30F3"); | |||
ex.close(); | |||
//now try turning them off | |||
ex = | |||
new XSSFEventBasedExcelExtractor( | |||
XSSFTestDataSamples.openSamplePackage("51519.xlsx")); | |||
ex.setConcatenatePhoneticRuns(false); | |||
text = ex.getText(); | |||
assertFalse(text.contains("\u65E5\u672C\u30AA\u30E9\u30AF\u30EB \u30CB\u30DB\u30F3"), | |||
"should not be able to find appended phonetic run"); | |||
ex.close(); | |||
} | |||
void test59021() throws Exception { | |||
XSSFEventBasedExcelExtractor ex = | |||
new XSSFEventBasedExcelExtractor( | |||
XSSFTestDataSamples.openSamplePackage("59021.xlsx")); | |||
String text = ex.getText(); | |||
assertContains(text, "Abkhazia - Fixed"); | |||
assertContains(text, "10/02/2016"); | |||
ex.close(); | |||
} | |||
@Test | |||
void test51519() throws Exception { | |||
//default behavior: include phonetic runs | |||
XSSFEventBasedExcelExtractor ex = | |||
new XSSFEventBasedExcelExtractor( | |||
XSSFTestDataSamples.openSamplePackage("51519.xlsx")); | |||
String text = ex.getText(); | |||
assertContains(text, "\u65E5\u672C\u30AA\u30E9\u30AF\u30EB \u30CB\u30DB\u30F3"); | |||
ex.close(); | |||
//now try turning them off | |||
ex = | |||
new XSSFEventBasedExcelExtractor( | |||
XSSFTestDataSamples.openSamplePackage("51519.xlsx")); | |||
ex.setConcatenatePhoneticRuns(false); | |||
text = ex.getText(); | |||
assertFalse(text.contains("\u65E5\u672C\u30AA\u30E9\u30AF\u30EB \u30CB\u30DB\u30F3"), | |||
"should not be able to find appended phonetic run"); | |||
ex.close(); | |||
} | |||
} |
@@ -22,15 +22,15 @@ import org.junit.jupiter.api.AfterEach; | |||
class TestXSSFEventBasedExcelExtractorUsingFactory extends TestXSSFEventBasedExcelExtractor { | |||
@Override | |||
protected final XSSFEventBasedExcelExtractor getExtractor(String sampleName) throws Exception { | |||
ExtractorFactory.setAllThreadsPreferEventExtractors(true); | |||
return (XSSFEventBasedExcelExtractor) ExtractorFactory.createExtractor(HSSFTestDataSamples.openSampleFileStream(sampleName)); | |||
} | |||
@Override | |||
protected final XSSFEventBasedExcelExtractor getExtractor(String sampleName) throws Exception { | |||
ExtractorFactory.setAllThreadsPreferEventExtractors(true); | |||
return (XSSFEventBasedExcelExtractor) ExtractorFactory.createExtractor(HSSFTestDataSamples.openSampleFileStream(sampleName)); | |||
} | |||
@AfterEach | |||
@AfterEach | |||
void tearDown() { | |||
// reset setting to not affect other tests | |||
ExtractorFactory.setAllThreadsPreferEventExtractors(null); | |||
} | |||
// reset setting to not affect other tests | |||
ExtractorFactory.setAllThreadsPreferEventExtractors(null); | |||
} | |||
} |
@@ -41,164 +41,164 @@ import org.junit.jupiter.api.Test; | |||
* Tests for {@link XSSFExcelExtractor} | |||
*/ | |||
class TestXSSFExcelExtractor { | |||
protected XSSFExcelExtractor getExtractor(String sampleName) { | |||
return new XSSFExcelExtractor(XSSFTestDataSamples.openSampleWorkbook(sampleName)); | |||
} | |||
/** | |||
* Get text out of the simple file | |||
*/ | |||
@Test | |||
void testGetSimpleText() throws IOException { | |||
// a very simple file | |||
XSSFExcelExtractor extractor = getExtractor("sample.xlsx"); | |||
String text = extractor.getText(); | |||
assertTrue(text.length() > 0); | |||
// Check sheet names | |||
assertStartsWith(text, "Sheet1"); | |||
assertEndsWith(text, "Sheet3\n"); | |||
// Now without, will have text | |||
extractor.setIncludeSheetNames(false); | |||
text = extractor.getText(); | |||
String CHUNK1 = | |||
"Lorem\t111\n" + | |||
"ipsum\t222\n" + | |||
"dolor\t333\n" + | |||
"sit\t444\n" + | |||
"amet\t555\n" + | |||
"consectetuer\t666\n" + | |||
"adipiscing\t777\n" + | |||
"elit\t888\n" + | |||
"Nunc\t999\n"; | |||
String CHUNK2 = | |||
"The quick brown fox jumps over the lazy dog\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n"; | |||
assertEquals( | |||
CHUNK1 + | |||
"at\t4995\n" + | |||
CHUNK2 | |||
, text); | |||
// Now get formulas not their values | |||
extractor.setFormulasNotResults(true); | |||
text = extractor.getText(); | |||
assertEquals( | |||
CHUNK1 + | |||
"at\tSUM(B1:B9)\n" + | |||
CHUNK2, text); | |||
// With sheet names too | |||
extractor.setIncludeSheetNames(true); | |||
text = extractor.getText(); | |||
assertEquals( | |||
"Sheet1\n" + | |||
CHUNK1 + | |||
"at\tSUM(B1:B9)\n" + | |||
"rich test\n" + | |||
CHUNK2 + | |||
"Sheet3\n" | |||
, text); | |||
extractor.close(); | |||
} | |||
@Test | |||
void testGetComplexText() throws IOException { | |||
// A fairly complex file | |||
XSSFExcelExtractor extractor = getExtractor("AverageTaxRates.xlsx"); | |||
String text = extractor.getText(); | |||
assertTrue(text.length() > 0); | |||
// Might not have all formatting it should do! | |||
assertStartsWith(text, | |||
"Avgtxfull\n" + | |||
"\t(iii) AVERAGE TAX RATES ON ANNUAL" | |||
); | |||
extractor.close(); | |||
} | |||
/** | |||
* Test that we return pretty much the same as | |||
* ExcelExtractor does, when we're both passed | |||
* the same file, just saved as xls and xlsx | |||
*/ | |||
@Test | |||
void testComparedToOLE2() throws IOException { | |||
// A fairly simple file - ooxml | |||
XSSFExcelExtractor ooxmlExtractor = getExtractor("SampleSS.xlsx"); | |||
ExcelExtractor ole2Extractor = | |||
new ExcelExtractor(HSSFTestDataSamples.openSampleWorkbook("SampleSS.xls")); | |||
Map<String, POITextExtractor> extractors = new HashMap<>(); | |||
extractors.put("SampleSS.xlsx", ooxmlExtractor); | |||
extractors.put("SampleSS.xls", ole2Extractor); | |||
for (final Entry<String, POITextExtractor> e : extractors.entrySet()) { | |||
String filename = e.getKey(); | |||
POITextExtractor extractor = e.getValue(); | |||
String text = extractor.getText().replaceAll("[\r\t]", ""); | |||
assertStartsWith(filename, text, "First Sheet\nTest spreadsheet\n2nd row2nd row 2nd column\n"); | |||
Pattern pattern = Pattern.compile(".*13(\\.0+)?\\s+Sheet3.*", Pattern.DOTALL); | |||
Matcher m = pattern.matcher(text); | |||
assertTrue(m.matches(), filename); | |||
} | |||
ole2Extractor.close(); | |||
ooxmlExtractor.close(); | |||
} | |||
/** | |||
* From bug #45540 | |||
*/ | |||
@Test | |||
void testHeaderFooter() throws IOException { | |||
String[] files = new String[] { | |||
"45540_classic_Header.xlsx", "45540_form_Header.xlsx", | |||
"45540_classic_Footer.xlsx", "45540_form_Footer.xlsx", | |||
}; | |||
for(String sampleName : files) { | |||
XSSFExcelExtractor extractor = getExtractor(sampleName); | |||
String text = extractor.getText(); | |||
assertContains(sampleName, text, "testdoc"); | |||
assertContains(sampleName, text, "test phrase"); | |||
extractor.close(); | |||
} | |||
} | |||
/** | |||
* From bug #45544 | |||
*/ | |||
@Test | |||
void testComments() throws IOException { | |||
XSSFExcelExtractor extractor = getExtractor("45544.xlsx"); | |||
String text = extractor.getText(); | |||
// No comments there yet | |||
assertNotContained(text, "testdoc"); | |||
assertNotContained(text, "test phrase"); | |||
// Turn on comment extraction, will then be | |||
extractor.setIncludeCellComments(true); | |||
text = extractor.getText(); | |||
assertContains(text, "testdoc"); | |||
assertContains(text, "test phrase"); | |||
extractor.close(); | |||
} | |||
@Test | |||
void testInlineStrings() throws IOException { | |||
protected XSSFExcelExtractor getExtractor(String sampleName) { | |||
return new XSSFExcelExtractor(XSSFTestDataSamples.openSampleWorkbook(sampleName)); | |||
} | |||
/** | |||
* Get text out of the simple file | |||
*/ | |||
@Test | |||
void testGetSimpleText() throws IOException { | |||
// a very simple file | |||
XSSFExcelExtractor extractor = getExtractor("sample.xlsx"); | |||
String text = extractor.getText(); | |||
assertTrue(text.length() > 0); | |||
// Check sheet names | |||
assertStartsWith(text, "Sheet1"); | |||
assertEndsWith(text, "Sheet3\n"); | |||
// Now without, will have text | |||
extractor.setIncludeSheetNames(false); | |||
text = extractor.getText(); | |||
String CHUNK1 = | |||
"Lorem\t111\n" + | |||
"ipsum\t222\n" + | |||
"dolor\t333\n" + | |||
"sit\t444\n" + | |||
"amet\t555\n" + | |||
"consectetuer\t666\n" + | |||
"adipiscing\t777\n" + | |||
"elit\t888\n" + | |||
"Nunc\t999\n"; | |||
String CHUNK2 = | |||
"The quick brown fox jumps over the lazy dog\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n" + | |||
"hello, xssf hello, xssf\n"; | |||
assertEquals( | |||
CHUNK1 + | |||
"at\t4995\n" + | |||
CHUNK2 | |||
, text); | |||
// Now get formulas not their values | |||
extractor.setFormulasNotResults(true); | |||
text = extractor.getText(); | |||
assertEquals( | |||
CHUNK1 + | |||
"at\tSUM(B1:B9)\n" + | |||
CHUNK2, text); | |||
// With sheet names too | |||
extractor.setIncludeSheetNames(true); | |||
text = extractor.getText(); | |||
assertEquals( | |||
"Sheet1\n" + | |||
CHUNK1 + | |||
"at\tSUM(B1:B9)\n" + | |||
"rich test\n" + | |||
CHUNK2 + | |||
"Sheet3\n" | |||
, text); | |||
extractor.close(); | |||
} | |||
@Test | |||
void testGetComplexText() throws IOException { | |||
// A fairly complex file | |||
XSSFExcelExtractor extractor = getExtractor("AverageTaxRates.xlsx"); | |||
String text = extractor.getText(); | |||
assertTrue(text.length() > 0); | |||
// Might not have all formatting it should do! | |||
assertStartsWith(text, | |||
"Avgtxfull\n" + | |||
"\t(iii) AVERAGE TAX RATES ON ANNUAL" | |||
); | |||
extractor.close(); | |||
} | |||
/** | |||
* Test that we return pretty much the same as | |||
* ExcelExtractor does, when we're both passed | |||
* the same file, just saved as xls and xlsx | |||
*/ | |||
@Test | |||
void testComparedToOLE2() throws IOException { | |||
// A fairly simple file - ooxml | |||
XSSFExcelExtractor ooxmlExtractor = getExtractor("SampleSS.xlsx"); | |||
ExcelExtractor ole2Extractor = | |||
new ExcelExtractor(HSSFTestDataSamples.openSampleWorkbook("SampleSS.xls")); | |||
Map<String, POITextExtractor> extractors = new HashMap<>(); | |||
extractors.put("SampleSS.xlsx", ooxmlExtractor); | |||
extractors.put("SampleSS.xls", ole2Extractor); | |||
for (final Entry<String, POITextExtractor> e : extractors.entrySet()) { | |||
String filename = e.getKey(); | |||
POITextExtractor extractor = e.getValue(); | |||
String text = extractor.getText().replaceAll("[\r\t]", ""); | |||
assertStartsWith(filename, text, "First Sheet\nTest spreadsheet\n2nd row2nd row 2nd column\n"); | |||
Pattern pattern = Pattern.compile(".*13(\\.0+)?\\s+Sheet3.*", Pattern.DOTALL); | |||
Matcher m = pattern.matcher(text); | |||
assertTrue(m.matches(), filename); | |||
} | |||
ole2Extractor.close(); | |||
ooxmlExtractor.close(); | |||
} | |||
/** | |||
* From bug #45540 | |||
*/ | |||
@Test | |||
void testHeaderFooter() throws IOException { | |||
String[] files = new String[] { | |||
"45540_classic_Header.xlsx", "45540_form_Header.xlsx", | |||
"45540_classic_Footer.xlsx", "45540_form_Footer.xlsx", | |||
}; | |||
for(String sampleName : files) { | |||
XSSFExcelExtractor extractor = getExtractor(sampleName); | |||
String text = extractor.getText(); | |||
assertContains(sampleName, text, "testdoc"); | |||
assertContains(sampleName, text, "test phrase"); | |||
extractor.close(); | |||
} | |||
} | |||
/** | |||
* From bug #45544 | |||
*/ | |||
@Test | |||
void testComments() throws IOException { | |||
XSSFExcelExtractor extractor = getExtractor("45544.xlsx"); | |||
String text = extractor.getText(); | |||
// No comments there yet | |||
assertNotContained(text, "testdoc"); | |||
assertNotContained(text, "test phrase"); | |||
// Turn on comment extraction, will then be | |||
extractor.setIncludeCellComments(true); | |||
text = extractor.getText(); | |||
assertContains(text, "testdoc"); | |||
assertContains(text, "test phrase"); | |||
extractor.close(); | |||
} | |||
@Test | |||
void testInlineStrings() throws IOException { | |||
XSSFExcelExtractor extractor = getExtractor("InlineStrings.xlsx"); | |||
extractor.setFormulasNotResults(true); | |||
String text = extractor.getText(); | |||
@@ -220,13 +220,13 @@ class TestXSSFExcelExtractor { | |||
assertContains(text, "A5-A$2"); | |||
extractor.close(); | |||
} | |||
} | |||
/** | |||
* Simple test for text box text | |||
*/ | |||
@Test | |||
void testTextBoxes() throws IOException { | |||
/** | |||
* Simple test for text box text | |||
*/ | |||
@Test | |||
void testTextBoxes() throws IOException { | |||
try (XSSFExcelExtractor extractor = getExtractor("WithTextBox.xlsx")) { | |||
extractor.setFormulasNotResults(true); | |||
String text = extractor.getText(); | |||
@@ -234,10 +234,10 @@ class TestXSSFExcelExtractor { | |||
assertContains(text, "Line 2"); | |||
assertContains(text, "Line 3"); | |||
} | |||
} | |||
} | |||
@Test | |||
void testPhoneticRuns() throws Exception { | |||
@Test | |||
void testPhoneticRuns() throws Exception { | |||
try (XSSFExcelExtractor extractor = getExtractor("51519.xlsx")) { | |||
String text = extractor.getText(); | |||
assertContains(text, "\u8C4A\u7530"); | |||
@@ -246,5 +246,5 @@ class TestXSSFExcelExtractor { | |||
assertNotContained(text, "\u30CB\u30DB\u30F3"); | |||
} | |||
} | |||
} | |||
} |
@@ -25,16 +25,16 @@ import org.junit.jupiter.api.AfterEach; | |||
* Tests for {@link XSSFExcelExtractor} | |||
*/ | |||
public final class TestXSSFExcelExtractorUsingFactory extends TestXSSFExcelExtractor { | |||
@Override | |||
protected final XSSFExcelExtractor getExtractor(String sampleName) { | |||
ExtractorFactory.setAllThreadsPreferEventExtractors(false); | |||
ExtractorFactory.setThreadPrefersEventExtractors(false); | |||
try { | |||
return (XSSFExcelExtractor) ExtractorFactory.createExtractor(HSSFTestDataSamples.openSampleFileStream(sampleName)); | |||
} catch (Exception e) { | |||
throw new RuntimeException(e); | |||
} | |||
} | |||
@Override | |||
protected final XSSFExcelExtractor getExtractor(String sampleName) { | |||
ExtractorFactory.setAllThreadsPreferEventExtractors(false); | |||
ExtractorFactory.setThreadPrefersEventExtractors(false); | |||
try { | |||
return (XSSFExcelExtractor) ExtractorFactory.createExtractor(HSSFTestDataSamples.openSampleFileStream(sampleName)); | |||
} catch (Exception e) { | |||
throw new RuntimeException(e); | |||
} | |||
} | |||
@AfterEach | |||
void tearDown() { |
@@ -35,48 +35,48 @@ import org.junit.jupiter.api.Test; | |||
public final class TestOutlining { | |||
@Test | |||
void testSetRowGroupCollapsed() throws IOException { | |||
SXSSFWorkbook wb2 = new SXSSFWorkbook(100); | |||
wb2.setCompressTempFiles(true); | |||
SXSSFSheet sheet2 = wb2.createSheet("new sheet"); | |||
int rowCount = 20; | |||
for (int i = 0; i < rowCount; i++) { | |||
sheet2.createRow(i); | |||
} | |||
sheet2.groupRow(4, 9); | |||
sheet2.groupRow(11, 19); | |||
sheet2.setRowGroupCollapsed(4, true); | |||
SXSSFRow r = sheet2.getRow(8); | |||
assertTrue(r.getHidden()); | |||
r = sheet2.getRow(10); | |||
assertTrue(r.getCollapsed()); | |||
r = sheet2.getRow(12); | |||
assertNull(r.getHidden()); | |||
wb2.dispose(); | |||
wb2.close(); | |||
} | |||
void testSetRowGroupCollapsed() throws IOException { | |||
SXSSFWorkbook wb2 = new SXSSFWorkbook(100); | |||
wb2.setCompressTempFiles(true); | |||
SXSSFSheet sheet2 = wb2.createSheet("new sheet"); | |||
int rowCount = 20; | |||
for (int i = 0; i < rowCount; i++) { | |||
sheet2.createRow(i); | |||
} | |||
sheet2.groupRow(4, 9); | |||
sheet2.groupRow(11, 19); | |||
sheet2.setRowGroupCollapsed(4, true); | |||
SXSSFRow r = sheet2.getRow(8); | |||
assertTrue(r.getHidden()); | |||
r = sheet2.getRow(10); | |||
assertTrue(r.getCollapsed()); | |||
r = sheet2.getRow(12); | |||
assertNull(r.getHidden()); | |||
wb2.dispose(); | |||
wb2.close(); | |||
} | |||
@Test | |||
void testSetRowGroupCollapsedError() throws IOException { | |||
SXSSFWorkbook wb2 = new SXSSFWorkbook(100); | |||
wb2.setCompressTempFiles(true); | |||
SXSSFSheet sheet2 = wb2.createSheet("new sheet"); | |||
SXSSFWorkbook wb2 = new SXSSFWorkbook(100); | |||
wb2.setCompressTempFiles(true); | |||
SXSSFSheet sheet2 = wb2.createSheet("new sheet"); | |||
int rowCount = 20; | |||
for (int i = 0; i < rowCount; i++) { | |||
sheet2.createRow(i); | |||
} | |||
int rowCount = 20; | |||
for (int i = 0; i < rowCount; i++) { | |||
sheet2.createRow(i); | |||
} | |||
sheet2.groupRow(4, 9); | |||
sheet2.groupRow(11, 19); | |||
sheet2.groupRow(4, 9); | |||
sheet2.groupRow(11, 19); | |||
IllegalArgumentException e; | |||
e = assertThrows(IllegalArgumentException.class, () -> sheet2.setRowGroupCollapsed(3, true)); | |||
e = assertThrows(IllegalArgumentException.class, () -> sheet2.setRowGroupCollapsed(3, true)); | |||
assertTrue(e.getMessage().contains("row (3)")); | |||
e = assertThrows(IllegalArgumentException.class, () -> sheet2.setRowGroupCollapsed(10, true)); | |||
@@ -88,17 +88,17 @@ public final class TestOutlining { | |||
e = assertThrows(IllegalArgumentException.class, () -> sheet2.setRowGroupCollapsed(20, true)); | |||
assertTrue(e.getMessage().contains("Row does not exist"), "Had: " + e.getMessage()); | |||
SXSSFRow r = sheet2.getRow(8); | |||
assertNotNull(r); | |||
assertNull(r.getHidden()); | |||
r = sheet2.getRow(10); | |||
assertNull(r.getCollapsed()); | |||
r = sheet2.getRow(12); | |||
assertNull(r.getHidden()); | |||
wb2.dispose(); | |||
wb2.close(); | |||
} | |||
SXSSFRow r = sheet2.getRow(8); | |||
assertNotNull(r); | |||
assertNull(r.getHidden()); | |||
r = sheet2.getRow(10); | |||
assertNull(r.getCollapsed()); | |||
r = sheet2.getRow(12); | |||
assertNull(r.getHidden()); | |||
wb2.dispose(); | |||
wb2.close(); | |||
} | |||
@Test | |||
void testOutlineGettersHSSF() throws IOException { |
@@ -98,23 +98,23 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook { | |||
@Test | |||
void existingWorkbook() throws IOException { | |||
XSSFWorkbook xssfWb1 = new XSSFWorkbook(); | |||
xssfWb1.createSheet("S1"); | |||
XSSFWorkbook xssfWb1 = new XSSFWorkbook(); | |||
xssfWb1.createSheet("S1"); | |||
SXSSFWorkbook wb1 = new SXSSFWorkbook(xssfWb1); | |||
XSSFWorkbook xssfWb2 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb1); | |||
assertTrue(wb1.dispose()); | |||
XSSFWorkbook xssfWb2 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb1); | |||
assertTrue(wb1.dispose()); | |||
SXSSFWorkbook wb2 = new SXSSFWorkbook(xssfWb2); | |||
assertEquals(1, wb2.getNumberOfSheets()); | |||
Sheet sheet = wb2.getSheetAt(0); | |||
assertNotNull(sheet); | |||
assertEquals("S1", sheet.getSheetName()); | |||
assertTrue(wb2.dispose()); | |||
xssfWb2.close(); | |||
xssfWb1.close(); | |||
wb2.close(); | |||
wb1.close(); | |||
assertEquals(1, wb2.getNumberOfSheets()); | |||
Sheet sheet = wb2.getSheetAt(0); | |||
assertNotNull(sheet); | |||
assertEquals("S1", sheet.getSheetName()); | |||
assertTrue(wb2.dispose()); | |||
xssfWb2.close(); | |||
xssfWb1.close(); | |||
wb2.close(); | |||
wb1.close(); | |||
} | |||
@Test | |||
@@ -157,76 +157,76 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook { | |||
@Test | |||
void addToExistingWorkbook() throws IOException { | |||
XSSFWorkbook xssfWb1 = new XSSFWorkbook(); | |||
xssfWb1.createSheet("S1"); | |||
Sheet sheet = xssfWb1.createSheet("S2"); | |||
Row row = sheet.createRow(1); | |||
Cell cell = row.createCell(1); | |||
cell.setCellValue("value 2_1_1"); | |||
XSSFWorkbook xssfWb1 = new XSSFWorkbook(); | |||
xssfWb1.createSheet("S1"); | |||
Sheet sheet = xssfWb1.createSheet("S2"); | |||
Row row = sheet.createRow(1); | |||
Cell cell = row.createCell(1); | |||
cell.setCellValue("value 2_1_1"); | |||
SXSSFWorkbook wb1 = new SXSSFWorkbook(xssfWb1); | |||
XSSFWorkbook xssfWb2 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb1); | |||
XSSFWorkbook xssfWb2 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb1); | |||
assertTrue(wb1.dispose()); | |||
xssfWb1.close(); | |||
SXSSFWorkbook wb2 = new SXSSFWorkbook(xssfWb2); | |||
// Add a row to the existing empty sheet | |||
Sheet sheet1 = wb2.getSheetAt(0); | |||
Row row1_1 = sheet1.createRow(1); | |||
Cell cell1_1_1 = row1_1.createCell(1); | |||
cell1_1_1.setCellValue("value 1_1_1"); | |||
// Add a row to the existing non-empty sheet | |||
Sheet sheet2 = wb2.getSheetAt(1); | |||
Row row2_2 = sheet2.createRow(2); | |||
Cell cell2_2_1 = row2_2.createCell(1); | |||
cell2_2_1.setCellValue("value 2_2_1"); | |||
// Add a sheet with one row | |||
Sheet sheet3 = wb2.createSheet("S3"); | |||
Row row3_1 = sheet3.createRow(1); | |||
Cell cell3_1_1 = row3_1.createCell(1); | |||
cell3_1_1.setCellValue("value 3_1_1"); | |||
XSSFWorkbook xssfWb3 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb2); | |||
wb2.close(); | |||
assertEquals(3, xssfWb3.getNumberOfSheets()); | |||
// Verify sheet 1 | |||
sheet1 = xssfWb3.getSheetAt(0); | |||
assertEquals("S1", sheet1.getSheetName()); | |||
assertEquals(1, sheet1.getPhysicalNumberOfRows()); | |||
row1_1 = sheet1.getRow(1); | |||
assertNotNull(row1_1); | |||
cell1_1_1 = row1_1.getCell(1); | |||
assertNotNull(cell1_1_1); | |||
assertEquals("value 1_1_1", cell1_1_1.getStringCellValue()); | |||
// Verify sheet 2 | |||
sheet2 = xssfWb3.getSheetAt(1); | |||
assertEquals("S2", sheet2.getSheetName()); | |||
assertEquals(2, sheet2.getPhysicalNumberOfRows()); | |||
Row row2_1 = sheet2.getRow(1); | |||
assertNotNull(row2_1); | |||
Cell cell2_1_1 = row2_1.getCell(1); | |||
assertNotNull(cell2_1_1); | |||
assertEquals("value 2_1_1", cell2_1_1.getStringCellValue()); | |||
row2_2 = sheet2.getRow(2); | |||
assertNotNull(row2_2); | |||
cell2_2_1 = row2_2.getCell(1); | |||
assertNotNull(cell2_2_1); | |||
assertEquals("value 2_2_1", cell2_2_1.getStringCellValue()); | |||
// Verify sheet 3 | |||
sheet3 = xssfWb3.getSheetAt(2); | |||
assertEquals("S3", sheet3.getSheetName()); | |||
assertEquals(1, sheet3.getPhysicalNumberOfRows()); | |||
row3_1 = sheet3.getRow(1); | |||
assertNotNull(row3_1); | |||
cell3_1_1 = row3_1.getCell(1); | |||
assertNotNull(cell3_1_1); | |||
assertEquals("value 3_1_1", cell3_1_1.getStringCellValue()); | |||
// Add a row to the existing empty sheet | |||
Sheet sheet1 = wb2.getSheetAt(0); | |||
Row row1_1 = sheet1.createRow(1); | |||
Cell cell1_1_1 = row1_1.createCell(1); | |||
cell1_1_1.setCellValue("value 1_1_1"); | |||
// Add a row to the existing non-empty sheet | |||
Sheet sheet2 = wb2.getSheetAt(1); | |||
Row row2_2 = sheet2.createRow(2); | |||
Cell cell2_2_1 = row2_2.createCell(1); | |||
cell2_2_1.setCellValue("value 2_2_1"); | |||
// Add a sheet with one row | |||
Sheet sheet3 = wb2.createSheet("S3"); | |||
Row row3_1 = sheet3.createRow(1); | |||
Cell cell3_1_1 = row3_1.createCell(1); | |||
cell3_1_1.setCellValue("value 3_1_1"); | |||
XSSFWorkbook xssfWb3 = SXSSFITestDataProvider.instance.writeOutAndReadBack(wb2); | |||
wb2.close(); | |||
assertEquals(3, xssfWb3.getNumberOfSheets()); | |||
// Verify sheet 1 | |||
sheet1 = xssfWb3.getSheetAt(0); | |||
assertEquals("S1", sheet1.getSheetName()); | |||
assertEquals(1, sheet1.getPhysicalNumberOfRows()); | |||
row1_1 = sheet1.getRow(1); | |||
assertNotNull(row1_1); | |||
cell1_1_1 = row1_1.getCell(1); | |||
assertNotNull(cell1_1_1); | |||
assertEquals("value 1_1_1", cell1_1_1.getStringCellValue()); | |||
// Verify sheet 2 | |||
sheet2 = xssfWb3.getSheetAt(1); | |||
assertEquals("S2", sheet2.getSheetName()); | |||
assertEquals(2, sheet2.getPhysicalNumberOfRows()); | |||
Row row2_1 = sheet2.getRow(1); | |||
assertNotNull(row2_1); | |||
Cell cell2_1_1 = row2_1.getCell(1); | |||
assertNotNull(cell2_1_1); | |||
assertEquals("value 2_1_1", cell2_1_1.getStringCellValue()); | |||
row2_2 = sheet2.getRow(2); | |||
assertNotNull(row2_2); | |||
cell2_2_1 = row2_2.getCell(1); | |||
assertNotNull(cell2_2_1); | |||
assertEquals("value 2_2_1", cell2_2_1.getStringCellValue()); | |||
// Verify sheet 3 | |||
sheet3 = xssfWb3.getSheetAt(2); | |||
assertEquals("S3", sheet3.getSheetName()); | |||
assertEquals(1, sheet3.getPhysicalNumberOfRows()); | |||
row3_1 = sheet3.getRow(1); | |||
assertNotNull(row3_1); | |||
cell3_1_1 = row3_1.getCell(1); | |||
assertNotNull(cell3_1_1); | |||
assertEquals("value 3_1_1", cell3_1_1.getStringCellValue()); | |||
xssfWb2.close(); | |||
xssfWb3.close(); | |||
wb1.close(); | |||
xssfWb3.close(); | |||
wb1.close(); | |||
} | |||
@Test | |||
@@ -358,7 +358,7 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook { | |||
@Disabled("Crashes the JVM because of documented JVM behavior with concurrent writing/reading of zip-files, " | |||
+ "see http://www.oracle.com/technetwork/java/javase/documentation/overview-156328.html") | |||
@Test | |||
@Test | |||
void bug53515a() throws Exception { | |||
File out = new File("Test.xlsx"); | |||
assertTrue(!out.exists() || out.delete()); | |||
@@ -529,7 +529,7 @@ public final class TestSXSSFWorkbook extends BaseTestXWorkbook { | |||
} | |||
@Disabled("not implemented") | |||
@Test | |||
@Test | |||
void changeSheetNameWithSharedFormulas() { | |||
} | |||
} |