/* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more 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 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, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ package org.apache.poi; import java.io.IOException; import java.util.LinkedList; import java.util.List; import org.apache.xmlbeans.XmlOptions; import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogFactory; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.*; import org.apache.poi.openxml4j.opc.Package; /** * Represents an entry of a OOXML package. * *
* Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.apache.poi.openxml4j.opc.PackagePart}. *
* * @author Yegor Kozlov */ public class POIXMLDocumentPart { private static POILogger logger = POILogFactory.getLogger(POIXMLDocumentPart.class); public static final XmlOptions DEFAULT_XML_OPTIONS; static { DEFAULT_XML_OPTIONS = new XmlOptions(); DEFAULT_XML_OPTIONS.setSaveOuter(); DEFAULT_XML_OPTIONS.setUseDefaultNamespace(); DEFAULT_XML_OPTIONS.setSaveAggressiveNamespaces(); } private PackagePart packagePart; private PackageRelationship packageRel; private POIXMLDocumentPart parent; private Listnull
for the root element.
*/
public final POIXMLDocumentPart getParent(){
return parent;
}
@Override
public String toString(){
return packagePart.toString();
}
/**
* Save the content in the underlying package part.
* Default implementation is empty meaning that the package part is left unmodified.
*
* Sub-classes should override and add logic to marshal the "model" into Ooxml4J.
*
* For example, the code saving a generic XML entry may look as follows:
*
* protected void commit() throws IOException {
* PackagePart part = getPackagePart();
* OutputStream out = part.getOutputStream();
* XmlObject bean = getXmlBean(); //the "model" which holds changes in memory
* bean.save(out, DEFAULT_XML_OPTIONS);
* out.close();
* }
*
*
*/
protected void commit() throws IOException {
}
/**
* Save changes in the underlying OOXML package.
* Recursively fires {@link #commit()} for each package part
*/
protected final void onSave() throws IOException{
commit();
for(POIXMLDocumentPart p : relations){
p.onSave();
}
}
/**
* Create a new child POIXMLDocumentPart
*
* @param descriptor the part descriptor
* @param factory the factory that will create an instance of the requested relation
* @return the created child POIXMLDocumentPart
*/
protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory){
return createRelationship(descriptor, factory, -1, false);
}
protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx){
return createRelationship(descriptor, factory, idx, false);
}
/**
* Create a new child POIXMLDocumentPart
*
* @param descriptor the part descriptor
* @param factory the factory that will create an instance of the requested relation
* @param idx part number
* @param noRelation if true, then no relationship is added.
* @return the created child POIXMLDocumentPart
*/
protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx, boolean noRelation){
try {
PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx));
PackageRelationship rel = null;
if(!noRelation) rel = packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation());
PackagePart part = packagePart.getPackage().createPart(ppName, descriptor.getContentType());
POIXMLDocumentPart doc = factory.newDocumentPart(descriptor);
doc.packageRel = rel;
doc.packagePart = part;
doc.parent = this;
addRelation(doc);
return doc;
} catch (Exception e){
throw new POIXMLException(e);
}
}
/**
* Iterate through the underlying PackagePart and create child POIXMLFactory instances
* using the specified factory
*
* @param factory the factory object that creates POIXMLFactory instances
*/
protected final void read(POIXMLFactory factory) throws OpenXML4JException {
PackageRelationshipCollection rels = packagePart.getRelationships();
for (PackageRelationship rel : rels) {
if(rel.getTargetMode() == TargetMode.INTERNAL){
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
PackagePart p = packagePart.getPackage().getPart(relName);
if(p == null) {
logger.log(POILogger.ERROR, "Skipped invalid entry " + rel.getTargetURI());
continue;
}
POIXMLDocumentPart childPart = factory.createDocumentPart(rel, p);
childPart.parent = this;
addRelation(childPart);
if(p.hasRelationships()) childPart.read(factory);
}
}
}
/**
* Fired when a new package part is created
*/
protected void onDocumentCreate() throws IOException {
}
/**
* Fired when a package part is read
*/
protected void onDocumentRead() throws IOException{
}
}