aboutsummaryrefslogtreecommitdiffstats
path: root/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComments.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComments.java')
-rw-r--r--src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComments.java280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComments.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComments.java
new file mode 100644
index 0000000000..3cf82b680c
--- /dev/null
+++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComments.java
@@ -0,0 +1,280 @@
+/* ====================================================================
+ 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.xwpf.usermodel;
+
+import org.apache.poi.ooxml.POIXMLDocumentPart;
+import org.apache.poi.ooxml.POIXMLException;
+import org.apache.poi.ooxml.POIXMLRelation;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.Internal;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlOptions;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComments;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CommentsDocument;
+
+import javax.xml.namespace.QName;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
+
+/**
+ * specifies all of the comments defined in the current document
+ */
+public class XWPFComments extends POIXMLDocumentPart {
+
+ XWPFDocument document;
+ private List<XWPFComment> comments = new ArrayList<>();
+ private List<XWPFPictureData> pictures = new ArrayList<>();
+ private CTComments ctComments;
+
+ /**
+ * Construct XWPFComments from a package part
+ *
+ * @param part the package part holding the data of the footnotes,
+ */
+ public XWPFComments(PackagePart part) {
+ super(part);
+ }
+
+ /**
+ * Construct XWPFComments from scratch for a new document.
+ */
+ public XWPFComments() {
+ ctComments = CTComments.Factory.newInstance();
+ }
+
+ /**
+ * read comments form an existing package
+ */
+ @Override
+ public void onDocumentRead() throws IOException {
+ try (InputStream is = getPackagePart().getInputStream()) {
+ CommentsDocument doc = CommentsDocument.Factory.parse(is, DEFAULT_XML_OPTIONS);
+ ctComments = doc.getComments();
+ for (CTComment ctComment : ctComments.getCommentList()) {
+ comments.add(new XWPFComment(ctComment, this));
+ }
+ } catch (XmlException e) {
+ throw new POIXMLException("Unable to read comments", e);
+ }
+
+ for (POIXMLDocumentPart poixmlDocumentPart : getRelations()) {
+ if (poixmlDocumentPart instanceof XWPFPictureData) {
+ XWPFPictureData xwpfPicData = (XWPFPictureData) poixmlDocumentPart;
+ pictures.add(xwpfPicData);
+ document.registerPackagePictureData(xwpfPicData);
+ }
+ }
+ }
+
+ /**
+ * Adds a picture to the comments.
+ *
+ * @param is The stream to read image from
+ * @param format The format of the picture.
+ * @return the index to this picture (0 based), the added picture can be
+ * obtained from {@link #getAllPictures()} .
+ * @throws InvalidFormatException If the format of the picture is not known.
+ * @throws IOException If reading the picture-data from the stream fails.
+ */
+ public String addPictureData(InputStream is, int format) throws InvalidFormatException, IOException {
+ byte[] data = IOUtils.toByteArray(is);
+ return addPictureData(data, format);
+ }
+
+ /**
+ * Adds a picture to the comments.
+ *
+ * @param pictureData The picture data
+ * @param format The format of the picture.
+ * @return the index to this picture (0 based), the added picture can be
+ * obtained from {@link #getAllPictures()} .
+ * @throws InvalidFormatException If the format of the picture is not known.
+ */
+ public String addPictureData(byte[] pictureData, int format) throws InvalidFormatException {
+ XWPFPictureData xwpfPicData = document.findPackagePictureData(pictureData, format);
+ POIXMLRelation relDesc = XWPFPictureData.RELATIONS[format];
+
+ if (xwpfPicData == null) {
+ /* Part doesn't exist, create a new one */
+ int idx = getXWPFDocument().getNextPicNameNumber(format);
+ xwpfPicData = (XWPFPictureData) createRelationship(relDesc, XWPFFactory.getInstance(), idx);
+ /* write bytes to new part */
+ PackagePart picDataPart = xwpfPicData.getPackagePart();
+ try (OutputStream out = picDataPart.getOutputStream()) {
+ out.write(pictureData);
+ } catch (IOException e) {
+ throw new POIXMLException(e);
+ }
+
+ document.registerPackagePictureData(xwpfPicData);
+ pictures.add(xwpfPicData);
+ return getRelationId(xwpfPicData);
+ } else if (!getRelations().contains(xwpfPicData)) {
+ /*
+ * Part already existed, but was not related so far. Create
+ * relationship to the already existing part and update
+ * POIXMLDocumentPart data.
+ */
+ // TODO add support for TargetMode.EXTERNAL relations.
+ RelationPart rp = addRelation(null, XWPFRelation.IMAGES, xwpfPicData);
+ pictures.add(xwpfPicData);
+ return rp.getRelationship().getId();
+ } else {
+ /* Part already existed, get relation id and return it */
+ return getRelationId(xwpfPicData);
+ }
+ }
+
+ /**
+ * save and commit comments
+ */
+ @Override
+ protected void commit() throws IOException {
+ XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
+ xmlOptions.setSaveSyntheticDocumentElement(new QName(
+ CTComments.type.getName().getNamespaceURI(), "comments"));
+ PackagePart part = getPackagePart();
+ OutputStream out = part.getOutputStream();
+ ctComments.save(out, xmlOptions);
+ out.close();
+ }
+
+ public List<XWPFPictureData> getAllPictures() {
+ return Collections.unmodifiableList(pictures);
+ }
+
+ /**
+ * Gets the underlying CTComments object for the comments.
+ *
+ * @return CTComments object
+ */
+ public CTComments getCtComments() {
+ return ctComments;
+ }
+
+ /**
+ * set a new comments
+ */
+ @Internal
+ public void setCtComments(CTComments ctComments) {
+ this.ctComments = ctComments;
+ }
+
+ /**
+ * Get the list of {@link XWPFComment} in the Comments part.
+ *
+ * @return
+ */
+ public List<XWPFComment> getComments() {
+ return comments;
+ }
+
+ /**
+ * Get the specified comment by position
+ *
+ * @param pos Array position of the comment
+ * @return
+ */
+ public XWPFComment getComment(int pos) {
+ if (pos >= 0 && pos < ctComments.sizeOfCommentArray()) {
+ return getComments().get(pos);
+ }
+ return null;
+ }
+
+ /**
+ * Get the specified comment by comment id
+ *
+ * @param id comment id
+ * @return the specified comment
+ */
+ public XWPFComment getCommentByID(String id) {
+ for (XWPFComment comment : comments) {
+ if (comment.getId().equals(id)) {
+ return comment;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the specified comment by ctComment
+ *
+ * @param ctComment
+ * @return
+ */
+ public XWPFComment getComment(CTComment ctComment) {
+ for (int i = 0; i < comments.size(); i++) {
+ if (comments.get(i).getCtComment() == ctComment) {
+ return comments.get(i);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Create a new comment and add it to the document.
+ *
+ * @param cid comment Id
+ * @return
+ */
+ public XWPFComment createComment(BigInteger cid) {
+ CTComment ctComment = ctComments.addNewComment();
+ ctComment.setId(cid);
+ XWPFComment comment = new XWPFComment(ctComment, this);
+ comments.add(comment);
+ return comment;
+ }
+
+ /**
+ * Remove the specified comment if present.
+ *
+ * @param pos Array position of the comment to be removed
+ * @return True if the comment was removed.
+ */
+ public boolean removeComment(int pos) {
+ if (pos >= 0 && pos < ctComments.sizeOfCommentArray()) {
+ comments.remove(pos);
+ ctComments.removeComment(pos);
+ return true;
+ }
+ return false;
+ }
+
+ public XWPFDocument getXWPFDocument() {
+ if (null != document) {
+ return document;
+ }
+ return (XWPFDocument) getParent();
+ }
+
+ public void setXWPFDocument(XWPFDocument document) {
+ this.document = document;
+ }
+
+}