| /* ==================================================================== |
| 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.xslf.usermodel; |
| |
| import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; |
| |
| import java.io.IOException; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.apache.poi.ooxml.POIXMLDocument; |
| import org.apache.poi.openxml4j.exceptions.InvalidFormatException; |
| import org.apache.poi.openxml4j.exceptions.OpenXML4JException; |
| import org.apache.poi.openxml4j.opc.OPCPackage; |
| import org.apache.poi.openxml4j.opc.PackagePart; |
| import org.apache.poi.openxml4j.opc.PackageRelationship; |
| import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; |
| import org.apache.poi.openxml4j.opc.TargetMode; |
| import org.apache.poi.util.Internal; |
| import org.apache.xmlbeans.XmlException; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTCommentList; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdList; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdListEntry; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterIdList; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterIdListEntry; |
| import org.openxmlformats.schemas.presentationml.x2006.main.CmLstDocument; |
| import org.openxmlformats.schemas.presentationml.x2006.main.NotesDocument; |
| import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument; |
| import org.openxmlformats.schemas.presentationml.x2006.main.SldDocument; |
| import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument; |
| |
| /** |
| * Experimental class to do low level processing of pptx files. |
| * |
| * Most users should use the higher level {@link XMLSlideShow} instead. |
| * |
| * If you are using these low level classes, then you |
| * will almost certainly need to refer to the OOXML |
| * specifications from |
| * http://www.ecma-international.org/publications/standards/Ecma-376.htm |
| * |
| * WARNING - APIs expected to change rapidly |
| */ |
| public class XSLFSlideShow extends POIXMLDocument { |
| |
| 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); |
| |
| if(getCorePart().getContentType().equals(XSLFRelation.THEME_MANAGER.getContentType())) { |
| rebase(getPackage()); |
| } |
| |
| 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())); |
| |
| 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)); |
| } |
| |
| /** |
| * 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 |
| * 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 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); |
| |
| 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()); |
| } |
| |
| 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); |
| |
| 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); |
| |
| 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()); |
| } |
| |
| 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; |
| } |
| |
| } |