View | Details | Raw Unified | Return to bug 51265
Collapse All | Expand All

(-)src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java (+22 lines)
Lines 32-37 Link Here
32
import java.util.Date;
32
import java.util.Date;
33
import java.util.Hashtable;
33
import java.util.Hashtable;
34
import java.util.concurrent.locks.ReentrantReadWriteLock;
34
import java.util.concurrent.locks.ReentrantReadWriteLock;
35
import java.util.regex.Matcher;
36
import java.util.regex.Pattern;
35
37
36
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
38
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
37
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
39
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
Lines 554-559 Link Here
554
	}
556
	}
555
557
556
	/**
558
	/**
559
	 * @param nameBase
560
	 * @return
561
	 */
562
	public ArrayList<PackagePart> getPartsByName(final Pattern namePattern) {
563
	    if (namePattern == null) {
564
	        throw new IllegalArgumentException("value for parameter 'nameBase' must not be null");
565
	    }
566
	    ArrayList<PackagePart> result = new ArrayList<PackagePart>();
567
	    for (PackagePart part : partList.values()) {
568
	        PackagePartName partName = part.getPartName();
569
	        String name = partName.getName();
570
	        Matcher matcher = namePattern.matcher(name);
571
	        if (matcher.matches()) {
572
	            result.add(part);
573
	        }
574
	    }
575
	    return result;
576
	}
577
578
	/**
557
	 * Get the target part from the specified relationship.
579
	 * Get the target part from the specified relationship.
558
	 *
580
	 *
559
	 * @param partRel
581
	 * @param partRel
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java (-349 / +434 lines)
Lines 16-27 Link Here
16
==================================================================== */
16
==================================================================== */
17
package org.apache.poi.xwpf.usermodel;
17
package org.apache.poi.xwpf.usermodel;
18
18
19
import java.io.ByteArrayInputStream;
20
import java.io.ByteArrayOutputStream;
19
import java.io.ByteArrayOutputStream;
21
import java.io.IOException;
20
import java.io.IOException;
22
import java.io.InputStream;
21
import java.io.InputStream;
23
import java.io.OutputStream;
22
import java.io.OutputStream;
24
import java.util.ArrayList;
23
import java.util.ArrayList;
24
import java.util.Arrays;
25
import java.util.Collection;
25
import java.util.Collection;
26
import java.util.Collections;
26
import java.util.Collections;
27
import java.util.HashMap;
27
import java.util.HashMap;
Lines 36-41 Link Here
36
import org.apache.poi.POIXMLDocumentPart;
36
import org.apache.poi.POIXMLDocumentPart;
37
import org.apache.poi.POIXMLException;
37
import org.apache.poi.POIXMLException;
38
import org.apache.poi.POIXMLProperties;
38
import org.apache.poi.POIXMLProperties;
39
import org.apache.poi.POIXMLRelation;
39
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
40
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
40
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
41
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
41
import org.apache.poi.openxml4j.opc.OPCPackage;
42
import org.apache.poi.openxml4j.opc.OPCPackage;
Lines 46-51 Link Here
46
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
47
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
47
import org.apache.poi.openxml4j.opc.TargetMode;
48
import org.apache.poi.openxml4j.opc.TargetMode;
48
import org.apache.poi.util.IOUtils;
49
import org.apache.poi.util.IOUtils;
50
import org.apache.poi.util.IdentifierManager;
49
import org.apache.poi.util.Internal;
51
import org.apache.poi.util.Internal;
50
import org.apache.poi.util.PackageHelper;
52
import org.apache.poi.util.PackageHelper;
51
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
53
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
Lines 84-99 Link Here
84
86
85
    private CTDocument1 ctDocument;
87
    private CTDocument1 ctDocument;
86
    private XWPFSettings settings;
88
    private XWPFSettings settings;
87
    protected List<XWPFFooter> footers;
89
    /**
88
    protected List <XWPFHeader> headers;
90
     * Keeps track on all id-values used in this document and included parts, like headers, footers, etc.
89
    protected List<XWPFComment> comments;
91
     */
90
    protected List<XWPFHyperlink> hyperlinks;
92
    private IdentifierManager drawingIdManager = new IdentifierManager(1L,4294967295L);
91
    protected List<XWPFParagraph> paragraphs;
93
    protected List<XWPFFooter> footers = new ArrayList<XWPFFooter>();
92
    protected List<XWPFTable> tables;
94
    protected List<XWPFHeader> headers = new ArrayList<XWPFHeader>();
93
    protected List<IBodyElement> bodyElements;
95
    protected List<XWPFComment> comments = new ArrayList<XWPFComment>();
94
    protected List<XWPFPictureData> pictures;
96
    protected List<XWPFHyperlink> hyperlinks = new ArrayList<XWPFHyperlink>();
95
    protected Map<Integer, XWPFFootnote> footnotes;
97
    protected List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>();
96
    protected Map<Integer, XWPFFootnote> endnotes;
98
    protected List<XWPFTable> tables = new ArrayList<XWPFTable>();
99
    protected List<IBodyElement> bodyElements = new ArrayList<IBodyElement>();
100
    protected List<XWPFPictureData> pictures = new ArrayList<XWPFPictureData>();
101
    protected Map<Long, List<XWPFPictureData>> packagePictures = new HashMap<Long, List<XWPFPictureData>>();
102
    protected Map<Integer, XWPFFootnote> footnotes = new HashMap<Integer, XWPFFootnote>();
103
    protected Map<Integer, XWPFFootnote> endnotes = new HashMap<Integer, XWPFFootnote>();
97
    protected XWPFNumbering numbering;
104
    protected XWPFNumbering numbering;
98
    protected XWPFStyles styles;
105
    protected XWPFStyles styles;
99
106
Lines 121-200 Link Here
121
128
122
    @Override
129
    @Override
123
    protected void onDocumentRead() throws IOException {
130
    protected void onDocumentRead() throws IOException {
124
        hyperlinks = new ArrayList<XWPFHyperlink>();
125
        comments = new ArrayList<XWPFComment>();
126
        paragraphs = new ArrayList<XWPFParagraph>();
127
        tables= new ArrayList<XWPFTable>();
128
        bodyElements = new ArrayList<IBodyElement>();
129
        footers = new ArrayList<XWPFFooter>();
130
        headers = new ArrayList<XWPFHeader>();
131
        footnotes = new HashMap<Integer, XWPFFootnote>();
132
        endnotes = new HashMap<Integer, XWPFFootnote>();
133
134
        try {
131
        try {
135
            DocumentDocument doc = DocumentDocument.Factory.parse(getPackagePart().getInputStream());
132
            DocumentDocument doc = DocumentDocument.Factory.parse(getPackagePart().getInputStream());
136
            ctDocument = doc.getDocument();
133
            ctDocument = doc.getDocument();
137
134
138
            initFootnotes();
135
            initFootnotes();
139
           
136
140
            
141
            // parse the document with cursor and add
137
            // parse the document with cursor and add
142
            // the XmlObject to its lists
138
            // the XmlObject to its lists
143
    		XmlCursor cursor = ctDocument.getBody().newCursor();
139
            XmlCursor cursor = ctDocument.getBody().newCursor();
144
            cursor.selectPath("./*");
140
            cursor.selectPath("./*");
145
            while (cursor.toNextSelection()) {
141
            while (cursor.toNextSelection()) {
146
                XmlObject o = cursor.getObject();
142
                XmlObject o = cursor.getObject();
147
                if (o instanceof CTP) {
143
                if (o instanceof CTP) {
148
                	XWPFParagraph p = new XWPFParagraph((CTP)o, this);
144
                    XWPFParagraph p = new XWPFParagraph((CTP) o, this);
149
                	bodyElements.add(p);
145
                    bodyElements.add(p);
150
                	paragraphs.add(p);
146
                    paragraphs.add(p);
151
                }
147
                } else if (o instanceof CTTbl) {
152
                if (o instanceof CTTbl) {
148
                    XWPFTable t = new XWPFTable((CTTbl) o, this);
153
                	XWPFTable t = new XWPFTable((CTTbl)o, this);
149
                    bodyElements.add(t);
154
                	bodyElements.add(t);
150
                    tables.add(t);
155
                	tables.add(t);
156
                }
151
                }
157
            }
152
            }
158
            cursor.dispose();
153
            cursor.dispose();
159
			
154
160
            // Sort out headers and footers
155
            // Sort out headers and footers
161
			if (doc.getDocument().getBody().getSectPr() != null)
156
            if (doc.getDocument().getBody().getSectPr() != null)
162
				headerFooterPolicy = new XWPFHeaderFooterPolicy(this);
157
                headerFooterPolicy = new XWPFHeaderFooterPolicy(this);
163
				
158
164
			// Create for each XML-part in the Package a PartClass
159
            // Create for each XML-part in the Package a PartClass
165
            for(POIXMLDocumentPart p : getRelations()){
160
            for (POIXMLDocumentPart p : getRelations()) {
166
                String relation = p.getPackageRelationship().getRelationshipType();
161
                String relation = p.getPackageRelationship().getRelationshipType();
167
                if(relation.equals(XWPFRelation.STYLES.getRelation())){
162
                if (relation.equals(XWPFRelation.STYLES.getRelation())) {
168
                	this.styles = (XWPFStyles) p;
163
                    this.styles = (XWPFStyles) p;
169
                } else if (relation.equals(XWPFRelation.NUMBERING.getRelation())){
164
                    this.styles.onDocumentRead();
170
                	this.numbering = (XWPFNumbering) p;
165
                } else if (relation.equals(XWPFRelation.NUMBERING.getRelation())) {
171
                } else if (relation.equals(XWPFRelation.FOOTER.getRelation())){
166
                    this.numbering = (XWPFNumbering) p;
172
                	footers.add((XWPFFooter)p);
167
                    this.numbering.onDocumentRead();
173
                } else if (relation.equals(XWPFRelation.HEADER.getRelation())){
168
                } else if (relation.equals(XWPFRelation.FOOTER.getRelation())) {
174
                	headers.add((XWPFHeader)p);
169
                    XWPFFooter footer = (XWPFFooter) p;
175
                } else if (relation.equals(XWPFRelation.COMMENT.getRelation())){
170
                    footers.add(footer);
171
                    footer.onDocumentRead();
172
                } else if (relation.equals(XWPFRelation.HEADER.getRelation())) {
173
                    XWPFHeader header = (XWPFHeader) p;
174
                    headers.add(header);
175
                    header.onDocumentRead();
176
                } else if (relation.equals(XWPFRelation.COMMENT.getRelation())) {
177
                    // TODO Create according XWPFComment class, extending POIXMLDocumentPart
176
                    CommentsDocument cmntdoc = CommentsDocument.Factory.parse(p.getPackagePart().getInputStream());
178
                    CommentsDocument cmntdoc = CommentsDocument.Factory.parse(p.getPackagePart().getInputStream());
177
                    for(CTComment ctcomment : cmntdoc.getComments().getCommentList()) {
179
                    for (CTComment ctcomment : cmntdoc.getComments().getCommentList()) {
178
                        comments.add(new XWPFComment(ctcomment, this));
180
                        comments.add(new XWPFComment(ctcomment, this));
179
                    }
181
                    }
180
                } else if (relation.equals(XWPFRelation.SETTINGS.getRelation())){
182
                } else if (relation.equals(XWPFRelation.SETTINGS.getRelation())) {
181
                	settings = (XWPFSettings)p;
183
                    settings = (XWPFSettings) p;
184
                    settings.onDocumentRead();
185
                } else if (relation.equals(XWPFRelation.IMAGES.getRelation())) {
186
                    XWPFPictureData picData = (XWPFPictureData) p;
187
                    picData.onDocumentRead();
188
                    registerPackagePictureData(picData);
189
                    pictures.add(picData);
182
                }
190
                }
183
            }
191
            }
184
185
            initHyperlinks();
192
            initHyperlinks();
186
        } catch (XmlException e) {
193
        } catch (XmlException e) {
187
            throw new POIXMLException(e);
194
            throw new POIXMLException(e);
188
        }
195
        }
189
        // create for every Graphic-Part in Package a new XWPFGraphic
190
        getAllPictures();
191
    }
196
    }
192
197
193
    private void initHyperlinks(){
198
    private void initHyperlinks(){
194
        // Get the hyperlinks
199
        // Get the hyperlinks
195
        // TODO: make me optional/separated in private function
200
        // TODO: make me optional/separated in private function
196
        try	{
201
        try {
197
            Iterator <PackageRelationship> relIter =
202
            Iterator<PackageRelationship> relIter =
198
                getPackagePart().getRelationshipsByType(XWPFRelation.HYPERLINK.getRelation()).iterator();
203
                getPackagePart().getRelationshipsByType(XWPFRelation.HYPERLINK.getRelation()).iterator();
199
            while(relIter.hasNext()) {
204
            while(relIter.hasNext()) {
200
                PackageRelationship rel = relIter.next();
205
                PackageRelationship rel = relIter.next();
Lines 250-269 Link Here
250
     */
255
     */
251
    @Override
256
    @Override
252
    protected void onDocumentCreate() {
257
    protected void onDocumentCreate() {
253
        hyperlinks = new ArrayList<XWPFHyperlink>();
254
        comments = new ArrayList<XWPFComment>();
255
        paragraphs = new ArrayList<XWPFParagraph>();
256
        tables= new ArrayList<XWPFTable>();
257
        bodyElements = new ArrayList<IBodyElement>();
258
        footers = new ArrayList<XWPFFooter>();
259
        headers = new ArrayList<XWPFHeader>();
260
        footnotes = new HashMap<Integer, XWPFFootnote>();
261
        endnotes = new HashMap<Integer, XWPFFootnote>();
262
263
        ctDocument = CTDocument1.Factory.newInstance();
258
        ctDocument = CTDocument1.Factory.newInstance();
264
        ctDocument.addNewBody();
259
        ctDocument.addNewBody();
265
        
260
266
        settings =  (XWPFSettings) createRelationship(XWPFRelation.SETTINGS, XWPFFactory.getInstance());
261
        settings = (XWPFSettings) createRelationship(XWPFRelation.SETTINGS,XWPFFactory.getInstance());
267
262
268
        POIXMLProperties.ExtendedProperties expProps = getProperties().getExtendedProperties();
263
        POIXMLProperties.ExtendedProperties expProps = getProperties().getExtendedProperties();
269
        expProps.getUnderlyingProperties().setApplication(DOCUMENT_CREATOR);
264
        expProps.getUnderlyingProperties().setApplication(DOCUMENT_CREATOR);
Lines 276-281 Link Here
276
    public CTDocument1 getDocument() {
271
    public CTDocument1 getDocument() {
277
        return ctDocument;
272
        return ctDocument;
278
    }
273
    }
274
275
    IdentifierManager getDrawingIdManager() {
276
        return drawingIdManager;
277
    }
279
    
278
    
280
    /**
279
    /**
281
     * returns an Iterator with paragraphs and tables
280
     * returns an Iterator with paragraphs and tables
Lines 339-348 Link Here
339
338
340
    public XWPFHyperlink getHyperlinkByID(String id) {
339
    public XWPFHyperlink getHyperlinkByID(String id) {
341
        Iterator<XWPFHyperlink> iter = hyperlinks.iterator();
340
        Iterator<XWPFHyperlink> iter = hyperlinks.iterator();
342
        while(iter.hasNext())
341
        while (iter.hasNext()) {
343
        {
344
            XWPFHyperlink link = iter.next();
342
            XWPFHyperlink link = iter.next();
345
            if(link.getId().equals(id))
343
            if (link.getId().equals(id))
346
                return link;
344
                return link;
347
        }
345
        }
348
346
Lines 362-376 Link Here
362
    }
360
    }
363
361
364
    public XWPFHyperlink[] getHyperlinks() {
362
    public XWPFHyperlink[] getHyperlinks() {
365
        return hyperlinks.toArray(
363
        return hyperlinks.toArray(new XWPFHyperlink[hyperlinks.size()]);
366
                new XWPFHyperlink[hyperlinks.size()]
367
        );
368
    }
364
    }
369
365
370
    public XWPFComment getCommentByID(String id) {
366
    public XWPFComment getCommentByID(String id) {
371
        Iterator<XWPFComment> iter = comments.iterator();
367
        Iterator<XWPFComment> iter = comments.iterator();
372
        while(iter.hasNext())
368
        while (iter.hasNext()) {
373
        {
374
            XWPFComment comment = iter.next();
369
            XWPFComment comment = iter.next();
375
            if(comment.getId().equals(id))
370
            if(comment.getId().equals(id))
376
                return comment;
371
                return comment;
Lines 378-387 Link Here
378
373
379
        return null;
374
        return null;
380
    }
375
    }
376
381
    public XWPFComment[] getComments() {
377
    public XWPFComment[] getComments() {
382
        return comments.toArray(
378
        return comments.toArray(new XWPFComment[comments.size()]);
383
                new XWPFComment[comments.size()]
384
        );
385
    }
379
    }
386
380
387
    /**
381
    /**
Lines 390-399 Link Here
390
     */
384
     */
391
    public PackagePart getPartById(String id) {
385
    public PackagePart getPartById(String id) {
392
        try {
386
        try {
393
            return getTargetPart(
387
            return getTargetPart(getCorePart().getRelationship(id));
394
                    getCorePart().getRelationship(id)
388
        } catch (InvalidFormatException e) {
395
            );
396
        } catch(InvalidFormatException e) {
397
            throw new IllegalArgumentException(e);
389
            throw new IllegalArgumentException(e);
398
        }
390
        }
399
    }
391
    }
Lines 421-428 Link Here
421
            throw new IllegalStateException("Expecting one Styles document part, but found " + parts.length);
413
            throw new IllegalStateException("Expecting one Styles document part, but found " + parts.length);
422
        }
414
        }
423
415
424
        StylesDocument sd =
416
        StylesDocument sd = StylesDocument.Factory.parse(parts[0].getInputStream());
425
            StylesDocument.Factory.parse(parts[0].getInputStream());
426
        return sd.getStyles();
417
        return sd.getStyles();
427
    }
418
    }
428
419
Lines 434-448 Link Here
434
        List<PackagePart> embedds = new LinkedList<PackagePart>();
425
        List<PackagePart> embedds = new LinkedList<PackagePart>();
435
426
436
        // Get the embeddings for the workbook
427
        // Get the embeddings for the workbook
437
        for(PackageRelationship rel : getPackagePart().getRelationshipsByType(OLE_OBJECT_REL_TYPE))
428
        for (PackageRelationship rel : getPackagePart().getRelationshipsByType(OLE_OBJECT_REL_TYPE)) {
438
            embedds.add(getTargetPart(rel));
429
            embedds.add(getTargetPart(rel));
430
        }
439
431
440
        for(PackageRelationship rel : getPackagePart().getRelationshipsByType(PACK_OBJECT_REL_TYPE))
432
        for (PackageRelationship rel : getPackagePart().getRelationshipsByType(PACK_OBJECT_REL_TYPE)) {
441
            embedds.add(getTargetPart(rel));
433
            embedds.add(getTargetPart(rel));
434
        }
442
435
443
        return embedds;
436
        return embedds;
444
    }
437
    }
445
    
438
446
    /**
439
    /**
447
     * Finds that for example the 2nd entry in the body list is the 1st paragraph
440
     * Finds that for example the 2nd entry in the body list is the 1st paragraph
448
     */
441
     */
Lines 451-457 Link Here
451
       if(list.size() == 0) {
444
       if(list.size() == 0) {
452
          return -1;
445
          return -1;
453
       }
446
       }
454
       
447
455
       if(pos >= 0 && pos < bodyElements.size()) {
448
       if(pos >= 0 && pos < bodyElements.size()) {
456
          // Ensure the type is correct
449
          // Ensure the type is correct
457
          IBodyElement needle = bodyElements.get(pos);
450
          IBodyElement needle = bodyElements.get(pos);
Lines 459-465 Link Here
459
             // Wrong type
452
             // Wrong type
460
             return -1;
453
             return -1;
461
          }
454
          }
462
          
455
463
          // Work back until we find it
456
          // Work back until we find it
464
          int startPos = Math.min(pos, list.size()-1);
457
          int startPos = Math.min(pos, list.size()-1);
465
          for(int i=startPos; i>=0; i--) {
458
          for(int i=startPos; i>=0; i--) {
Lines 474-490 Link Here
474
    }
467
    }
475
    
468
    
476
    /**
469
    /**
477
     * get with the position of a Paragraph in the bodyelement array list 
470
     * Look up the paragraph at the specified position in the body elemnts list
478
     * the position of this paragraph in the paragraph array list
471
     * and return this paragraphs position in the paragraphs list
479
     * @param pos position of the paragraph in the bodyelement array list
472
     * 
480
     * @return if there is a paragraph at the position in the bodyelement array list,
473
     * @param pos
481
     * 			else it will return -1 
474
     *            The position of the relevant paragraph in the body elements
482
     * 			
475
     *            list
476
     * @return the position of the paragraph in the paragraphs list, if there is
477
     *         a paragraph at the position in the bodyelements list. Else it
478
     *         will return -1
479
     * 
483
     */
480
     */
484
    public int getParagraphPos(int pos){
481
    public int getParagraphPos(int pos) {
485
       return getBodyElementSpecificPos(pos, paragraphs);
482
       return getBodyElementSpecificPos(pos, paragraphs);
486
    }
483
    }
487
    
484
488
    /**
485
    /**
489
     * get with the position of a table in the bodyelement array list 
486
     * get with the position of a table in the bodyelement array list 
490
     * the position of this table in the table array list
487
     * the position of this table in the table array list
Lines 492-589 Link Here
492
     * @return if there is a table at the position in the bodyelement array list,
489
     * @return if there is a table at the position in the bodyelement array list,
493
     * 		   else it will return null. 
490
     * 		   else it will return null. 
494
     */
491
     */
495
    public int getTablePos(int pos){
492
    public int getTablePos(int pos) {
496
       return getBodyElementSpecificPos(pos, tables);
493
       return getBodyElementSpecificPos(pos, tables);
497
    }
494
    }
498
    
495
499
    /**
496
    /**
500
     * add a new paragraph at position of the cursor
497
     * add a new paragraph at position of the cursor. The cursor must be on the
498
     * {@link TokenType#START} tag of an subelement of the documents body. When
499
     * this method is done, the cursor passed as parameter points to the
500
     * {@link TokenType#END} of the newly inserted paragraph.
501
     * 
501
     * @param cursor
502
     * @param cursor
503
     * @return the {@link XWPFParagraph} object representing the newly inserted
504
     *         CTP object
502
     */
505
     */
503
    public XWPFParagraph insertNewParagraph(XmlCursor cursor){
506
    public XWPFParagraph insertNewParagraph(XmlCursor cursor) {
504
    	if(isCursorInBody(cursor)){
507
        if (isCursorInBody(cursor)) {
505
    		String uri = CTP.type.getName().getNamespaceURI();
508
            String uri = CTP.type.getName().getNamespaceURI();
506
    		String localPart = "p";
509
            /*
507
    		cursor.beginElement(localPart,uri);
510
             * TODO DO not use a coded constant, find the constant in the OOXML
508
    		cursor.toParent();
511
             * classes instead, as the child of type CT_Paragraph is defined in the 
509
    		CTP p = (CTP)cursor.getObject();
512
             * OOXML schema as 'p'
510
    		XWPFParagraph newP = new XWPFParagraph(p, this);
513
             */
511
    		XmlObject o = null;
514
            String localPart = "p";
512
	    	while(!(o instanceof CTP)&&(cursor.toPrevSibling())){
515
            // creates a new Paragraph, cursor is positioned inside the new
513
	    		o = cursor.getObject();
516
            // element
514
	    	}
517
            cursor.beginElement(localPart, uri);
515
	    	if((!(o instanceof CTP)) || (CTP)o == p){
518
            // move the cursor to the START token to the paragraph just created
516
	    		paragraphs.add(0, newP);
519
            cursor.toParent();
517
	    	}
520
            CTP p = (CTP) cursor.getObject();
518
	    	else{
521
            XWPFParagraph newP = new XWPFParagraph(p, this);
519
	    		int pos = paragraphs.indexOf(getParagraph((CTP)o))+1;
522
            XmlObject o = null;
520
	    		paragraphs.add(pos,newP);
523
            /*
521
	    	}
524
             * move the cursor to the previous element until a) the next
522
	    	int i=0;
525
             * paragraph is found or b) all elements have been passed
523
	    	cursor.toCursor(p.newCursor());
526
             */
524
			while(cursor.toPrevSibling()){
527
            while (!(o instanceof CTP) && (cursor.toPrevSibling())) {
525
				o =cursor.getObject();
528
                o = cursor.getObject();
526
				if(o instanceof CTP || o instanceof CTTbl)
529
            }
527
					i++;
530
            /*
528
			}
531
             * if the object that has been found is a) not a paragraph or b) is
529
			bodyElements.add(i, newP);
532
             * the paragraph that has just been inserted, as the cursor in the
530
	    	cursor.toCursor(p.newCursor());
533
             * while loop above was not moved as there were no other siblings,
531
	    	cursor.toEndToken();
534
             * then the paragraph that was just inserted is the first paragraph
532
	    	return newP;
535
             * in the body. Otherwise, take the previous paragraph and calculate
533
    	}
536
             * the new index for the new paragraph.
534
    	return null;
537
             */
538
            if ((!(o instanceof CTP)) || (CTP) o == p) {
539
                paragraphs.add(0, newP);
540
            } else {
541
                int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1;
542
                paragraphs.add(pos, newP);
543
            }
544
545
            /*
546
             * create a new cursor, that points to the START token of the just
547
             * inserted paragraph
548
             */
549
            XmlCursor newParaPos = p.newCursor();
550
            try {
551
                /*
552
                 * Calculate the paragraphs index in the list of all body
553
                 * elements
554
                 */
555
                int i = 0;
556
                cursor.toCursor(newParaPos);
557
                while (cursor.toPrevSibling()) {
558
                    o = cursor.getObject();
559
                    if (o instanceof CTP || o instanceof CTTbl)
560
                        i++;
561
                }
562
                bodyElements.add(i, newP);
563
                cursor.toCursor(newParaPos);
564
                cursor.toEndToken();
565
                return newP;
566
            } finally {
567
                newParaPos.dispose();
568
            }
569
        }
570
        return null;
535
    }
571
    }
536
572
537
	public XWPFTable insertNewTbl(XmlCursor cursor) {
573
    public XWPFTable insertNewTbl(XmlCursor cursor) {
538
		if(isCursorInBody(cursor)){
574
        if (isCursorInBody(cursor)) {
539
			String uri = CTTbl.type.getName().getNamespaceURI();
575
            String uri = CTTbl.type.getName().getNamespaceURI();
540
			String localPart ="tbl";
576
            String localPart = "tbl";
541
    		cursor.beginElement(localPart,uri);
577
            cursor.beginElement(localPart, uri);
542
			cursor.toParent();
578
            cursor.toParent();
543
			CTTbl t = (CTTbl)cursor.getObject();
579
            CTTbl t = (CTTbl) cursor.getObject();
544
			XWPFTable newT = new XWPFTable(t, this);
580
            XWPFTable newT = new XWPFTable(t, this);
545
			cursor.removeXmlContents();
581
            cursor.removeXmlContents();
546
			XmlObject o = null;
582
            XmlObject o = null;
547
			while(!(o instanceof CTTbl)&&(cursor.toPrevSibling())){
583
            while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) {
548
				o = cursor.getObject();
584
                o = cursor.getObject();
549
			}
585
            }
550
			if(!(o instanceof CTTbl)){
586
            if (!(o instanceof CTTbl)) {
551
				tables.add(0, newT);
587
                tables.add(0, newT);
552
			}
588
            } else {
553
			else{
589
                int pos = tables.indexOf(getTable((CTTbl) o)) + 1;
554
				int pos = tables.indexOf(getTable((CTTbl)o))+1;
590
                tables.add(pos, newT);
555
				tables.add(pos,newT);
591
            }
556
			}
592
            int i = 0;
557
			int i=0;
593
            cursor = t.newCursor();
558
			cursor = t.newCursor();
594
            while (cursor.toPrevSibling()) {
559
			while(cursor.toPrevSibling()){
595
                o = cursor.getObject();
560
				o =cursor.getObject();
596
                if (o instanceof CTP || o instanceof CTTbl)
561
				if(o instanceof CTP || o instanceof CTTbl)
597
                    i++;
562
					i++;
598
            }
563
			}
599
            bodyElements.add(i, newT);
564
			bodyElements.add(i, newT);
600
            cursor = t.newCursor();
565
			cursor = t.newCursor();
601
            cursor.toEndToken();
566
			cursor.toEndToken();
602
            return newT;
567
			return newT;
603
        }
568
		}
604
        return null;
569
		return null;
605
    }
570
	}
606
571
    
607
    /**
572
	/**
608
     * verifies that cursor is on the right position
573
	 * verifies that cursor is on the right position
609
     * @param cursor
574
	 * @param cursor
610
     */
575
	 */
611
    private boolean isCursorInBody(XmlCursor cursor) {
576
	private boolean isCursorInBody(XmlCursor cursor) {
612
        XmlCursor verify = cursor.newCursor();
577
		XmlCursor verify = cursor.newCursor();
613
        verify.toParent();
578
		verify.toParent();
614
        try {
579
		if(verify.getObject() == this.ctDocument.getBody()){
615
            return (verify.getObject() == this.ctDocument.getBody());
580
			return true;
616
        } finally {
581
		}
617
            verify.dispose();
582
		XmlObject o = verify.getObject();
618
        }
583
		return false;
619
    }
584
		
620
585
	}
586
	
587
	private int getPosOfBodyElement(IBodyElement needle) {
621
	private int getPosOfBodyElement(IBodyElement needle) {
588
	   BodyElementType type = needle.getElementType();
622
	   BodyElementType type = needle.getElementType();
589
      IBodyElement current; 
623
      IBodyElement current; 
Lines 607-613 Link Here
607
	public int getPosOfParagraph(XWPFParagraph p){
641
	public int getPosOfParagraph(XWPFParagraph p){
608
	   return getPosOfBodyElement(p);
642
	   return getPosOfBodyElement(p);
609
    }
643
    }
610
	
644
611
	/**
645
	/**
612
	 * Get the position of the table, within the list of
646
	 * Get the position of the table, within the list of
613
	 *  all the body elements.
647
	 *  all the body elements.
Lines 648-662 Link Here
648
     * Appends a new paragraph to this document
682
     * Appends a new paragraph to this document
649
     * @return a new paragraph
683
     * @return a new paragraph
650
     */
684
     */
651
    public XWPFParagraph createParagraph(){
685
    public XWPFParagraph createParagraph() {
652
        XWPFParagraph p = new XWPFParagraph(ctDocument.getBody().addNewP(), this);
686
        XWPFParagraph p = new XWPFParagraph(ctDocument.getBody().addNewP(), this);
653
        bodyElements.add(p);
687
        bodyElements.add(p);
654
        paragraphs.add(p);
688
        paragraphs.add(p);
655
        return p;
689
        return p;
656
    }
690
    }
657
    
691
658
    /**
692
    /**
659
     * remove a BodyElement from bodyElements array list 
693
     * remove a BodyElement from bodyElements array list
660
     * @param pos
694
     * @param pos
661
     * @return true if removing was successfully, else return false
695
     * @return true if removing was successfully, else return false
662
     */
696
     */
Lines 684-707 Link Here
684
     * @param paragraph
718
     * @param paragraph
685
     * @param pos
719
     * @param pos
686
     */
720
     */
687
    public void setParagraph(XWPFParagraph paragraph, int pos){
721
    public void setParagraph(XWPFParagraph paragraph, int pos) {
688
    	paragraphs.set(pos, paragraph);
722
        paragraphs.set(pos, paragraph);
689
    	ctDocument.getBody().setPArray(pos, paragraph.getCTP());
723
        ctDocument.getBody().setPArray(pos, paragraph.getCTP());
724
        /* TODO update body element, update xwpf element, verify that
725
         * incoming paragraph belongs to this document or if not, XML was
726
         * copied properly (namespace-abbreviations, etc.)
727
         */
690
    }
728
    }
691
    
729
692
    /**
730
    /**
693
     * @return the LastParagraph of the document
731
     * @return the LastParagraph of the document
694
     */
732
     */
695
    public XWPFParagraph getLastParagraph(){
733
    public XWPFParagraph getLastParagraph() {
696
    	int lastPos = paragraphs.toArray().length - 1;
734
        int lastPos = paragraphs.toArray().length - 1;
697
    	return paragraphs.get(lastPos);
735
        return paragraphs.get(lastPos);
698
    }
736
    }
699
737
700
    /**
738
    /**
701
     * Create an empty table with one row and one column as default.
739
     * Create an empty table with one row and one column as default.
702
     * @return a new table
740
     * @return a new table
703
     */
741
     */
704
    public XWPFTable createTable(){
742
    public XWPFTable createTable() {
705
        XWPFTable table = new XWPFTable(ctDocument.getBody().addNewTbl(), this);
743
        XWPFTable table = new XWPFTable(ctDocument.getBody().addNewTbl(), this);
706
        bodyElements.add(table);
744
        bodyElements.add(table);
707
        tables.add(table);
745
        tables.add(table);
Lines 720-756 Link Here
720
       tables.add(table);
758
       tables.add(table);
721
       return table;
759
       return table;
722
    }
760
    }
723
    
761
724
    
725
    /**
762
    /**
726
     * 
763
     * 
727
     */
764
     */
728
    public void createTOC() {
765
    public void createTOC() {
729
        CTSdtBlock block = this.getDocument().getBody().addNewSdt();
766
        CTSdtBlock block = this.getDocument().getBody().addNewSdt();
730
        TOC toc = new TOC(block);
767
        TOC toc = new TOC(block);
731
        for (XWPFParagraph par: paragraphs ) {
768
        for (XWPFParagraph par : paragraphs) {
732
            String parStyle = par.getStyle();
769
            String parStyle = par.getStyle();
733
            if (parStyle != null && parStyle.substring(0, 7).equals("Heading")) {
770
            if (parStyle != null && parStyle.substring(0, 7).equals("Heading")) {
734
                try {
771
                try {
735
                    int level = Integer.valueOf(parStyle.substring("Heading".length())).intValue();
772
                    int level = Integer.valueOf(parStyle.substring("Heading".length())).intValue();
736
                    toc.addRow(level, par.getText(), 1, "112723803");
773
                    toc.addRow(level, par.getText(), 1, "112723803");
737
                }
774
                } catch (NumberFormatException e) {
738
                catch (NumberFormatException e) {
739
                    e.printStackTrace();
775
                    e.printStackTrace();
740
                }
776
                }
741
            }
777
            }
742
        }
778
        }
743
    }
779
    }
744
    
780
745
    /**Replace content of table in array tables at position pos with a
781
    /**Replace content of table in array tables at position pos with a
746
     * @param pos
782
     * @param pos
747
     * @param table
783
     * @param table
748
     */
784
     */
749
    public void setTable(int pos, XWPFTable table){
785
    public void setTable(int pos, XWPFTable table) {
750
    	tables.set(pos, table);
786
        tables.set(pos, table);
751
    	ctDocument.getBody().setTblArray(pos, table.getCTTbl());
787
        ctDocument.getBody().setTblArray(pos, table.getCTTbl());
752
    }
788
    }
753
    
789
754
    /**
790
    /**
755
     * Verifies that the documentProtection tag in settings.xml file <br/>
791
     * Verifies that the documentProtection tag in settings.xml file <br/>
756
     * specifies that the protection is enforced (w:enforcement="1") <br/>
792
     * specifies that the protection is enforced (w:enforcement="1") <br/>
Lines 831-837 Link Here
831
     *         &lt;w:documentProtection w:edit=&quot;readOnly&quot; w:enforcement=&quot;1&quot;/&gt;
867
     *         &lt;w:documentProtection w:edit=&quot;readOnly&quot; w:enforcement=&quot;1&quot;/&gt;
832
     * </pre>
868
     * </pre>
833
     */
869
     */
834
    public void enforceReadonlyProtection() { 
870
    public void enforceReadonlyProtection() {
835
        settings.setEnforcementEditValue(STDocProtect.READ_ONLY);
871
        settings.setEnforcementEditValue(STDocProtect.READ_ONLY);
836
    }
872
    }
837
873
Lines 849-855 Link Here
849
     */
885
     */
850
    public void enforceFillingFormsProtection() {
886
    public void enforceFillingFormsProtection() {
851
        settings.setEnforcementEditValue(STDocProtect.FORMS);
887
        settings.setEnforcementEditValue(STDocProtect.FORMS);
852
    } 
888
    }
853
889
854
    /**
890
    /**
855
     * Enforce the Comments protection.<br/>
891
     * Enforce the Comments protection.<br/>
Lines 880-886 Link Here
880
     * </pre>
916
     * </pre>
881
     */
917
     */
882
    public void enforceTrackedChangesProtection() {
918
    public void enforceTrackedChangesProtection() {
883
        settings.setEnforcementEditValue(STDocProtect.TRACKED_CHANGES);               
919
        settings.setEnforcementEditValue(STDocProtect.TRACKED_CHANGES);
884
    }
920
    }
885
921
886
    /**
922
    /**
Lines 892-1058 Link Here
892
        settings.removeEnforcement();
928
        settings.removeEnforcement();
893
    }
929
    }
894
930
895
	/**
896
	 * inserts an existing XWPFTable to the arrays bodyElements and tables
897
	 * @param pos
898
	 * @param table
899
	 */
900
	public void insertTable(int pos, XWPFTable table) {
901
		bodyElements.add(pos, table);
902
		int i;
903
    	for (i = 0; i < ctDocument.getBody().getTblList().size(); i++) {
904
			CTTbl tbl = ctDocument.getBody().getTblArray(i);
905
			if(tbl == table.getCTTbl()){
906
				break;
907
			}
908
		}
909
		tables.add(i, table);
910
	}
911
    
912
    public List<XWPFPictureData> getAllPictures() {
913
    	if(pictures == null){
914
    		pictures = new ArrayList<XWPFPictureData>();
915
    		for (POIXMLDocumentPart poixmlDocumentPart : getRelations()){
916
    			if(poixmlDocumentPart instanceof XWPFPictureData){
917
    				pictures.add((XWPFPictureData)poixmlDocumentPart);
918
    			}
919
    		}
920
    	}
921
    return pictures;
922
    }
923
    
924
    /**
931
    /**
925
     * @return  all Pictures in this package
932
     * inserts an existing XWPFTable to the arrays bodyElements and tables
933
     * @param pos
934
     * @param table
926
     */
935
     */
927
    public List<XWPFPictureData> getAllPackagePictures(){
936
    public void insertTable(int pos, XWPFTable table) {
928
    	List<XWPFPictureData> pkgpictures = new ArrayList<XWPFPictureData>();
937
        bodyElements.add(pos, table);
929
    	pkgpictures.addAll(getAllPictures());
938
        int i;
930
    	for (POIXMLDocumentPart poixmlDocumentPart : getRelations()){
939
        for (i = 0; i < ctDocument.getBody().getTblList().size(); i++) {
931
			if(poixmlDocumentPart instanceof XWPFHeaderFooter){
940
            CTTbl tbl = ctDocument.getBody().getTblArray(i);
932
				pkgpictures.addAll(((XWPFHeaderFooter)poixmlDocumentPart).getAllPictures());
941
            if (tbl == table.getCTTbl()) {
933
			}
942
                break;
934
		}
943
            }
935
    	return pkgpictures;
944
        }
945
        tables.add(i, table);
936
    }
946
    }
937
   
938
     /**
939
     * Adds a picture to the document. Users should normally call
940
     *  {@link XWPFRun#addPicture(InputStream, int)}
941
     *   
942
     *
943
     * @param is                The stream to read image from
944
     * @param format            The format of the picture, eg {@link Document#PICTURE_TYPE_JPEG}
945
947
946
     *
948
    /**
947
     * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} .
949
     * Returns all Pictures, which are referenced from the document itself.
948
     * @throws InvalidFormatException 
950
     * @return a {@link List} of {@link XSLFPictureData}. The returned {@link List} is unmodifiable. Use #a
949
     */
951
     */
950
    public int addPicture(InputStream is, int format) throws IOException, InvalidFormatException {
952
    public List<XWPFPictureData> getAllPictures() {
951
        int imageNumber = getNextPicNameNumber(format);
953
        return Collections.unmodifiableList(pictures);
952
        XWPFPictureData img = (XWPFPictureData)createRelationship(XWPFPictureData.RELATIONS[format], XWPFFactory.getInstance(), imageNumber, false);
953
        OutputStream out = img.getPackagePart().getOutputStream();
954
        IOUtils.copy(is, out);
955
        out.close();
956
        pictures.add(img);
957
        return getAllPictures().size()-1;
958
    }
954
    }
959
    
955
960
    /**
956
    /**
961
     * Adds a picture to the document. Users should normally call
957
     * @return all Pictures in this package
962
     *  {@link XWPFRun#addPicture(InputStream, int)}
963
     *
964
     * @param pictureData       The bytes to read image from
965
     * @param format            The format of the picture, eg {@link Document#PICTURE_TYPE_JPEG}
966
     *
967
     * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} .
968
     * @throws InvalidFormatException 
969
     */
958
     */
970
    public int addPicture(byte[] pictureData, int format) throws InvalidFormatException {
959
    public List<XWPFPictureData> getAllPackagePictures() {
960
        List<XWPFPictureData> result = new ArrayList<XWPFPictureData>();
961
        Collection<List<XWPFPictureData>> values = packagePictures.values();
962
        for (List<XWPFPictureData> list : values) {
963
            result.addAll(list);
964
        }
965
        return Collections.unmodifiableList(result);
966
    }
967
968
    void registerPackagePictureData(XWPFPictureData picData) {
969
        List<XWPFPictureData> list = packagePictures.get(picData.getChecksum());
970
        if (list == null) {
971
            list = new ArrayList<XWPFPictureData>(1);
972
            packagePictures.put(picData.getChecksum(), list);
973
        }
974
        if (!list.contains(picData))
975
        {
976
            list.add(picData);
977
        }
978
    }
979
    
980
    XWPFPictureData findPackagePictureData(byte[] pictureData, int format)
981
    {
982
        Long checksum = IOUtils.calculateChecksum(pictureData);
983
        XWPFPictureData xwpfPicData = null;
984
        /*
985
         * Try to find PictureData with this checksum. Create new, if none
986
         * exists.
987
         */
988
        List<XWPFPictureData> xwpfPicDataList = packagePictures.get(checksum);
989
        if (xwpfPicDataList != null) {
990
            Iterator<XWPFPictureData> iter = xwpfPicDataList.iterator();
991
            while (iter.hasNext() && xwpfPicData == null) {
992
                XWPFPictureData curElem = iter.next();
993
                if (Arrays.equals(pictureData, curElem.getData())) {
994
                    xwpfPicData = curElem;
995
                }
996
            }
997
        } 
998
        return xwpfPicData;
999
    }
1000
1001
    public String addPictureData(byte[] pictureData,int format) throws InvalidFormatException
1002
    {
1003
        XWPFPictureData xwpfPicData = findPackagePictureData(pictureData, format);
1004
        POIXMLRelation relDesc = XWPFPictureData.RELATIONS[format];
1005
        
1006
        if (xwpfPicData == null)
1007
        {
1008
            /* Part doesn't exist, create a new one */
1009
            int idx = getNextPicNameNumber(format);
1010
            xwpfPicData = (XWPFPictureData) createRelationship(relDesc, XWPFFactory.getInstance(),idx);
1011
            /* write bytes to new part */
1012
            PackagePart picDataPart = xwpfPicData.getPackagePart();
1013
            OutputStream out = null;
1014
            try {
1015
                out = picDataPart.getOutputStream();
1016
                out.write(pictureData);
1017
            } catch (IOException e) {
1018
                throw new POIXMLException(e);
1019
            } finally {
1020
                try {
1021
                    out.close();
1022
                } catch (IOException e) {
1023
                    // ignore
1024
                }
1025
            }
1026
1027
            registerPackagePictureData(xwpfPicData);
1028
            pictures.add(xwpfPicData);
1029
            
1030
            return getRelationId(xwpfPicData);
1031
        }
1032
        else if (!getRelations().contains(xwpfPicData))
1033
        {
1034
            /*
1035
             * Part already existed, but was not related so far. Create
1036
             * relationship to the already existing part and update
1037
             * POIXMLDocumentPart data.
1038
             */
1039
            PackagePart picDataPart = xwpfPicData.getPackagePart();
1040
            // TODO add support for TargetMode.EXTERNAL relations.
1041
            TargetMode targetMode = TargetMode.INTERNAL;
1042
            PackagePartName partName = picDataPart.getPartName();
1043
            String relation = relDesc.getRelation();
1044
            PackageRelationship relShip = getPackagePart().addRelationship(partName,targetMode,relation);
1045
            String id = relShip.getId();
1046
            addRelation(id,xwpfPicData);
1047
            pictures.add(xwpfPicData);
1048
            return id;
1049
        }
1050
        else 
1051
        {
1052
            /* Part already existed, get relation id and return it */
1053
            return getRelationId(xwpfPicData);
1054
        }
1055
    }
1056
    
1057
    public String addPictureData(InputStream is,int format) throws InvalidFormatException
1058
    {
971
        try {
1059
        try {
972
           return addPicture(new ByteArrayInputStream(pictureData), format);
1060
            byte[] data = IOUtils.toByteArray(is);
973
        } catch (IOException e){
1061
            return addPictureData(data, format);
1062
        } catch (IOException e) {
974
            throw new POIXMLException(e);
1063
            throw new POIXMLException(e);
975
        }
1064
        }
976
    }
1065
    }
977
    
1066
978
    /**
1067
    /**
979
     * get the next free ImageNumber
1068
     * get the next free ImageNumber
980
     * @param format
1069
     * @param format
981
     * @return the next free ImageNumber
1070
     * @return the next free ImageNumber
982
     * @throws InvalidFormatException 
1071
     * @throws InvalidFormatException 
983
     */
1072
     */
984
    public int getNextPicNameNumber(int format) throws InvalidFormatException{
1073
    public int getNextPicNameNumber(int format) throws InvalidFormatException {
985
    	int img = getAllPackagePictures().size()+1;
1074
        int img = getAllPackagePictures().size() + 1;
986
   		String proposal = XWPFPictureData.RELATIONS[format].getFileName(img);
1075
        String proposal = XWPFPictureData.RELATIONS[format].getFileName(img);
987
   		PackagePartName createPartName = PackagingURIHelper.createPartName(proposal);
1076
        PackagePartName createPartName = PackagingURIHelper.createPartName(proposal);
988
		while (this.getPackage().getPart(createPartName)!= null){
1077
        while (this.getPackage().getPart(createPartName) != null) {
989
			img++;
1078
            img++;
990
			proposal = XWPFPictureData.RELATIONS[format].getFileName(img);
1079
            proposal = XWPFPictureData.RELATIONS[format].getFileName(img);
991
			createPartName = PackagingURIHelper.createPartName(proposal);
1080
            createPartName = PackagingURIHelper.createPartName(proposal);
992
		}
1081
        }
993
    	return img;
1082
        return img;
994
    }
1083
    }
995
	
1084
996
    /**
1085
    /**
997
     * returns the PictureData by blipID
1086
     * returns the PictureData by blipID
998
     * @param blipID
1087
     * @param blipID
999
     * @return XWPFPictureData of a specificID
1088
     * @return XWPFPictureData of a specificID
1000
     * @throws Exception 
1001
     */
1089
     */
1002
    public XWPFPictureData getPictureDataByID(String blipID) {
1090
    public XWPFPictureData getPictureDataByID(String blipID) {
1003
    	for(POIXMLDocumentPart part: getRelations()){
1091
        POIXMLDocumentPart relatedPart = getRelationById(blipID);
1004
    	  if(part.getPackageRelationship() != null){
1092
        if (relatedPart instanceof XWPFPictureData) {
1005
    		  if(part.getPackageRelationship().getId() != null){
1093
            XWPFPictureData xwpfPicData = (XWPFPictureData) relatedPart;
1006
    			  if(part.getPackageRelationship().getId().equals(blipID)){
1094
            return xwpfPicData;
1007
    				  return (XWPFPictureData)part;
1095
        }
1008
    			  }
1096
        return null;
1009
    		  }
1010
    	  	}
1011
    	}
1012
		return null;	    	
1013
    }
1097
    }
1014
    
1098
1015
    /**
1099
    /**
1016
     *  getNumbering
1100
     * getNumbering
1017
     * @return numbering
1101
     * @return numbering
1018
     */
1102
     */
1019
    public XWPFNumbering getNumbering(){
1103
    public XWPFNumbering getNumbering() {
1020
    	return numbering;
1104
        return numbering;
1021
    }
1105
    }
1022
1106
1023
	/**
1107
    /**
1024
	 * get Styles 
1108
     * get Styles
1025
	 * @return  styles for this document
1109
     * @return styles for this document
1026
	 */
1110
     */
1027
	public XWPFStyles getStyles(){
1111
    public XWPFStyles getStyles() {
1028
		return styles;
1112
        return styles;
1029
	}
1113
    }
1030
	
1114
1031
	/**
1115
    /**
1032
	 *  get the paragraph with the CTP class p
1116
     * get the paragraph with the CTP class p
1033
     *
1117
     * 
1034
	 * @param p
1118
     * @param p
1035
	 * @return  the paragraph with the CTP class p
1119
     * @return the paragraph with the CTP class p
1036
	 */
1120
     */
1037
	public XWPFParagraph getParagraph(CTP p){
1121
    public XWPFParagraph getParagraph(CTP p) {
1038
		for(int i=0; i<getParagraphs().size(); i++){
1122
        for (int i = 0; i < getParagraphs().size(); i++) {
1039
			if(getParagraphs().get(i).getCTP() == p) return getParagraphs().get(i); 
1123
            if (getParagraphs().get(i).getCTP() == p) {
1040
		}
1124
                return getParagraphs().get(i);
1041
		return null;
1125
            }
1042
	}
1126
        }
1043
	
1127
        return null;
1044
	/**
1128
    }
1045
	 * get a table by its CTTbl-Object
1129
1046
	 * @param ctTbl
1130
    /**
1047
	 * @see org.apache.poi.xwpf.usermodel.IBody#getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl)
1131
     * get a table by its CTTbl-Object
1048
	 * @return a table by its CTTbl-Object or null
1132
     * @param ctTbl
1049
	 */
1133
     * @see org.apache.poi.xwpf.usermodel.IBody#getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl)
1134
     * @return a table by its CTTbl-Object or null
1135
     */
1050
    public XWPFTable getTable(CTTbl ctTbl) {
1136
    public XWPFTable getTable(CTTbl ctTbl) {
1051
		for(int i=0; i<tables.size(); i++){
1137
        for (int i = 0; i < tables.size(); i++) {
1052
			if(getTables().get(i).getCTTbl() == ctTbl) return getTables().get(i); 
1138
            if (getTables().get(i).getCTTbl() == ctTbl) {
1053
		}
1139
                return getTables().get(i);
1054
		return null;
1140
            }
1055
	}
1141
        }
1142
        return null;
1143
    }
1056
1144
1057
1145
1058
	public Iterator<XWPFTable> getTablesIterator() {
1146
	public Iterator<XWPFTable> getTablesIterator() {
Lines 1074-1095 Link Here
1074
		return null;
1162
		return null;
1075
	}
1163
	}
1076
1164
1077
1165
    /**
1078
1166
     * returns the Part, to which the body belongs, which you need for adding relationship to other parts
1079
	/**
1167
     * Actually it is needed of the class XWPFTableCell. Because you have to know to which part the tableCell
1080
	 * returns the Part, to which the body belongs, which you need for adding relationship to other parts
1168
     * belongs.
1081
	 * Actually it is needed of the class XWPFTableCell. Because you have to know to which part the tableCell
1169
     * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
1082
	 * belongs.
1170
     */
1083
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
1171
    public POIXMLDocumentPart getPart() {
1084
	 */
1172
        return this;
1085
	public IBody getPart() {
1173
    }
1086
		return this;
1087
	}
1088
1174
1089
	/**
1175
	/**
1090
	 * get the PartType of the body, for example
1176
	 * get the PartType of the body, for example
1091
	 * DOCUMENT, HEADER, FOOTER,	FOOTNOTE,
1177
	 * DOCUMENT, HEADER, FOOTER,	FOOTNOTE,
1092
     *
1093
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
1178
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
1094
	 */
1179
	 */
1095
	public BodyType getPartType() {
1180
	public BodyType getPartType() {
Lines 1129-1132 Link Here
1129
    public XWPFDocument getXWPFDocument() {
1214
    public XWPFDocument getXWPFDocument() {
1130
        return this;
1215
        return this;
1131
    }
1216
    }
1132
}//end class
1217
} // end class
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java (-10 / +9 lines)
Lines 20-25 Link Here
20
import java.util.Collections;
20
import java.util.Collections;
21
import java.util.List;
21
import java.util.List;
22
22
23
import org.apache.poi.POIXMLDocumentPart;
23
import org.apache.poi.util.Internal;
24
import org.apache.poi.util.Internal;
24
import org.apache.xmlbeans.XmlCursor;
25
import org.apache.xmlbeans.XmlCursor;
25
import org.apache.xmlbeans.XmlObject;
26
import org.apache.xmlbeans.XmlObject;
Lines 248-263 Link Here
248
		return null;
249
		return null;
249
	}
250
	}
250
251
251
252
    /**
252
253
     * get the to which the TableCell belongs
253
254
     * 
254
	/**
255
     * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
255
	 * get the to which the TableCell belongs 
256
     */
256
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
257
    public POIXMLDocumentPart getPart() {
257
	 */
258
        return tableRow.getTable().getPart();
258
	public IBody getPart() {
259
    }
259
		return tableRow.getTable().getPart();
260
	}
261
260
262
261
263
	/** 
262
	/** 
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java (-1 / +1 lines)
Lines 213-219 Link Here
213
        XSSFPictureData data = wb.getAllPictures().get(pictureIndex);
213
        XSSFPictureData data = wb.getAllPictures().get(pictureIndex);
214
        PackagePartName ppName = data.getPackagePart().getPartName();
214
        PackagePartName ppName = data.getPackagePart().getPartName();
215
        PackageRelationship rel = getPackagePart().addRelationship(ppName, TargetMode.INTERNAL, XSSFRelation.IMAGES.getRelation());
215
        PackageRelationship rel = getPackagePart().addRelationship(ppName, TargetMode.INTERNAL, XSSFRelation.IMAGES.getRelation());
216
        addRelation(new XSSFPictureData(data.getPackagePart(), rel));
216
        addRelation(rel.getId(),new XSSFPictureData(data.getPackagePart(), rel));
217
        return rel;
217
        return rel;
218
    }
218
    }
219
219
(-)src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java (-70 / +219 lines)
Lines 17-31 Link Here
17
package org.apache.poi;
17
package org.apache.poi;
18
18
19
import java.io.IOException;
19
import java.io.IOException;
20
import java.util.*;
21
import java.net.URI;
20
import java.net.URI;
21
import java.util.ArrayList;
22
import java.util.Collection;
23
import java.util.Collections;
24
import java.util.HashMap;
25
import java.util.Iterator;
26
import java.util.List;
27
import java.util.Map;
28
import java.util.Set;
29
import java.util.Map.Entry;
22
30
23
import org.apache.xmlbeans.XmlOptions;
24
import org.apache.poi.util.POILogger;
25
import org.apache.poi.util.POILogFactory;
26
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
31
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
27
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
32
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
28
import org.apache.poi.openxml4j.opc.*;
33
import org.apache.poi.openxml4j.opc.OPCPackage;
34
import org.apache.poi.openxml4j.opc.PackagePart;
35
import org.apache.poi.openxml4j.opc.PackagePartName;
36
import org.apache.poi.openxml4j.opc.PackageRelationship;
37
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
38
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
39
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
40
import org.apache.poi.openxml4j.opc.TargetMode;
41
import org.apache.poi.util.POILogFactory;
42
import org.apache.poi.util.POILogger;
43
import org.apache.xmlbeans.XmlOptions;
29
44
30
/**
45
/**
31
 * Represents an entry of a OOXML package.
46
 * Represents an entry of a OOXML package.
Lines 47-65 Link Here
47
        DEFAULT_XML_OPTIONS.setSaveAggressiveNamespaces();
62
        DEFAULT_XML_OPTIONS.setSaveAggressiveNamespaces();
48
    }
63
    }
49
64
65
    /**
66
     * Get the PackagePart that is the target of a relationship.
67
     *
68
     * @param rel The relationship
69
     * @param pkg The package to fetch from
70
     * @return The target part
71
     * @throws InvalidFormatException
72
     */
73
    protected static PackagePart getTargetPart(OPCPackage pkg, PackageRelationship rel)
74
    throws InvalidFormatException {
75
        PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
76
        PackagePart part = pkg.getPart(relName);
77
        if (part == null) {
78
            throw new IllegalArgumentException("No part found for relationship " + rel);
79
        }
80
        return part;
81
    }
82
50
    private PackagePart packagePart;
83
    private PackagePart packagePart;
51
    private PackageRelationship packageRel;
84
    private PackageRelationship packageRel;
52
    private POIXMLDocumentPart parent;
85
    private POIXMLDocumentPart parent;
53
    private List<POIXMLDocumentPart> relations;
86
    private Map<String,POIXMLDocumentPart> relations = new HashMap<String,POIXMLDocumentPart>();
87
    private List<POIXMLDocumentPart> relationsOrder = new ArrayList<POIXMLDocumentPart>();
88
    
89
    /**
90
     * Counter that provides the amount of incoming relations from other parts
91
     * to this part.
92
     */
93
    private int relationCounter = 0;
94
95
    int incrementRelationCounter() {
96
        relationCounter++;
97
        return relationCounter;
98
    }
99
100
    int decrementRelationCounter() {
101
        relationCounter--;
102
        return relationCounter;
103
    }
104
105
    int getRelationCounter() {
106
        return relationCounter;
107
    }
54
108
55
    /**
109
    /**
56
     * Construct POIXMLDocumentPart representing a "core document" package part.
110
     * Construct POIXMLDocumentPart representing a "core document" package part.
57
     */
111
     */
58
    public POIXMLDocumentPart(OPCPackage pkg) {
112
    public POIXMLDocumentPart(OPCPackage pkg) {
59
        PackageRelationship coreRel = pkg.getRelationshipsByType(
113
        PackageRelationship coreRel = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT).getRelationship(0);
60
                PackageRelationshipTypes.CORE_DOCUMENT).getRelationship(0);
61
114
62
        this.relations = new LinkedList<POIXMLDocumentPart>();
63
        this.packagePart = pkg.getPart(coreRel);
115
        this.packagePart = pkg.getPart(coreRel);
64
        this.packageRel = coreRel;
116
        this.packageRel = coreRel;
65
    }
117
    }
Lines 70-76 Link Here
70
     * @see #createRelationship(POIXMLRelation, POIXMLFactory, int, boolean)
122
     * @see #createRelationship(POIXMLRelation, POIXMLFactory, int, boolean)
71
     */
123
     */
72
    public POIXMLDocumentPart(){
124
    public POIXMLDocumentPart(){
73
        this.relations = new LinkedList<POIXMLDocumentPart>();
74
    }
125
    }
75
126
76
    /**
127
    /**
Lines 82-88 Link Here
82
     * @see #read(POIXMLFactory, java.util.Map) 
133
     * @see #read(POIXMLFactory, java.util.Map) 
83
     */
134
     */
84
    public POIXMLDocumentPart(PackagePart part, PackageRelationship rel){
135
    public POIXMLDocumentPart(PackagePart part, PackageRelationship rel){
85
        this.relations = new LinkedList<POIXMLDocumentPart>();
86
        this.packagePart = part;
136
        this.packagePart = part;
87
        this.packageRel = rel;
137
        this.packageRel = rel;
88
    }
138
    }
Lines 97-103 Link Here
97
     * @see #read(POIXMLFactory, java.util.Map)
147
     * @see #read(POIXMLFactory, java.util.Map)
98
     */
148
     */
99
    public POIXMLDocumentPart(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel){
149
    public POIXMLDocumentPart(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel){
100
        this.relations = new LinkedList<POIXMLDocumentPart>();
101
        this.packagePart = part;
150
        this.packagePart = part;
102
        this.packageRel = rel;
151
        this.packageRel = rel;
103
        this.parent = parent;
152
        this.parent = parent;
Lines 109-124 Link Here
109
     *  current core document 
158
     *  current core document 
110
     */
159
     */
111
    protected final void rebase(OPCPackage pkg) throws InvalidFormatException {
160
    protected final void rebase(OPCPackage pkg) throws InvalidFormatException {
112
       PackageRelationshipCollection cores =
161
        PackageRelationshipCollection cores =
113
          packagePart.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT);
162
            packagePart.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT);
114
       if(cores.size() != 1) {
163
        if(cores.size() != 1) {
115
          throw new IllegalStateException(
164
            throw new IllegalStateException(
116
                "Tried to rebase using " + PackageRelationshipTypes.CORE_DOCUMENT +
165
                "Tried to rebase using " + PackageRelationshipTypes.CORE_DOCUMENT +
117
                " but found " + cores.size() + " parts of the right type"
166
                " but found " + cores.size() + " parts of the right type"
118
          );
167
            );
119
       }
168
        }
120
       packageRel = cores.getRelationship(0);
169
        packageRel = cores.getRelationship(0);
121
       packagePart = POIXMLDocument.getTargetPart(pkg, packageRel);
170
        packagePart = POIXMLDocument.getTargetPart(pkg, packageRel);
122
    }
171
    }
123
172
124
    /**
173
    /**
Lines 145-151 Link Here
145
     * @return child relations
194
     * @return child relations
146
     */
195
     */
147
    public final List<POIXMLDocumentPart> getRelations(){
196
    public final List<POIXMLDocumentPart> getRelations(){
148
        return relations;
197
        return Collections.unmodifiableList(relationsOrder);
198
    }
199
200
    /**
201
     * Returns the target {@link POIXMLDocumentPart}, where a
202
     * {@link PackageRelationship} is set from the {@link PackagePart} of this
203
     * {@link POIXMLDocumentPart} to the {@link PackagePart} of the target
204
     * {@link POIXMLDocumentPart} with a {@link PackageRelationship#getId()}
205
     * matching the given parameter value.
206
     * 
207
     * @param id
208
     *            The relation id to look for
209
     * @return the target part of the relation, or null, if none exists
210
     */
211
    public final POIXMLDocumentPart getRelationById(String id) {
212
        return relations.get(id);
213
    }
214
215
    /**
216
     * Returns the {@link PackageRelationship#getId()} of the
217
     * {@link PackageRelationship}, that sources from the {@link PackagePart} of
218
     * this {@link POIXMLDocumentPart} to the {@link PackagePart} of the given
219
     * parameter value.
220
     * 
221
     * @param part
222
     *            The {@link POIXMLDocumentPart} for which the according
223
     *            relation-id shall be found.
224
     * @return The value of the {@link PackageRelationship#getId()} or null, if
225
     *         parts are not related.
226
     */
227
    public final String getRelationId(POIXMLDocumentPart part) {
228
        Iterator<Entry<String, POIXMLDocumentPart>> iter = relations.entrySet().iterator();
229
        while (iter.hasNext())
230
        {
231
            Entry<String, POIXMLDocumentPart> entry = iter.next();
232
            if (entry.getValue() == part) {
233
                return entry.getKey();
234
            }
235
        }
236
        return null;
149
    }
237
    }
150
238
151
    /**
239
    /**
Lines 153-169 Link Here
153
     *
241
     *
154
     * @param part the child to add
242
     * @param part the child to add
155
     */
243
     */
156
    protected final void addRelation(POIXMLDocumentPart part){
244
    protected final void addRelation(String id,POIXMLDocumentPart part){
157
        relations.add(part);
245
        relations.put(id,part);
246
        relationsOrder.add(part);
247
        part.incrementRelationCounter();
158
    }
248
    }
159
249
160
    /**
250
    /**
161
     * Remove the specified part in this package.
251
     * Remove the relation to the specified part in this package and remove the
252
     * part, if it is no longer needed.
162
     */
253
     */
163
    public final void removeRelation(POIXMLDocumentPart part){
254
    protected final void removeRelation(POIXMLDocumentPart part){
164
        getPackagePart().removeRelationship(part.getPackageRelationship().getId());
255
        removeRelation(part,true);
165
        getPackagePart().getPackage().removePart(part.getPackagePart());
256
    }
166
        relations.remove(part);
257
258
    /**
259
     * Remove the relation to the specified part in this package and remove the
260
     * part, if it is no longer needed and flag is set to true.
261
     * 
262
     * @param part
263
     *            The related part, to which the relation shall be removed.
264
     * @param removeUnusedParts
265
     *            true, if the part shall be removed from the package if not
266
     *            needed any longer.
267
     */
268
    protected final boolean removeRelation(POIXMLDocumentPart part, boolean removeUnusedParts){
269
        String id = getRelationId(part);
270
        if (id == null) {
271
            // part is not related with this POIXMLDocumentPart
272
            return false;
273
        }
274
        /* decrement usage counter */
275
        part.decrementRelationCounter();
276
        /* remove packagepart relationship */
277
        getPackagePart().removeRelationship(id);
278
        /* remove POIXMLDocument from relations */
279
        relations.remove(id);
280
        relationsOrder.remove(part);
281
282
        if (removeUnusedParts) {
283
            /* if last relation to target part was removed, delete according target part */
284
            if (part.getRelationCounter() == 0) {
285
                try {
286
                    part.onDocumentRemove();
287
                } catch (IOException e) {
288
                    throw new POIXMLException(e);
289
                }
290
                getPackagePart().getPackage().removePart(part.getPackagePart());
291
            }
292
        }
293
        return true;
167
    }
294
    }
168
295
169
    /**
296
    /**
Lines 209-221 Link Here
209
     * @param alreadySaved    context set containing already visited nodes
336
     * @param alreadySaved    context set containing already visited nodes
210
     */
337
     */
211
    protected final void onSave(Set<PackagePart> alreadySaved) throws IOException{
338
    protected final void onSave(Set<PackagePart> alreadySaved) throws IOException{
212
    	commit();
339
        commit();
213
    	alreadySaved.add(this.getPackagePart());
340
        alreadySaved.add(this.getPackagePart());
214
    	for(POIXMLDocumentPart p : relations){
341
        for(POIXMLDocumentPart p : relationsOrder){
215
            if (!alreadySaved.contains(p.getPackagePart())) {
342
            if (!alreadySaved.contains(p.getPackagePart())) {
216
    			p.onSave(alreadySaved);
343
                p.onSave(alreadySaved);
217
    		}
344
            }
218
    	}
345
        }
219
    }
346
    }
220
347
221
    /**
348
    /**
Lines 246-260 Link Here
246
        try {
373
        try {
247
            PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx));
374
            PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx));
248
            PackageRelationship rel = null;
375
            PackageRelationship rel = null;
376
            PackagePart part = packagePart.getPackage().createPart(ppName, descriptor.getContentType());
249
            if(!noRelation) {
377
            if(!noRelation) {
250
               rel = packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation());
378
                /* only add to relations, if according relationship is being created. */
379
                rel = packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation());
251
            }
380
            }
252
            PackagePart part = packagePart.getPackage().createPart(ppName, descriptor.getContentType());
253
            POIXMLDocumentPart doc = factory.newDocumentPart(descriptor);
381
            POIXMLDocumentPart doc = factory.newDocumentPart(descriptor);
254
            doc.packageRel = rel;
382
            doc.packageRel = rel;
255
            doc.packagePart = part;
383
            doc.packagePart = part;
256
            doc.parent = this;
384
            doc.parent = this;
257
            addRelation(doc);
385
            if(!noRelation) {
386
                /* only add to relations, if according relationship is being created. */
387
                addRelation(rel.getId(),doc);
388
            }
258
            return doc;
389
            return doc;
259
        } catch (Exception e){
390
        } catch (Exception e){
260
            throw new POIXMLException(e);
391
            throw new POIXMLException(e);
Lines 269-308 Link Here
269
     * @param context   context map containing already visited noted keyed by targetURI
400
     * @param context   context map containing already visited noted keyed by targetURI
270
     */
401
     */
271
    protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException {
402
    protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException {
272
    	PackageRelationshipCollection rels = packagePart.getRelationships();
403
        PackageRelationshipCollection rels = packagePart.getRelationships();
273
    	for (PackageRelationship rel : rels) {
404
        for (PackageRelationship rel : rels) {
274
    	   if(rel.getTargetMode() == TargetMode.INTERNAL){
405
            if(rel.getTargetMode() == TargetMode.INTERNAL){
275
    	      URI uri = rel.getTargetURI();
406
                URI uri = rel.getTargetURI();
276
407
277
    	      PackagePart p;
408
                PackagePart p;
278
    	      if(uri.getRawFragment() != null) {
409
                if(uri.getRawFragment() != null) {
279
    	         /*
410
                    /*
280
    	          * For internal references (e.g. '#Sheet1!A1') the package part is null
411
                     * For internal references (e.g. '#Sheet1!A1') the package part is null
281
    	          */
412
                     */
282
    	         p = null;
413
                    p = null;
283
    	      } else {
414
                } else {
284
    	         PackagePartName relName = PackagingURIHelper.createPartName(uri);
415
                    PackagePartName relName = PackagingURIHelper.createPartName(uri);
285
    	         p = packagePart.getPackage().getPart(relName);
416
                    p = packagePart.getPackage().getPart(relName);
286
    	         if(p == null) {
417
                    if(p == null) {
287
    	            logger.log(POILogger.ERROR, "Skipped invalid entry " + rel.getTargetURI());
418
                        logger.log(POILogger.ERROR, "Skipped invalid entry " + rel.getTargetURI());
288
    	            continue;
419
                        continue;
289
    	         }
420
                    }
290
    	      }
421
                }
291
422
292
    	      if (!context.containsKey(p)) {
423
                if (!context.containsKey(p)) {
293
    	         POIXMLDocumentPart childPart = factory.createDocumentPart(this, rel, p);
424
                    POIXMLDocumentPart childPart = factory.createDocumentPart(this, rel, p);
294
    	         childPart.parent = this;
425
                    childPart.parent = this;
295
    	         addRelation(childPart);
426
                    addRelation(rel.getId(),childPart);
296
    	         if(p != null){
427
                    if(p != null){
297
    	            context.put(p, childPart);
428
                        context.put(p, childPart);
298
    	            if(p.hasRelationships()) childPart.read(factory, context);
429
                        if(p.hasRelationships()) childPart.read(factory, context);
299
    	         }
430
                    }
300
    	      }
431
                }
301
    	      else {
432
                else {
302
    	         addRelation(context.get(p));
433
                    addRelation(rel.getId(),context.get(p));
303
    	      }
434
                }
304
    	   }
435
            }
305
    	}
436
        }
306
    }
437
    }
307
438
308
    /**
439
    /**
Lines 315-321 Link Here
315
    /**
446
    /**
316
     * Fired when a package part is read
447
     * Fired when a package part is read
317
     */
448
     */
318
    protected void onDocumentRead() throws IOException{
449
    protected void onDocumentRead() throws IOException {
450
451
    }
452
453
    /**
454
     * Get the PackagePart that is the target of a relationship.
455
     *
456
     * @param rel The relationship
457
     * @return The target part
458
     * @throws InvalidFormatException
459
     */
460
    protected PackagePart getTargetPart(PackageRelationship rel) throws InvalidFormatException {
461
        return getTargetPart(getPackagePart().getPackage(), rel);
462
    }
463
464
    /**
465
     * Fired when a package part is about to be removed from the package
466
     */
467
    protected void onDocumentRemove() throws IOException {
319
468
320
    }
469
    }
321
}
470
}
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSettings.java (-1 / +6 lines)
Lines 40-46 Link Here
40
40
41
    public XWPFSettings(PackagePart part, PackageRelationship rel) throws IOException {
41
    public XWPFSettings(PackagePart part, PackageRelationship rel) throws IOException {
42
        super(part, rel);
42
        super(part, rel);
43
        readFrom(part.getInputStream());
44
    }
43
    }
45
44
46
    public XWPFSettings() {
45
    public XWPFSettings() {
Lines 48-53 Link Here
48
        ctSettings = CTSettings.Factory.newInstance();
47
        ctSettings = CTSettings.Factory.newInstance();
49
    }
48
    }
50
49
50
    @Override
51
    protected void onDocumentRead() throws IOException
52
    {
53
        super.onDocumentRead();
54
        readFrom(getPackagePart().getInputStream());
55
    }
51
56
52
    /**
57
    /**
53
     * Verifies the documentProtection tag inside settings.xml file <br/>
58
     * Verifies the documentProtection tag inside settings.xml file <br/>
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java (-50 / +62 lines)
Lines 21-26 Link Here
21
import java.util.Collections;
21
import java.util.Collections;
22
import java.util.List;
22
import java.util.List;
23
23
24
import org.apache.poi.POIXMLDocumentPart;
24
import org.apache.poi.util.Internal;
25
import org.apache.poi.util.Internal;
25
import org.apache.xmlbeans.XmlCursor;
26
import org.apache.xmlbeans.XmlCursor;
26
import org.apache.xmlbeans.XmlObject;
27
import org.apache.xmlbeans.XmlObject;
Lines 50-66 Link Here
50
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
51
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
51
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTextAlignment;
52
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTextAlignment;
52
53
53
54
/**
54
/**
55
 * Sketch of XWPF paragraph class
55
 * Sketch of XWPF paragraph class
56
 */
56
 */
57
public class XWPFParagraph implements IBodyElement{
57
public class XWPFParagraph implements IBodyElement {
58
    private final CTP paragraph;
58
    private final CTP paragraph;
59
    protected IBody part;
59
    protected IBody part;
60
    /** For access to the document's hyperlink, comments, tables etc */
60
    /** For access to the document's hyperlink, comments, tables etc */
61
    protected XWPFDocument document;
61
    protected XWPFDocument document;
62
    protected List<XWPFRun> runs;
62
    protected List<XWPFRun> runs;
63
    
63
64
    private StringBuffer footnoteText = new StringBuffer();
64
    private StringBuffer footnoteText = new StringBuffer();
65
65
66
    public XWPFParagraph(CTP prgrph, IBody part) {
66
    public XWPFParagraph(CTP prgrph, IBody part) {
Lines 260-268 Link Here
260
     * @return a new text run
260
     * @return a new text run
261
     */
261
     */
262
    public XWPFRun createRun() {
262
    public XWPFRun createRun() {
263
       XWPFRun run = new XWPFRun(paragraph.addNewR(), this);
263
        XWPFRun xwpfRun = new XWPFRun(paragraph.addNewR(), this);
264
       runs.add(run);
264
        runs.add(xwpfRun);
265
       return run;
265
        return xwpfRun;
266
    }
266
    }
267
267
268
    /**
268
    /**
Lines 1233-1285 Link Here
1233
    	 return false;
1233
    	 return false;
1234
    }
1234
    }
1235
1235
1236
	/**
1236
    /**
1237
	 * returns the type of the BodyElement Paragraph
1237
     * returns the type of the BodyElement Paragraph
1238
	 * @see org.apache.poi.xwpf.usermodel.IBodyElement#getElementType()
1238
     * @see org.apache.poi.xwpf.usermodel.IBodyElement#getElementType()
1239
	 */
1239
     */
1240
	public BodyElementType getElementType() {
1240
    public BodyElementType getElementType() {
1241
		return BodyElementType.PARAGRAPH;
1241
        return BodyElementType.PARAGRAPH;
1242
	}
1242
    }
1243
1244
	/**
1245
	 * returns the part of the bodyElement
1246
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
1247
	 */
1248
	public IBody getPart() {
1249
		if(part != null){
1250
			return part.getPart();
1251
		}
1252
		return null;
1253
	}
1254
1243
1255
	/**
1244
    @Override
1256
	 * returns the partType of the bodyPart which owns the bodyElement
1245
    public IBody getBody()
1257
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
1246
    {
1258
	 */
1247
        return part;
1259
	public BodyType getPartType() {
1248
    }
1260
		return part.getPartType();
1261
	}
1262
	
1263
	/**
1264
	 * adds a new Run to the Paragraph
1265
	 */
1266
	public void addRun(XWPFRun r){
1267
		runs.add(r);
1268
	}
1269
	
1270
	/**
1271
	 * return the XWPFRun-Element which owns the CTR run-Element
1272
	 */
1273
	public XWPFRun getRun(CTR r){
1274
		for(int i=0; i < getRuns().size(); i++){
1275
			if(getRuns().get(i).getCTR() == r) return getRuns().get(i); 
1276
		}
1277
		return null;
1278
	}
1279
	
1280
1249
1250
    /**
1251
     * returns the part of the bodyElement
1252
     * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
1253
     */
1254
    public POIXMLDocumentPart getPart() {
1255
        if(part != null){
1256
            return part.getPart();
1257
        }
1258
        return null;
1259
    }
1281
1260
1282
}//end class
1261
    /**
1262
     * returns the partType of the bodyPart which owns the bodyElement
1263
     * 
1264
     * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
1265
     */
1266
    public BodyType getPartType() {
1267
        return part.getPartType();
1268
    }
1283
1269
1270
    /**
1271
     * adds a new Run to the Paragraph
1272
     * 
1273
     * @param r
1274
     * @return
1275
     */
1276
    public void addRun(XWPFRun r) {
1277
        if (!runs.contains(r)) {
1278
            runs.add(r);
1279
        }
1280
    }
1284
1281
1282
    /**
1283
     * return the XWPFRun-Element which owns the CTR run-Element
1284
     * 
1285
     * @param r
1286
     * @return
1287
     */
1288
    public XWPFRun getRun(CTR r) {
1289
        for (int i = 0; i < getRuns().size(); i++) {
1290
            if (getRuns().get(i).getCTR() == r) {
1291
                return getRuns().get(i);
1292
            }
1293
        }
1294
        return null;
1295
    }
1285
1296
1297
}//end class
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java (-35 / +129 lines)
Lines 18-26 Link Here
18
package org.apache.poi.xwpf.usermodel;
18
package org.apache.poi.xwpf.usermodel;
19
19
20
import java.io.IOException;
20
import java.io.IOException;
21
import java.io.InputStream;
22
import java.util.Arrays;
21
23
22
import org.apache.poi.POIXMLDocumentPart;
24
import org.apache.poi.POIXMLDocumentPart;
25
import org.apache.poi.POIXMLException;
23
import org.apache.poi.POIXMLRelation;
26
import org.apache.poi.POIXMLRelation;
27
import org.apache.poi.openxml4j.opc.OPCPackage;
24
import org.apache.poi.openxml4j.opc.PackagePart;
28
import org.apache.poi.openxml4j.opc.PackagePart;
25
import org.apache.poi.openxml4j.opc.PackageRelationship;
29
import org.apache.poi.openxml4j.opc.PackageRelationship;
26
import org.apache.poi.util.IOUtils;
30
import org.apache.poi.util.IOUtils;
Lines 32-60 Link Here
32
36
33
/**
37
/**
34
 * @author Philipp Epp
38
 * @author Philipp Epp
35
 *
36
 */
39
 */
37
public class XWPFPictureData extends POIXMLDocumentPart {
40
public class XWPFPictureData extends POIXMLDocumentPart {
38
	
41
39
    /**
42
    /**
40
     * Relationships for each known picture type
43
     * Relationships for each known picture type
41
     */
44
     */
42
    protected static final POIXMLRelation[] RELATIONS;
45
    protected static final POIXMLRelation[] RELATIONS;
43
    static {
46
    static {
44
        RELATIONS = new POIXMLRelation[9];
47
        RELATIONS = new POIXMLRelation[9];
45
        RELATIONS[Document.PICTURE_TYPE_EMF] =  XWPFRelation.IMAGE_EMF;
48
        RELATIONS[Document.PICTURE_TYPE_EMF] = XWPFRelation.IMAGE_EMF;
46
        RELATIONS[Document.PICTURE_TYPE_WMF] =  XWPFRelation.IMAGE_WMF;
49
        RELATIONS[Document.PICTURE_TYPE_WMF] = XWPFRelation.IMAGE_WMF;
47
        RELATIONS[Document.PICTURE_TYPE_PICT] = XWPFRelation.IMAGE_PICT;
50
        RELATIONS[Document.PICTURE_TYPE_PICT] = XWPFRelation.IMAGE_PICT;
48
        RELATIONS[Document.PICTURE_TYPE_JPEG] = XWPFRelation.IMAGE_JPEG;
51
        RELATIONS[Document.PICTURE_TYPE_JPEG] = XWPFRelation.IMAGE_JPEG;
49
        RELATIONS[Document.PICTURE_TYPE_PNG] =  XWPFRelation.IMAGE_PNG;
52
        RELATIONS[Document.PICTURE_TYPE_PNG] = XWPFRelation.IMAGE_PNG;
50
        RELATIONS[Document.PICTURE_TYPE_DIB] =  XWPFRelation.IMAGE_DIB;
53
        RELATIONS[Document.PICTURE_TYPE_DIB] = XWPFRelation.IMAGE_DIB;
51
        RELATIONS[Document.PICTURE_TYPE_GIF] =  XWPFRelation.IMAGE_GIF;
54
        RELATIONS[Document.PICTURE_TYPE_GIF] = XWPFRelation.IMAGE_GIF;
52
    }
55
    }
56
57
    private Long checksum = null;
58
53
    /**
59
    /**
54
     * Create a new XWPFGraphicData node
60
     * Create a new XWPFGraphicData node
55
     *
61
     *
56
     */
62
     */
57
	protected XWPFPictureData() {
63
    protected XWPFPictureData() {
58
        super();
64
        super();
59
    }
65
    }
60
66
Lines 65-75 Link Here
65
     * @param rel  the package relationship holding this drawing,
71
     * @param rel  the package relationship holding this drawing,
66
     * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/image
72
     * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/image
67
     */
73
     */
68
	
74
    public XWPFPictureData(PackagePart part, PackageRelationship rel) {
69
	public XWPFPictureData(PackagePart part, PackageRelationship rel) {
70
        super(part, rel);
75
        super(part, rel);
71
    }
76
    }
72
    
77
78
    @Override
79
    protected void onDocumentRead() throws IOException {
80
        super.onDocumentRead();
81
    }
82
73
    /**
83
    /**
74
     * Gets the picture data as a byte array.
84
     * Gets the picture data as a byte array.
75
     * <p>
85
     * <p>
Lines 80-123 Link Here
80
     * InputStream is = getPackagePart().getInputStream();
90
     * InputStream is = getPackagePart().getInputStream();
81
     * </code>
91
     * </code>
82
     * </p>
92
     * </p>
83
     *
84
     * @return the Picture data.
93
     * @return the Picture data.
85
     */
94
     */
86
    public byte[] getData() {
95
    public byte[] getData() {
87
          try {
96
        try {
88
			return IOUtils.toByteArray(getPackagePart().getInputStream());
97
            return IOUtils.toByteArray(getPackagePart().getInputStream());
89
		} catch (IOException e) {
98
        } catch (IOException e) {
90
			// TODO Auto-generated catch block
99
            throw new POIXMLException(e);
91
			e.printStackTrace();
100
        }
92
		}
93
		return null;
94
    }
101
    }
95
    
102
96
    /**
103
    /**
97
     * Returns the file name of the image, eg image7.jpg .
104
     * Returns the file name of the image, eg image7.jpg . The original filename
98
     * The original filename isn't always available, but if it
105
     * isn't always available, but if it can be found it's likely to be in the
99
     *  can be found it's likely to be in the CTDrawing 
106
     * CTDrawing
100
     */
107
     */
101
    public String getFileName() {
108
    public String getFileName() {
102
       String name = getPackagePart().getPartName().getName();
109
        String name = getPackagePart().getPartName().getName();
103
       if(name == null)
110
        if (name == null)
104
          return null;
111
            return null;
105
       return name.substring(name.lastIndexOf('/') + 1);
112
        return name.substring(name.lastIndexOf('/') + 1);
106
    }
113
    }
107
    
114
108
    /**
115
    /**
109
     * Suggests a file extension for this image.
116
     * Suggests a file extension for this image.
110
     *
111
     * @return the file extension.
117
     * @return the file extension.
112
     */
118
     */
113
    public String suggestFileExtension() {
119
    public String suggestFileExtension() {
114
        return getPackagePart().getPartName().getExtension();
120
        return getPackagePart().getPartName().getExtension();
115
    }
121
    }
116
    
122
117
    /**
123
    /**
118
     * Return an integer constant that specifies type of this picture
124
     * Return an integer constant that specifies type of this picture
119
     *
125
     * 
120
     * @return an integer constant that specifies type of this picture 
126
     * @return an integer constant that specifies type of this picture
121
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF
127
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF
122
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF
128
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF
123
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PICT
129
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PICT
Lines 125-139 Link Here
125
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PNG
131
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PNG
126
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB
132
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB
127
     */
133
     */
128
    public int getPictureType(){
134
    public int getPictureType() {
129
        String contentType = getPackagePart().getContentType();
135
        String contentType = getPackagePart().getContentType();
130
        for (int i = 0; i < RELATIONS.length; i++) {
136
        for (int i = 0; i < RELATIONS.length; i++) {
131
            if(RELATIONS[i] == null) continue;
137
            if (RELATIONS[i] == null) {
138
                continue;
139
            }
132
140
133
            if(RELATIONS[i].getContentType().equals(contentType)){
141
            if (RELATIONS[i].getContentType().equals(contentType)) {
134
                return i;
142
                return i;
135
            }
143
            }
136
        }
144
        }
137
        return 0;
145
        return 0;
138
    }
146
    }
147
148
    public Long getChecksum() {
149
        if (this.checksum == null) {
150
            InputStream is = null;
151
            byte[] data;
152
            try {
153
                is = getPackagePart().getInputStream();
154
                data = IOUtils.toByteArray(is);
155
            } catch (IOException e) {
156
                throw new POIXMLException(e);
157
            } finally {
158
                try {
159
                    is.close();
160
                } catch (IOException e) {
161
                    throw new POIXMLException(e);
162
                }
163
            }
164
            this.checksum = IOUtils.calculateChecksum(data);
165
        }
166
        return this.checksum;
167
    }
168
169
    @Override
170
    public boolean equals(Object obj) {
171
        /**
172
         * In case two objects ARE equal, but its not the same instance, this
173
         * implementation will always run through the whole
174
         * byte-array-comparison before returning true. If this will turn into a
175
         * performance issue, two possible approaches are available:<br>
176
         * a) Use the checksum only and take the risk that two images might have
177
         * the same CRC32 sum, although they are not the same.<br>
178
         * b) Use a second (or third) checksum algorithm to minimise the chance
179
         * that two images have the same checksums but are not equal (e.g.
180
         * CRC32, MD5 and SHA-1 checksums, additionally compare the
181
         * data-byte-array lengths).
182
         */
183
        if (obj == this) {
184
            return true;
185
        }
186
187
        if (obj == null) {
188
            return false;
189
        }
190
191
        if (!(obj instanceof XWPFPictureData)) {
192
            return false;
193
        }
194
195
        XWPFPictureData picData = (XWPFPictureData) obj;
196
        PackagePart foreignPackagePart = picData.getPackagePart();
197
        PackagePart ownPackagePart = this.getPackagePart();
198
199
        if ((foreignPackagePart != null && ownPackagePart == null)
200
                || (foreignPackagePart == null && ownPackagePart != null)) {
201
            return false;
202
        }
203
204
        if (ownPackagePart != null) {
205
            OPCPackage foreignPackage = foreignPackagePart.getPackage();
206
            OPCPackage ownPackage = ownPackagePart.getPackage();
207
208
            if ((foreignPackage != null && ownPackage == null)
209
                    || (foreignPackage == null && ownPackage != null)) {
210
                return false;
211
            }
212
            if (ownPackage != null) {
213
214
                if (!ownPackage.equals(foreignPackage)) {
215
                    return false;
216
                }
217
            }
218
        }
219
        
220
        Long foreignChecksum = picData.getChecksum();
221
        Long localChecksum = getChecksum();
222
223
        if (!(localChecksum.equals(foreignChecksum))) {
224
            return false;
225
        }
226
        return Arrays.equals(this.getData(), picData.getData());
227
    }
228
229
    @Override
230
    public int hashCode() {
231
        return getChecksum().hashCode();
232
    }
139
}
233
}
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java (-28 / +28 lines)
Lines 25-52 Link Here
25
 * @author Philipp Epp
25
 * @author Philipp Epp
26
 */
26
 */
27
public class XWPFPicture {
27
public class XWPFPicture {
28
	protected XWPFParagraph paragraph;
28
29
	private CTPicture ctPic;
29
    private CTPicture ctPic;
30
    private String description;
30
    private String description;
31
    private XWPFRun run;
32
33
    public XWPFPicture(CTPicture ctPic, XWPFRun run){
34
        this.run = run;
35
        this.ctPic = ctPic;
36
        description = ctPic.getNvPicPr().getCNvPr().getDescr();
37
    }
38
39
    /**
40
     * Link Picture with PictureData
41
     * @param rel
42
     */
43
    public void setPictureReference(PackageRelationship rel){
44
        ctPic.getBlipFill().getBlip().setEmbed(rel.getId());
45
    }
31
46
32
    public XWPFParagraph getParagraph(){
33
		 return paragraph;
34
	 }
35
	 
36
	 public XWPFPicture(CTPicture ctPic, XWPFParagraph paragraph){
37
		 this.paragraph = paragraph;
38
		 this.ctPic = ctPic;
39
         description = ctPic.getNvPicPr().getCNvPr().getDescr();
40
     }
41
	 
42
	 /**
43
	  * Link Picture with PictureData
44
	  * @param rel
45
	  */
46
	 public void setPictureReference(PackageRelationship rel){
47
		 ctPic.getBlipFill().getBlip().setEmbed(rel.getId());
48
	 }
49
	 
50
    /**
47
    /**
51
     * Return the underlying CTPicture bean that holds all properties for this picture
48
     * Return the underlying CTPicture bean that holds all properties for this picture
52
     *
49
     *
Lines 55-73 Link Here
55
    public CTPicture getCTPicture(){
52
    public CTPicture getCTPicture(){
56
        return ctPic;
53
        return ctPic;
57
    }
54
    }
58
    
55
59
    /**
56
    /**
60
     * Get the PictureData of the Picture, if present.
57
     * Get the PictureData of the Picture, if present.
61
     * Note - not all kinds of picture have data
58
     * Note - not all kinds of picture have data
62
     */
59
     */
63
    public XWPFPictureData getPictureData(){
60
    public XWPFPictureData getPictureData(){
64
    	String blipId = ctPic.getBlipFill().getBlip().getEmbed();
61
        String blipId = ctPic.getBlipFill().getBlip().getEmbed();
65
        for(POIXMLDocumentPart part: ((POIXMLDocumentPart) paragraph.getPart()).getRelations()){
62
        POIXMLDocumentPart part = run.getParagraph().getPart();
66
    		  if(part.getPackageRelationship().getId().equals(blipId)){
63
        if (part != null)
67
    			  return (XWPFPictureData)part;
64
        {
68
    		  }
65
            POIXMLDocumentPart relatedPart = part.getRelationById(blipId);
69
    	}
66
            if (relatedPart instanceof XWPFPictureData) {
70
    	return null;
67
                return (XWPFPictureData) relatedPart;
68
            }
69
        }
70
        return null;
71
    }
71
    }
72
72
73
    public String getDescription() {
73
    public String getDescription() {
(-)src/ooxml/java/org/apache/poi/util/IdentifierManager.java (+268 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
package org.apache.poi.util;
18
19
import java.util.LinkedList;
20
import java.util.ListIterator;
21
22
/**
23
 * <p>
24
 * 24.08.2009<br>
25
 * </p>
26
 * 
27
 * @author Stefan Stern<br>
28
 */
29
30
public class IdentifierManager {
31
32
    public static final long MAX_ID = Long.MAX_VALUE - 1;
33
34
    public static final long MIN_ID = 0L;
35
36
    /**
37
	 * 
38
	 */
39
    private final long upperbound;
40
41
    /**
42
	 * 
43
	 */
44
    private final long lowerbound;
45
46
    /**
47
	 * List of segments of available identifiers
48
	 */
49
    private LinkedList<Segment> segments;
50
51
    /**
52
     * @param lowerbound the lower limit of the id-range to manage. Must be greater than or equal to {@link #MIN_ID}.
53
     * @param upperbound the upper limit of the id-range to manage. Must be less then or equal {@link #MAX_ID}.
54
     */
55
    public IdentifierManager(long lowerbound, long upperbound) {
56
        if (lowerbound > upperbound) {
57
            String message = "lowerbound must not be greater than upperbound";
58
            throw new IllegalArgumentException(message);
59
        }
60
        else if (lowerbound < MIN_ID) { 
61
            String message = "lowerbound must be greater than or equal to " + Long.toString(MIN_ID);
62
            throw new IllegalArgumentException(message);
63
        }
64
        else if (upperbound > MAX_ID) {
65
            /*
66
             * while MAX_ID is Long.MAX_VALUE, this check is pointless. But if
67
             * someone subclasses / tweaks the limits, this check if fine.
68
             */
69
            String message = "upperbound must be less thean or equal " + Long.toString(MAX_ID);
70
            throw new IllegalArgumentException(message);
71
        }
72
        this.lowerbound = lowerbound;
73
        this.upperbound = upperbound;
74
        this.segments = new LinkedList<Segment>();
75
        segments.add(new Segment(lowerbound, upperbound));
76
    }
77
78
    public long reserve(long id) {
79
        if (id < lowerbound || id > upperbound) {
80
            throw new IllegalArgumentException("Value for parameter 'id' was out of bounds");
81
        }
82
        verifyIdentifiersLeft();
83
        
84
        if (id == upperbound) {
85
            Segment lastSegment = segments.getLast();
86
            if (lastSegment.end == upperbound) {
87
                lastSegment.end = upperbound - 1;
88
                if (lastSegment.start > lastSegment.end) {
89
                    segments.removeLast();
90
                }
91
                return id;
92
            }
93
            return reserveNew();
94
        }
95
96
        if (id == lowerbound) {
97
            Segment firstSegment = segments.getFirst();
98
            if (firstSegment.start == lowerbound) {
99
                firstSegment.start = lowerbound + 1;
100
                if (firstSegment.end < firstSegment.start) {
101
                    segments.removeFirst();
102
                }
103
                return id;
104
            }
105
            return reserveNew();
106
        }
107
108
        ListIterator<Segment> iter = segments.listIterator();
109
        while (iter.hasNext()) {
110
            Segment segment = iter.next();
111
            if (segment.end < id) {
112
                continue;
113
            }
114
            else if (segment.start > id) {
115
                break;
116
            }
117
            else if (segment.start == id) {
118
                segment.start = id + 1;
119
                if (segment.end < segment.start) {
120
                    iter.remove();
121
                }
122
                return id;
123
            }
124
            else if (segment.end == id) {
125
                segment.end = id - 1;
126
                if (segment.start > segment.end) {
127
                    iter.remove();
128
                }
129
                return id;
130
            }
131
            else {
132
                iter.add(new Segment(id + 1, segment.end));
133
                segment.end = id - 1;
134
                return id;
135
            }
136
        }
137
        return reserveNew();
138
    }
139
140
    /**
141
     * @return a new identifier. 
142
     * @throws IllegalStateException if no more identifiers are available, then an Exception is raised.
143
     */
144
    public long reserveNew() {
145
        verifyIdentifiersLeft();
146
        Segment segment = segments.getFirst();
147
        long result = segment.start;
148
        segment.start += 1;
149
        if (segment.start > segment.end) {
150
            segments.removeFirst();
151
        }
152
        return result;
153
    }
154
155
    /**
156
     * @param id
157
     * the identifier to release. Must be greater than or equal to
158
     * {@link #lowerbound} and must be less than or equal to {@link #upperbound}
159
     * @return true, if the identifier was reserved and has been successfully
160
     * released, false, if the identifier was not reserved.
161
     */
162
    public boolean release(long id) {
163
        if (id < lowerbound || id > upperbound) {
164
            throw new IllegalArgumentException("Value for parameter 'id' was out of bounds");
165
        }
166
167
        if (id == upperbound) {
168
            Segment lastSegment = segments.getLast();
169
            if (lastSegment.end == upperbound - 1) {
170
                lastSegment.end = upperbound;
171
                return true;
172
            } else if (lastSegment.end == upperbound) {
173
                return false;
174
            } else {
175
                segments.add(new Segment(upperbound, upperbound));
176
                return true;
177
            }
178
        }
179
180
        if (id == lowerbound) {
181
            Segment firstSegment = segments.getFirst();
182
            if (firstSegment.start == lowerbound + 1) {
183
                firstSegment.start = lowerbound;
184
                return true;
185
            } else if (firstSegment.start == lowerbound) {
186
                return false;
187
            } else {
188
                segments.addFirst(new Segment(lowerbound, lowerbound));
189
                return true;
190
            }
191
        }
192
193
        long higher = id + 1;
194
        long lower = id - 1;
195
        ListIterator<Segment> iter = segments.listIterator();
196
197
        while (iter.hasNext()) {
198
            Segment segment = iter.next();
199
            if (segment.end < lower) {
200
                continue;
201
            }
202
            if (segment.start > higher) {
203
                iter.previous();
204
                iter.add(new Segment(id, id));
205
                return true;
206
            }
207
            if (segment.start == higher) {
208
                segment.start = id;
209
                return true;
210
            }
211
            else if (segment.end == lower) {
212
                segment.end = id;
213
                /* check if releasing this elements glues two segments into one */
214
                if (iter.hasNext()) {
215
                  Segment next = iter.next();
216
                    if (next.start == segment.end + 1) {
217
                        segment.end = next.end;
218
                        iter.remove();
219
                    }
220
                }
221
                return true;
222
            }
223
            else {
224
                /* id was not reserved, return false */
225
                break;
226
            }
227
        }
228
        return false;
229
    }
230
231
    public long getRemainingIdentifiers() {
232
        long result = 0;
233
        for (Segment segment : segments) {
234
            result = result - segment.start;
235
            result = result + segment.end + 1;
236
        }
237
        return result;
238
    }
239
240
    /**
241
	 * 
242
	 */
243
    private void verifyIdentifiersLeft() {
244
        if (segments.isEmpty()) {
245
            throw new IllegalStateException("No identifiers left");
246
        }
247
    }
248
249
    private static class Segment {
250
251
        public Segment(long start, long end) {
252
            this.start = start;
253
            this.end = end;
254
        }
255
256
        public long start;
257
        public long end;
258
259
        /*
260
         * (non-Javadoc)
261
         * 
262
         * @see java.lang.Object#toString()
263
         */
264
        public String toString() {
265
            return "[" + start + "; " + end + "]";
266
        }
267
    }
268
}
0
  + text/plain
269
  + text/plain
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java (-89 / +65 lines)
Lines 19-31 Link Here
19
import java.io.IOException;
19
import java.io.IOException;
20
import java.io.InputStream;
20
import java.io.InputStream;
21
import java.io.OutputStream;
21
import java.io.OutputStream;
22
import java.util.ArrayList;
23
import java.util.HashMap;
22
import java.util.HashMap;
24
import java.util.Map;
23
import java.util.Map;
25
24
26
import javax.xml.namespace.QName;
25
import javax.xml.namespace.QName;
27
26
28
import org.apache.poi.POIXMLDocumentPart;
27
import org.apache.poi.POIXMLDocumentPart;
28
import org.apache.poi.POIXMLException;
29
import org.apache.poi.openxml4j.opc.PackagePart;
29
import org.apache.poi.openxml4j.opc.PackagePart;
30
import org.apache.poi.openxml4j.opc.PackageRelationship;
30
import org.apache.poi.openxml4j.opc.PackageRelationship;
31
import org.apache.xmlbeans.XmlCursor;
31
import org.apache.xmlbeans.XmlCursor;
Lines 47-86 Link Here
47
    }
47
    }
48
48
49
    public XWPFHeader(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel) throws IOException {
49
    public XWPFHeader(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel) throws IOException {
50
		super(parent, part, rel);
50
        super(parent, part, rel);
51
	}
51
    }
52
	
52
53
	public XWPFHeader(XWPFDocument doc, CTHdrFtr hdrFtr) throws IOException {
53
    public XWPFHeader(XWPFDocument doc, CTHdrFtr hdrFtr) {
54
		super(doc, hdrFtr);
54
        super(doc, hdrFtr);
55
		paragraphs = new ArrayList<XWPFParagraph>();
55
        XmlCursor cursor = headerFooter.newCursor();
56
		tables = new ArrayList<XWPFTable>();
56
        cursor.selectPath("./*");
57
		XmlCursor cursor = headerFooter.newCursor();
57
        while (cursor.toNextSelection()) {
58
		cursor.selectPath("./*");
58
            XmlObject o = cursor.getObject();
59
		while (cursor.toNextSelection()) {
59
            if (o instanceof CTP) {
60
			XmlObject o = cursor.getObject();
60
                XWPFParagraph p = new XWPFParagraph((CTP) o, this);
61
			if (o instanceof CTP) {
61
                paragraphs.add(p);
62
				XWPFParagraph p = new XWPFParagraph((CTP) o, this);
62
            }
63
				paragraphs.add(p);
63
            if (o instanceof CTTbl) {
64
			}
64
                XWPFTable t = new XWPFTable((CTTbl) o, this);
65
			if (o instanceof CTTbl) {
65
                tables.add(t);
66
				XWPFTable t = new XWPFTable((CTTbl) o, this);
66
            }
67
				tables.add(t);
67
        }
68
			}
69
		}
70
        cursor.dispose();
68
        cursor.dispose();
71
		getAllPictures();
69
    }
72
	}
73
70
74
	/**
71
	/**
75
	public XWPFHeader(PackagePart part, PackageRelationship rel)
72
     * save and commit footer
76
			throws IOException {
73
     */
77
		super(part, rel);
74
    @Override
78
	}
79
	
80
	/**
81
	 * save and commit footer
82
	 */
83
	@Override
84
    protected void commit() throws IOException {
75
    protected void commit() throws IOException {
85
        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
76
        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
86
        xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "hdr"));
77
        xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "hdr"));
Lines 101-162 Link Here
101
        out.close();
92
        out.close();
102
    }
93
    }
103
94
104
	/**
95
    /**
105
	 * reads the document
96
     * reads the document
106
	 */
97
     * @throws IOException 
107
	  @Override  
98
     */
108
	    protected void onDocumentRead(){
99
    @Override  
109
		  	bodyElements = new ArrayList<IBodyElement>();
100
    protected void onDocumentRead() throws IOException {
110
	        paragraphs = new ArrayList<XWPFParagraph>();
101
        super.onDocumentRead();	          
111
	        tables= new ArrayList<XWPFTable>();
102
        HdrDocument hdrDocument = null;
112
	        HdrDocument hdrDocument = null;
103
        InputStream is;
113
			InputStream is;
104
        try {
114
			try {
105
            is = getPackagePart().getInputStream();
115
				is = getPackagePart().getInputStream();
106
            hdrDocument = HdrDocument.Factory.parse(is);
116
				hdrDocument = HdrDocument.Factory.parse(is);
107
            headerFooter = hdrDocument.getHdr();
117
				headerFooter = hdrDocument.getHdr();
108
            // parse the document with cursor and add
118
		        // parse the document with cursor and add
109
            // the XmlObject to its lists
119
		        // the XmlObject to its lists
110
            XmlCursor cursor = headerFooter.newCursor();
120
				XmlCursor cursor = headerFooter.newCursor();
111
            cursor.selectPath("./*");
121
		        cursor.selectPath("./*");
112
            while (cursor.toNextSelection()) {
122
		        while (cursor.toNextSelection()) {
113
                XmlObject o = cursor.getObject();
123
		            XmlObject o = cursor.getObject();
114
                if (o instanceof CTP) {
124
		            if (o instanceof CTP) {
115
                    XWPFParagraph p = new XWPFParagraph((CTP)o, this);
125
		            	XWPFParagraph p = new XWPFParagraph((CTP)o, this);
116
                    paragraphs.add(p);
126
		            	paragraphs.add(p);
117
                    bodyElements.add(p);
127
		            	bodyElements.add(p);
118
                }
128
		            }
119
                if (o instanceof CTTbl) {
129
		            if (o instanceof CTTbl) {
120
                    XWPFTable t = new XWPFTable((CTTbl)o, this);
130
		            	XWPFTable t = new XWPFTable((CTTbl)o, this);
121
                    tables.add(t);
131
		            	tables.add(t);
122
                    bodyElements.add(t);
132
		            	bodyElements.add(t);
123
                }
133
		            }
124
            }
134
		        }
125
            cursor.dispose();
135
                cursor.dispose();
126
        } catch (XmlException e) {
136
			} catch (IOException e) {
127
            throw new POIXMLException(e);
137
				// TODO Auto-generated catch block
128
        }
138
				e.printStackTrace();
129
    }
139
			} catch (XmlException e) {
140
				// TODO Auto-generated catch block
141
				e.printStackTrace();
142
			}
143
	  }
144
145
	/**
146
	 * returns the Part, to which the body belongs, which you need for adding relationship to other parts
147
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
148
	 */
149
	public IBody getPart() {
150
		return this;
151
	}
152
153
	/**
154
	 * get the PartType of the body
155
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
156
	 */
157
	public BodyType getPartType() {
158
		return BodyType.HEADER;
159
	}
160
161
130
131
    /**
132
     * get the PartType of the body
133
     * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
134
     */
135
    public BodyType getPartType() {
136
        return BodyType.HEADER;
137
    }
162
}//end class
138
}//end class
(-)src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java (-1 / +1 lines)
Lines 22-28 Link Here
22
import java.text.ParsePosition;
22
import java.text.ParsePosition;
23
import java.text.SimpleDateFormat;
23
import java.text.SimpleDateFormat;
24
import java.util.Date;
24
import java.util.Date;
25
import java.util.Locale;
25
26
import java.util.TimeZone;
26
import java.util.TimeZone;
27
27
28
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
28
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java (-3 / +3 lines)
Lines 52-58 Link Here
52
     * @return the newly created XWPFTableCell
52
     * @return the newly created XWPFTableCell
53
     */
53
     */
54
    public XWPFTableCell createCell() {
54
    public XWPFTableCell createCell() {
55
        XWPFTableCell tableCell = new XWPFTableCell(ctRow.addNewTc(), this, table.getPart());
55
        XWPFTableCell tableCell = new XWPFTableCell(ctRow.addNewTc(), this, table.getBody());
56
        tableCells.add(tableCell);
56
        tableCells.add(tableCell);
57
        return tableCell;
57
        return tableCell;
58
    }
58
    }
Lines 69-75 Link Here
69
     */
69
     */
70
    public XWPFTableCell addNewTableCell(){
70
    public XWPFTableCell addNewTableCell(){
71
    	CTTc cell = ctRow.addNewTc();
71
    	CTTc cell = ctRow.addNewTc();
72
    	XWPFTableCell tableCell = new XWPFTableCell(cell, this, table.getPart());
72
    	XWPFTableCell tableCell = new XWPFTableCell(cell, this, table.getBody());
73
    	tableCells.add(tableCell);
73
    	tableCells.add(tableCell);
74
    	return tableCell;
74
    	return tableCell;
75
    }
75
    }
Lines 123-129 Link Here
123
    	if(tableCells == null){
123
    	if(tableCells == null){
124
    		List<XWPFTableCell> cells = new ArrayList<XWPFTableCell>();
124
    		List<XWPFTableCell> cells = new ArrayList<XWPFTableCell>();
125
    		for (CTTc tableCell : ctRow.getTcList()) {
125
    		for (CTTc tableCell : ctRow.getTcList()) {
126
    			cells.add(new XWPFTableCell(tableCell, this, table.getPart()));
126
    			cells.add(new XWPFTableCell(tableCell, this, table.getBody()));
127
    		}
127
    		}
128
    		this.tableCells = cells;
128
    		this.tableCells = cells;
129
    	}
129
    	}
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java (-1 / +2 lines)
Lines 19-24 Link Here
19
19
20
import java.util.List;
20
import java.util.List;
21
21
22
import org.apache.poi.POIXMLDocumentPart;
22
import org.apache.xmlbeans.XmlCursor;
23
import org.apache.xmlbeans.XmlCursor;
23
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
24
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
24
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
25
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
Lines 42-48 Link Here
42
	 * belongs.
43
	 * belongs.
43
	 * @return the Part, to which the body belongs
44
	 * @return the Part, to which the body belongs
44
	 */
45
	 */
45
	IBody getPart();
46
	POIXMLDocumentPart getPart();
46
	
47
	
47
	/**
48
	/**
48
	 * get the PartType of the body, for example
49
	 * get the PartType of the body, for example
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java (-35 / +40 lines)
Lines 20-25 Link Here
20
import java.util.ArrayList;
20
import java.util.ArrayList;
21
import java.util.List;
21
import java.util.List;
22
22
23
import org.apache.poi.POIXMLDocumentPart;
23
import org.apache.poi.util.Internal;
24
import org.apache.poi.util.Internal;
24
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
25
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
25
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
26
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
Lines 47-65 Link Here
47
    protected List<String> styleIDs;
48
    protected List<String> styleIDs;
48
    protected IBody part;
49
    protected IBody part;
49
50
50
    public XWPFTable(CTTbl table, IBody part, int row, int col) {
51
    public XWPFTable(CTTbl table,IBody part,int row,int col) {
51
        this(table, part);
52
        this(table,part);
52
        for (int i = 0; i < row; i++) {
53
        for (int i = 0 ; i < row ; i++) {
53
            XWPFTableRow tabRow = (getRow(i) == null) ? createRow() : getRow(i);
54
            XWPFTableRow tabRow = (getRow(i) == null)?createRow():getRow(i);
54
            tableRows.add(tabRow);
55
            tableRows.add(tabRow);
55
            for (int k = 0; k < col; k++) {
56
            for (int k = 0 ; k < col ; k++) {
56
                XWPFTableCell tabCell = (tabRow.getCell(k) == null) ? tabRow
57
                if (tabRow.getCell(k) == null) {
57
                        .createCell() : null;
58
                    tabRow.createCell();
59
                }
58
            }
60
            }
59
        }
61
        }
60
    }
62
    }
61
63
62
63
    public XWPFTable(CTTbl table, IBody part){
64
    public XWPFTable(CTTbl table, IBody part){
64
    	this.part = part;
65
    	this.part = part;
65
        this.ctTbl = table;
66
        this.ctTbl = table;
Lines 132-148 Link Here
132
        return text.toString();
133
        return text.toString();
133
    }
134
    }
134
135
135
136
    public void addNewRowBetween(int start, int end) {
136
    public void addNewRowBetween(int start, int end) {
137
        // TODO
137
        // TODO
138
    }
138
    }
139
139
140
141
    /**
140
    /**
142
     * add a new column for each row in this table
141
     * add a new column for each row in this table
143
     */
142
     */
144
    public void addNewCol() {
143
    public void addNewCol() {
145
        if (ctTbl.sizeOfTrArray() == 0) createRow();
144
        if (ctTbl.sizeOfTrArray() == 0) {
145
            createRow();
146
        }
146
        for (int i = 0; i < ctTbl.sizeOfTrArray(); i++) {
147
        for (int i = 0; i < ctTbl.sizeOfTrArray(); i++) {
147
            XWPFTableRow tabRow = new XWPFTableRow(ctTbl.getTrArray(i), this);
148
            XWPFTableRow tabRow = new XWPFTableRow(ctTbl.getTrArray(i), this);
148
            tabRow.createCell();
149
            tabRow.createCell();
Lines 269-280 Link Here
269
     * @param pos	position the Row in the Table
270
     * @param pos	position the Row in the Table
270
     */
271
     */
271
    public boolean removeRow(int pos) throws IndexOutOfBoundsException {
272
    public boolean removeRow(int pos) throws IndexOutOfBoundsException {
272
    	if(pos > 0 && pos < tableRows.size()){
273
        if (pos >= 0 && pos < tableRows.size()) {
273
    		ctTbl.removeTr(pos);
274
            ctTbl.removeTr(pos);
274
    		tableRows.remove(pos);
275
            tableRows.remove(pos);
275
    		return true;
276
            return true;
276
    	}
277
        }
277
    	return false;
278
        return false;
278
    }
279
    }
279
	
280
	
280
    public List<XWPFTableRow> getRows() {
281
    public List<XWPFTableRow> getRows() {
Lines 290-315 Link Here
290
		return BodyElementType.TABLE;
291
		return BodyElementType.TABLE;
291
	}
292
	}
292
293
293
294
    @Override
294
	/**
295
    public IBody getBody()
295
	 * returns the part of the bodyElement
296
    {
296
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
297
        return part;
297
	 */
298
    }
298
	public IBody getPart() {
299
		if(part != null){
300
			return part.getPart();
301
		}
302
		return null;
303
	}
304
299
300
    /**
301
     * returns the part of the bodyElement
302
     * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
303
     */
304
    public POIXMLDocumentPart getPart() {
305
        if(part != null){
306
            return part.getPart();
307
        }
308
        return null;
309
    }
305
310
306
	/**
311
    /**
307
	 * returns the partType of the bodyPart which owns the bodyElement
312
     * returns the partType of the bodyPart which owns the bodyElement
308
	 * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
313
     * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
309
	 */
314
     */
310
	public BodyType getPartType() {
315
    public BodyType getPartType() {
311
		return ((IBody)part).getPartType();
316
        return part.getPartType();
312
	}
317
    }
313
318
314
	/**
319
	/**
315
	 * returns the XWPFRow which belongs to the CTRow row
320
	 * returns the XWPFRow which belongs to the CTRow row
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java (-8 / +6 lines)
Lines 44-53 Link Here
44
 *
44
 *
45
 */
45
 */
46
public class XWPFNumbering extends POIXMLDocumentPart {
46
public class XWPFNumbering extends POIXMLDocumentPart {
47
	private CTNumbering ctNumbering;
47
    protected List<XWPFAbstractNum> abstractNums = new ArrayList<XWPFAbstractNum>();
48
	protected List<XWPFAbstractNum> abstractNums;
48
    protected List<XWPFNum> nums = new ArrayList<XWPFNum>();
49
	protected List<XWPFNum> nums;
49
50
	protected boolean isNew;
50
    private CTNumbering ctNumbering;
51
	boolean isNew;
51
	
52
	
52
	/**
53
	/**
53
	 *create a new styles object with an existing document 
54
	 *create a new styles object with an existing document 
Lines 55-61 Link Here
55
	public XWPFNumbering(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException{
56
	public XWPFNumbering(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException{
56
		super(part, rel);
57
		super(part, rel);
57
		isNew = true;
58
		isNew = true;
58
		onDocumentRead();
59
	}
59
	}
60
	
60
	
61
	/**
61
	/**
Lines 63-70 Link Here
63
	 */
63
	 */
64
	@Override
64
	@Override
65
	protected void onDocumentRead() throws IOException{
65
	protected void onDocumentRead() throws IOException{
66
		abstractNums = new ArrayList<XWPFAbstractNum>();
67
		nums = new ArrayList<XWPFNum>();
68
		NumberingDocument numberingDoc = null;
66
		NumberingDocument numberingDoc = null;
69
		InputStream is;
67
		InputStream is;
70
		is = getPackagePart().getInputStream();
68
		is = getPackagePart().getInputStream();
Lines 91-97 Link Here
91
    protected void commit() throws IOException {
89
    protected void commit() throws IOException {
92
        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
90
        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
93
        xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "numbering"));
91
        xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "numbering"));
94
        Map map = new HashMap();
92
        Map<String,String> map = new HashMap<String,String>();
95
        map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve");
93
        map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve");
96
        map.put("urn:schemas-microsoft-com:office:office", "o");
94
        map.put("urn:schemas-microsoft-com:office:office", "o");
97
        map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r");
95
        map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r");
(-)src/ooxml/java/org/apache/poi/POIXMLDocument.java (-38 / +18 lines)
Lines 30-39 Link Here
30
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
30
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
31
import org.apache.poi.openxml4j.opc.OPCPackage;
31
import org.apache.poi.openxml4j.opc.OPCPackage;
32
import org.apache.poi.openxml4j.opc.PackagePart;
32
import org.apache.poi.openxml4j.opc.PackagePart;
33
import org.apache.poi.openxml4j.opc.PackagePartName;
34
import org.apache.poi.openxml4j.opc.PackageRelationship;
33
import org.apache.poi.openxml4j.opc.PackageRelationship;
35
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
34
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
36
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
37
import org.apache.poi.poifs.common.POIFSConstants;
35
import org.apache.poi.poifs.common.POIFSConstants;
38
import org.apache.poi.util.IOUtils;
36
import org.apache.poi.util.IOUtils;
39
37
Lines 81-113 Link Here
81
    }
79
    }
82
80
83
    /**
81
    /**
84
     * Get the PackagePart that is the target of a relationship.
85
     *
86
     * @param rel The relationship
87
     * @return The target part
88
     * @throws InvalidFormatException
89
     */
90
    protected PackagePart getTargetPart(PackageRelationship rel) throws InvalidFormatException {
91
        return getTargetPart(getPackage(), rel);
92
    }
93
    /**
94
     * Get the PackagePart that is the target of a relationship.
95
     *
96
     * @param rel The relationship
97
     * @param pkg The package to fetch from
98
     * @return The target part
99
     * @throws InvalidFormatException
100
     */
101
    protected static PackagePart getTargetPart(OPCPackage pkg, PackageRelationship rel) throws InvalidFormatException {
102
        PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
103
        PackagePart part = pkg.getPart(relName);
104
        if (part == null) {
105
            throw new IllegalArgumentException("No part found for relationship " + rel);
106
        }
107
        return part;
108
    }
109
110
    /**
111
     * Retrieves all the PackageParts which are defined as
82
     * Retrieves all the PackageParts which are defined as
112
     *  relationships of the base document with the
83
     *  relationships of the base document with the
113
     *  specified content type.
84
     *  specified content type.
Lines 125-132 Link Here
125
        return parts;
96
        return parts;
126
    }
97
    }
127
98
128
129
130
    /**
99
    /**
131
     * Checks that the supplied InputStream (which MUST
100
     * Checks that the supplied InputStream (which MUST
132
     *  support mark and reset, or be a PushbackInputStream)
101
     *  support mark and reset, or be a PushbackInputStream)
Lines 153-162 Link Here
153
122
154
        // Did it match the ooxml zip signature?
123
        // Did it match the ooxml zip signature?
155
        return (
124
        return (
156
            header[0] == POIFSConstants.OOXML_FILE_HEADER[0] &&
125
                header[0] == POIFSConstants.OOXML_FILE_HEADER[0] &&
157
            header[1] == POIFSConstants.OOXML_FILE_HEADER[1] &&
126
                header[1] == POIFSConstants.OOXML_FILE_HEADER[1] &&
158
            header[2] == POIFSConstants.OOXML_FILE_HEADER[2] &&
127
                header[2] == POIFSConstants.OOXML_FILE_HEADER[2] &&
159
            header[3] == POIFSConstants.OOXML_FILE_HEADER[3]
128
                header[3] == POIFSConstants.OOXML_FILE_HEADER[3]
160
        );
129
        );
161
    }
130
    }
162
131
Lines 181-194 Link Here
181
    public abstract List<PackagePart> getAllEmbedds() throws OpenXML4JException;
150
    public abstract List<PackagePart> getAllEmbedds() throws OpenXML4JException;
182
151
183
    protected final void load(POIXMLFactory factory) throws IOException {
152
    protected final void load(POIXMLFactory factory) throws IOException {
184
    	Map<PackagePart, POIXMLDocumentPart> context = new HashMap<PackagePart, POIXMLDocumentPart>();
153
        Map<PackagePart, POIXMLDocumentPart> context = new HashMap<PackagePart, POIXMLDocumentPart>();
185
        try {
154
        try {
186
            read(factory, context);
155
            read(factory, context);
187
        } catch (OpenXML4JException e){
156
        } catch (OpenXML4JException e){
188
            throw new POIXMLException(e);
157
            throw new POIXMLException(e);
189
        }
158
        }
190
    	onDocumentRead();
159
        onDocumentRead();
191
    	context.clear();
160
        context.clear();
192
    }
161
    }
193
162
194
    /**
163
    /**
Lines 209-212 Link Here
209
178
210
        getPackage().save(stream);
179
        getPackage().save(stream);
211
    }
180
    }
181
182
    public void save() throws IOException {
183
        Set<PackagePart> context = new HashSet<PackagePart>();
184
        onSave(context);
185
        context.clear();
186
187
        //save extended and custom properties
188
        getProperties().commit();
189
190
        getPackage().flush();
191
    }
212
}
192
}
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java (-1 / +3 lines)
Lines 17-22 Link Here
17
17
18
package org.apache.poi.xwpf.usermodel;
18
package org.apache.poi.xwpf.usermodel;
19
19
20
import org.apache.poi.POIXMLDocumentPart;
20
21
21
/**
22
/**
22
 * 9 Jan 2010
23
 * 9 Jan 2010
Lines 24-30 Link Here
24
 *
25
 *
25
 */
26
 */
26
public interface IBodyElement{
27
public interface IBodyElement{
27
	IBody getPart();
28
	IBody getBody();
29
    POIXMLDocumentPart getPart();
28
	BodyType getPartType();
30
	BodyType getPartType();
29
	BodyElementType getElementType();
31
	BodyElementType getElementType();
30
}
32
}
(-)src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java (-351 / +338 lines)
Lines 24-30 Link Here
24
import java.util.Map;
24
import java.util.Map;
25
25
26
import org.apache.poi.POIXMLDocumentPart;
26
import org.apache.poi.POIXMLDocumentPart;
27
import org.apache.poi.openxml4j.opc.PackagePart;
28
import org.apache.poi.xwpf.usermodel.XWPFDocument;
27
import org.apache.poi.xwpf.usermodel.XWPFDocument;
29
import org.apache.poi.xwpf.usermodel.XWPFFactory;
28
import org.apache.poi.xwpf.usermodel.XWPFFactory;
30
import org.apache.poi.xwpf.usermodel.XWPFFooter;
29
import org.apache.poi.xwpf.usermodel.XWPFFooter;
Lines 68-311 Link Here
68
 *  the right headers and footers for the document.
67
 *  the right headers and footers for the document.
69
 */
68
 */
70
public class XWPFHeaderFooterPolicy {
69
public class XWPFHeaderFooterPolicy {
71
	public static final Enum DEFAULT = STHdrFtr.DEFAULT;
70
    public static final Enum DEFAULT = STHdrFtr.DEFAULT;
72
	public static final Enum EVEN = STHdrFtr.EVEN;
71
    public static final Enum EVEN = STHdrFtr.EVEN;
73
	public static final Enum FIRST = STHdrFtr.FIRST;
72
    public static final Enum FIRST = STHdrFtr.FIRST;
74
75
	private XWPFDocument doc;
76
	
77
	private XWPFHeader firstPageHeader;
78
	private XWPFFooter firstPageFooter;
79
	
80
	private XWPFHeader evenPageHeader;
81
	private XWPFFooter evenPageFooter;
82
	
83
	private XWPFHeader defaultHeader;
84
	private XWPFFooter defaultFooter;
85
	
86
        /**
87
         * Figures out the policy for the given document,
88
         *  and creates any header and footer objects
89
         *  as required.
90
         */
91
        public XWPFHeaderFooterPolicy(XWPFDocument doc) throws IOException, XmlException {
92
                this(doc, doc.getDocument().getBody().getSectPr());
93
        }
94
95
	/**
96
	 * Figures out the policy for the given document,
97
	 *  and creates any header and footer objects
98
	 *  as required.
99
	 */
100
	public XWPFHeaderFooterPolicy(XWPFDocument doc, CTSectPr sectPr) throws IOException, XmlException {
101
		// Grab what headers and footers have been defined
102
		// For now, we don't care about different ranges, as it
103
		//  doesn't seem that .docx properly supports that
104
		//  feature of the file format yet
105
		this.doc = doc;
106
		for(int i=0; i<sectPr.sizeOfHeaderReferenceArray(); i++) {
107
			// Get the header
108
			CTHdrFtrRef ref = sectPr.getHeaderReferenceArray(i);
109
			PackagePart hdrPart = doc.getPartById(ref.getId());
110
73
111
            XWPFHeader hdr = null;
74
    private XWPFDocument doc;
112
75
113
            for (POIXMLDocumentPart part : doc.getRelations()) {
76
    private XWPFHeader firstPageHeader;
114
                if (part.getPackagePart().getPartName().equals(hdrPart.getPartName())) {
77
    private XWPFFooter firstPageFooter;
115
                    hdr = (XWPFHeader) part;
116
                }
117
            }
118
78
119
			// Assign it
79
    private XWPFHeader evenPageHeader;
120
			Enum type = ref.getType();
80
    private XWPFFooter evenPageFooter;
121
			assignHeader(hdr, type);
122
		}
123
		for(int i=0; i<sectPr.sizeOfFooterReferenceArray(); i++) {
124
			// Get the footer
125
			CTHdrFtrRef ref = sectPr.getFooterReferenceArray(i);
126
			PackagePart ftrPart = doc.getPartById(ref.getId());
127
			XWPFFooter ftr = new XWPFFooter(doc, 
128
					FtrDocument.Factory.parse(ftrPart.getInputStream()).getFtr());
129
81
130
			// Assign it
82
    private XWPFHeader defaultHeader;
131
			Enum type = ref.getType();
83
    private XWPFFooter defaultFooter;
132
			assignFooter(ftr, type);
133
		}
134
	}
135
84
85
    /**
86
     * Figures out the policy for the given document,
87
     *  and creates any header and footer objects
88
     *  as required.
89
     */
90
    public XWPFHeaderFooterPolicy(XWPFDocument doc) throws IOException, XmlException {
91
        this(doc, doc.getDocument().getBody().getSectPr());
92
    }
136
93
137
	private void assignFooter(XWPFFooter ftr, Enum type) {
94
    /**
138
		if(type == STHdrFtr.FIRST) {
95
     * Figures out the policy for the given document,
139
			firstPageFooter = ftr;
96
     *  and creates any header and footer objects
140
		} else if(type == STHdrFtr.EVEN) {
97
     *  as required.
141
			evenPageFooter = ftr;
98
     */
142
		} else {
99
    public XWPFHeaderFooterPolicy(XWPFDocument doc, CTSectPr sectPr) throws IOException, XmlException {
143
			defaultFooter = ftr;
100
        // Grab what headers and footers have been defined
144
		}
101
        // For now, we don't care about different ranges, as it
145
	}
102
        //  doesn't seem that .docx properly supports that
103
        //  feature of the file format yet
104
        this.doc = doc;
105
        for(int i=0; i<sectPr.sizeOfHeaderReferenceArray(); i++) {
106
            // Get the header
107
            CTHdrFtrRef ref = sectPr.getHeaderReferenceArray(i);
108
            POIXMLDocumentPart relatedPart = doc.getRelationById(ref.getId());
109
            XWPFHeader hdr = null;
110
            if (relatedPart != null && relatedPart instanceof XWPFHeader) {
111
                hdr = (XWPFHeader) relatedPart;
112
            }
113
            // Assign it
114
            Enum type = ref.getType();
115
            assignHeader(hdr, type);
116
        }
117
        for(int i=0; i<sectPr.sizeOfFooterReferenceArray(); i++) {
118
            // Get the footer
119
            CTHdrFtrRef ref = sectPr.getFooterReferenceArray(i);
120
            POIXMLDocumentPart relatedPart = doc.getRelationById(ref.getId());
121
            XWPFFooter ftr = null;
122
            if (relatedPart != null && relatedPart instanceof XWPFFooter)
123
            {
124
                ftr = (XWPFFooter) relatedPart;
125
            }
126
            // Assign it
127
            Enum type = ref.getType();
128
            assignFooter(ftr, type);
129
        }
130
    }
146
131
132
    private void assignFooter(XWPFFooter ftr, Enum type) {
133
        if(type == STHdrFtr.FIRST) {
134
            firstPageFooter = ftr;
135
        } else if(type == STHdrFtr.EVEN) {
136
            evenPageFooter = ftr;
137
        } else {
138
            defaultFooter = ftr;
139
        }
140
    }
147
141
148
	private void assignHeader(XWPFHeader hdr, Enum type) {
142
    private void assignHeader(XWPFHeader hdr, Enum type) {
149
		if(type == STHdrFtr.FIRST) {
143
        if(type == STHdrFtr.FIRST) {
150
			firstPageHeader = hdr;
144
            firstPageHeader = hdr;
151
		} else if(type == STHdrFtr.EVEN) {
145
        } else if(type == STHdrFtr.EVEN) {
152
			evenPageHeader = hdr;
146
            evenPageHeader = hdr;
153
		} else {
147
        } else {
154
			defaultHeader = hdr;
148
            defaultHeader = hdr;
155
		}
149
        }
156
	}
150
    }
157
151
158
    public XWPFHeader createHeader(Enum type) throws IOException {
152
    public XWPFHeader createHeader(Enum type) throws IOException {
159
    	return createHeader(type, null);
153
        return createHeader(type, null);
160
    }
154
    }
161
    
155
162
    public XWPFHeader createHeader(Enum type, XWPFParagraph[] pars) throws IOException {
156
    public XWPFHeader createHeader(Enum type, XWPFParagraph[] pars) throws IOException {
163
    	XWPFRelation relation = XWPFRelation.HEADER;
157
        XWPFRelation relation = XWPFRelation.HEADER;
164
    	String pStyle = "Header";
158
        String pStyle = "Header";
165
    	int i = getRelationIndex(relation);
159
        int i = getRelationIndex(relation);
166
    	HdrDocument hdrDoc = HdrDocument.Factory.newInstance();
160
        HdrDocument hdrDoc = HdrDocument.Factory.newInstance();
167
    	XWPFHeader wrapper = (XWPFHeader)doc.createRelationship(relation, XWPFFactory.getInstance(), i);
161
        XWPFHeader wrapper = (XWPFHeader)doc.createRelationship(relation, XWPFFactory.getInstance(), i);
162
163
        CTHdrFtr hdr = buildHdr(type, pStyle, wrapper, pars);
164
        wrapper.setHeaderFooter(hdr);
168
165
169
    	CTHdrFtr hdr = buildHdr(type, pStyle, wrapper, pars);
166
        OutputStream outputStream = wrapper.getPackagePart().getOutputStream();
170
    	wrapper.setHeaderFooter(hdr);
167
        hdrDoc.setHdr(hdr);
171
    	
168
172
    	OutputStream outputStream = wrapper.getPackagePart().getOutputStream();
173
    	hdrDoc.setHdr(hdr);
174
    	
175
        XmlOptions xmlOptions = commit(wrapper);
169
        XmlOptions xmlOptions = commit(wrapper);
176
170
177
    	assignHeader(wrapper, type);
171
        assignHeader(wrapper, type);
178
		hdrDoc.save(outputStream, xmlOptions);
172
        hdrDoc.save(outputStream, xmlOptions);
179
		outputStream.close();
173
        outputStream.close();
180
    	return wrapper;
174
        return wrapper;
181
    }
175
    }
182
    
183
    
184
176
185
    public XWPFFooter createFooter(Enum type) throws IOException {
177
    public XWPFFooter createFooter(Enum type) throws IOException {
186
    	return createFooter(type, null);
178
        return createFooter(type, null);
187
    }
179
    }
188
    
180
189
    public XWPFFooter createFooter(Enum type, XWPFParagraph[] pars) throws IOException {
181
    public XWPFFooter createFooter(Enum type, XWPFParagraph[] pars) throws IOException {
190
    	XWPFRelation relation = XWPFRelation.FOOTER;
182
        XWPFRelation relation = XWPFRelation.FOOTER;
191
    	String pStyle = "Footer";
183
        String pStyle = "Footer";
192
    	int i = getRelationIndex(relation);
184
        int i = getRelationIndex(relation);
193
    	FtrDocument ftrDoc = FtrDocument.Factory.newInstance();
185
        FtrDocument ftrDoc = FtrDocument.Factory.newInstance();
194
    	XWPFFooter wrapper = (XWPFFooter)doc.createRelationship(relation, XWPFFactory.getInstance(), i);
186
        XWPFFooter wrapper = (XWPFFooter)doc.createRelationship(relation, XWPFFactory.getInstance(), i);
195
187
196
    	CTHdrFtr ftr = buildFtr(type, pStyle, wrapper, pars);
188
        CTHdrFtr ftr = buildFtr(type, pStyle, wrapper, pars);
197
      wrapper.setHeaderFooter(ftr);
189
        wrapper.setHeaderFooter(ftr);
198
    	
199
    	OutputStream outputStream = wrapper.getPackagePart().getOutputStream();
200
    	ftrDoc.setFtr(ftr);
201
    	
202
        XmlOptions xmlOptions = commit(wrapper);
203
190
204
    	assignFooter(wrapper, type);
191
        OutputStream outputStream = wrapper.getPackagePart().getOutputStream();
205
		ftrDoc.save(outputStream, xmlOptions);
192
        ftrDoc.setFtr(ftr);
206
		outputStream.close();
207
    	return wrapper;
208
    }
209
193
194
        XmlOptions xmlOptions = commit(wrapper);
210
195
211
	private int getRelationIndex(XWPFRelation relation) {
196
        assignFooter(wrapper, type);
212
		List<POIXMLDocumentPart> relations = doc.getRelations();
197
        ftrDoc.save(outputStream, xmlOptions);
213
    	int i = 1;
198
        outputStream.close();
214
		for (Iterator<POIXMLDocumentPart> it = relations.iterator(); it.hasNext() ; ) {
199
        return wrapper;
215
    		POIXMLDocumentPart item = it.next();
200
    }
216
    		if (item.getPackageRelationship().getRelationshipType().equals(relation.getRelation())) {
217
    			i++;	
218
    		}
219
    	}
220
		return i;
221
	}
222
201
202
    private int getRelationIndex(XWPFRelation relation) {
203
        List<POIXMLDocumentPart> relations = doc.getRelations();
204
        int i = 1;
205
        for (Iterator<POIXMLDocumentPart> it = relations.iterator(); it.hasNext() ; ) {
206
            POIXMLDocumentPart item = it.next();
207
            if (item.getPackageRelationship().getRelationshipType().equals(relation.getRelation())) {
208
                i++;	
209
            }
210
        }
211
        return i;
212
    }
223
213
224
	private CTHdrFtr buildFtr(Enum type, String pStyle, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) {
214
    private CTHdrFtr buildFtr(Enum type, String pStyle, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) {
225
		//CTHdrFtr ftr = buildHdrFtr(pStyle, pars);				// MB 24 May 2010
215
        //CTHdrFtr ftr = buildHdrFtr(pStyle, pars);				// MB 24 May 2010
226
		CTHdrFtr ftr = buildHdrFtr(pStyle, pars, wrapper);		// MB 24 May 2010
216
        CTHdrFtr ftr = buildHdrFtr(pStyle, pars, wrapper);		// MB 24 May 2010
227
    	setFooterReference(type, wrapper);
217
        setFooterReference(type, wrapper);
228
		return ftr;
218
        return ftr;
229
	}
219
    }
230
220
221
    private CTHdrFtr buildHdr(Enum type, String pStyle, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) {
222
        //CTHdrFtr hdr = buildHdrFtr(pStyle, pars);				// MB 24 May 2010
223
        CTHdrFtr hdr = buildHdrFtr(pStyle, pars, wrapper);		// MB 24 May 2010
224
        setHeaderReference(type, wrapper);
225
        return hdr;
226
    }
231
227
232
	private CTHdrFtr buildHdr(Enum type, String pStyle, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) {
228
    private CTHdrFtr buildHdrFtr(String pStyle, XWPFParagraph[] paragraphs) {
233
		//CTHdrFtr hdr = buildHdrFtr(pStyle, pars);				// MB 24 May 2010
229
        CTHdrFtr ftr = CTHdrFtr.Factory.newInstance();
234
		CTHdrFtr hdr = buildHdrFtr(pStyle, pars, wrapper);		// MB 24 May 2010
230
        if (paragraphs != null) {
235
    	setHeaderReference(type, wrapper);
231
            for (int i = 0 ; i < paragraphs.length ; i++) {
236
		return hdr;
232
                CTP p = ftr.addNewP();
237
	}
233
                //ftr.setPArray(0, paragraphs[i].getCTP());		// MB 23 May 2010
234
                ftr.setPArray(i, paragraphs[i].getCTP());   	// MB 23 May 2010
235
            }
236
        }
237
        else {
238
            CTP p = ftr.addNewP();
239
            byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
240
            byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
241
            p.setRsidP(rsidr);
242
            p.setRsidRDefault(rsidrdefault);
243
            CTPPr pPr = p.addNewPPr();
244
            pPr.addNewPStyle().setVal(pStyle);
245
        }
246
        return ftr;
247
    }
238
248
239
	private CTHdrFtr buildHdrFtr(String pStyle, XWPFParagraph[] paragraphs) {
249
    /**
240
		CTHdrFtr ftr = CTHdrFtr.Factory.newInstance();
250
     * MB 24 May 2010. Created this overloaded buildHdrFtr() method because testing demonstrated
241
		if (paragraphs != null) {
251
     * that the XWPFFooter or XWPFHeader object returned by calls to the createHeader(int, XWPFParagraph[])
242
			for (int i = 0 ; i < paragraphs.length ; i++) {
252
     * and createFooter(int, XWPFParagraph[]) methods or the getXXXXXHeader/Footer methods where
243
				CTP p = ftr.addNewP();
253
     * headers or footers had been added to a document since it had been created/opened, returned
244
				//ftr.setPArray(0, paragraphs[i].getCTP());		// MB 23 May 2010
254
     * an object that contained no XWPFParagraph objects even if the header/footer itself did contain
245
				ftr.setPArray(i, paragraphs[i].getCTP());   	// MB 23 May 2010
255
     * text. The reason was that this line of code; CTHdrFtr ftr = CTHdrFtr.Factory.newInstance(); 
246
			}
256
     * created a brand new instance of the CTHDRFtr class which was then populated with data when
247
		}
257
     * it should have recovered the CTHdrFtr object encapsulated within the XWPFHeaderFooter object
248
		else {
258
     * that had previoulsy been instantiated in the createHeader(int, XWPFParagraph[]) or 
249
			CTP p = ftr.addNewP();
259
     * createFooter(int, XWPFParagraph[]) methods.
250
			byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
260
     */
251
			byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
261
    private CTHdrFtr buildHdrFtr(String pStyle, XWPFParagraph[] paragraphs, XWPFHeaderFooter wrapper) {
252
			p.setRsidP(rsidr);
262
        CTHdrFtr ftr = wrapper._getHdrFtr();
253
			p.setRsidRDefault(rsidrdefault);
263
        if (paragraphs != null) {
254
			CTPPr pPr = p.addNewPPr();
264
            for (int i = 0 ; i < paragraphs.length ; i++) {
255
			pPr.addNewPStyle().setVal(pStyle);
265
                CTP p = ftr.addNewP();
256
		}
266
                ftr.setPArray(i, paragraphs[i].getCTP());
257
		return ftr;
267
            }
258
	}
268
        }
259
	
269
        else {
260
	/**
270
            CTP p = ftr.addNewP();
261
	 * MB 24 May 2010. Created this overloaded buildHdrFtr() method because testing demonstrated
271
            byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
262
	 * that the XWPFFooter or XWPFHeader object returned by calls to the createHeader(int, XWPFParagraph[])
272
            byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
263
	 * and createFooter(int, XWPFParagraph[]) methods or the getXXXXXHeader/Footer methods where
273
            p.setRsidP(rsidr);
264
	 * headers or footers had been added to a document since it had been created/opened, returned
274
            p.setRsidRDefault(rsidrdefault);
265
	 * an object that contained no XWPFParagraph objects even if the header/footer itself did contain
275
            CTPPr pPr = p.addNewPPr();
266
	 * text. The reason was that this line of code; CTHdrFtr ftr = CTHdrFtr.Factory.newInstance(); 
276
            pPr.addNewPStyle().setVal(pStyle);
267
	 * created a brand new instance of the CTHDRFtr class which was then populated with data when
277
        }
268
	 * it should have recovered the CTHdrFtr object encapsulated within the XWPFHeaderFooter object
278
        return ftr;
269
	 * that had previoulsy been instantiated in the createHeader(int, XWPFParagraph[]) or 
279
    }
270
	 * createFooter(int, XWPFParagraph[]) methods.
271
	 */
272
	private CTHdrFtr buildHdrFtr(String pStyle, XWPFParagraph[] paragraphs, XWPFHeaderFooter wrapper) {
273
		CTHdrFtr ftr = wrapper._getHdrFtr();
274
		if (paragraphs != null) {
275
			for (int i = 0 ; i < paragraphs.length ; i++) {
276
				CTP p = ftr.addNewP();
277
				ftr.setPArray(i, paragraphs[i].getCTP());
278
			}
279
		}
280
		else {
281
			CTP p = ftr.addNewP();
282
			byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
283
			byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
284
			p.setRsidP(rsidr);
285
			p.setRsidRDefault(rsidrdefault);
286
			CTPPr pPr = p.addNewPPr();
287
			pPr.addNewPStyle().setVal(pStyle);
288
		}
289
		return ftr;
290
	}
291
280
292
281
293
	private void setFooterReference(Enum type, XWPFHeaderFooter wrapper) {
282
    private void setFooterReference(Enum type, XWPFHeaderFooter wrapper) {
294
		CTHdrFtrRef ref = doc.getDocument().getBody().getSectPr().addNewFooterReference();
283
        CTHdrFtrRef ref = doc.getDocument().getBody().getSectPr().addNewFooterReference();
295
    	ref.setType(type);
284
        ref.setType(type);
296
    	ref.setId(wrapper.getPackageRelationship().getId());
285
        ref.setId(wrapper.getPackageRelationship().getId());
297
	}
286
    }
298
287
299
288
300
	private void setHeaderReference(Enum type, XWPFHeaderFooter wrapper) {
289
    private void setHeaderReference(Enum type, XWPFHeaderFooter wrapper) {
301
		CTHdrFtrRef ref = doc.getDocument().getBody().getSectPr().addNewHeaderReference();
290
        CTHdrFtrRef ref = doc.getDocument().getBody().getSectPr().addNewHeaderReference();
302
    	ref.setType(type);
291
        ref.setType(type);
303
    	ref.setId(wrapper.getPackageRelationship().getId());
292
        ref.setId(wrapper.getPackageRelationship().getId());
304
	}
293
    }
305
294
306
295
307
	private XmlOptions commit(XWPFHeaderFooter wrapper) {
296
    private XmlOptions commit(XWPFHeaderFooter wrapper) {
308
		XmlOptions xmlOptions = new XmlOptions(wrapper.DEFAULT_XML_OPTIONS);
297
        XmlOptions xmlOptions = new XmlOptions(wrapper.DEFAULT_XML_OPTIONS);
309
        Map<String, String> map = new HashMap<String, String>();
298
        Map<String, String> map = new HashMap<String, String>();
310
        map.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m");
299
        map.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m");
311
        map.put("urn:schemas-microsoft-com:office:office", "o");
300
        map.put("urn:schemas-microsoft-com:office:office", "o");
Lines 317-470 Link Here
317
        map.put("http://schemas.microsoft.com/office/word/2006/wordml", "wne");
306
        map.put("http://schemas.microsoft.com/office/word/2006/wordml", "wne");
318
        map.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "wp");
307
        map.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "wp");
319
        xmlOptions.setSaveSuggestedPrefixes(map);
308
        xmlOptions.setSaveSuggestedPrefixes(map);
320
		return xmlOptions;
309
        return xmlOptions;
321
	}
310
    }
322
	
323
	public XWPFHeader getFirstPageHeader() {
324
		return firstPageHeader;
325
	}
326
	public XWPFFooter getFirstPageFooter() {
327
		return firstPageFooter;
328
	}
329
	/**
330
	 * Returns the odd page header. This is
331
	 *  also the same as the default one...
332
	 */
333
	public XWPFHeader getOddPageHeader() {
334
		return defaultHeader;
335
	}
336
	/**
337
	 * Returns the odd page footer. This is
338
	 *  also the same as the default one...
339
	 */
340
	public XWPFFooter getOddPageFooter() {
341
		return defaultFooter;
342
	}
343
	public XWPFHeader getEvenPageHeader() {
344
		return evenPageHeader;
345
	}
346
	public XWPFFooter getEvenPageFooter() {
347
		return evenPageFooter;
348
	}
349
	public XWPFHeader getDefaultHeader() {
350
		return defaultHeader;
351
	}
352
	public XWPFFooter getDefaultFooter() {
353
		return defaultFooter;
354
	}
355
311
356
	/**
312
    public XWPFHeader getFirstPageHeader() {
357
	 * Get the header that applies to the given
313
        return firstPageHeader;
358
	 *  (1 based) page.
314
    }
359
	 * @param pageNumber The one based page number
315
    public XWPFFooter getFirstPageFooter() {
360
	 */
316
        return firstPageFooter;
361
	public XWPFHeader getHeader(int pageNumber) {
317
    }
362
		if(pageNumber == 1 && firstPageHeader != null) {
318
    /**
363
			return firstPageHeader;
319
     * Returns the odd page header. This is
364
		}
320
     *  also the same as the default one...
365
		if(pageNumber % 2 == 0 && evenPageHeader != null) {
321
     */
366
			return evenPageHeader;
322
    public XWPFHeader getOddPageHeader() {
367
		}
323
        return defaultHeader;
368
		return defaultHeader;
324
    }
369
	}
325
    /**
370
	/**
326
     * Returns the odd page footer. This is
371
	 * Get the footer that applies to the given
327
     *  also the same as the default one...
372
	 *  (1 based) page.
328
     */
373
	 * @param pageNumber The one based page number
329
    public XWPFFooter getOddPageFooter() {
374
	 */
330
        return defaultFooter;
375
	public XWPFFooter getFooter(int pageNumber) {
331
    }
376
		if(pageNumber == 1 && firstPageFooter != null) {
332
    public XWPFHeader getEvenPageHeader() {
377
			return firstPageFooter;
333
        return evenPageHeader;
378
		}
334
    }
379
		if(pageNumber % 2 == 0 && evenPageFooter != null) {
335
    public XWPFFooter getEvenPageFooter() {
380
			return evenPageFooter;
336
        return evenPageFooter;
381
		}
337
    }
382
		return defaultFooter;
338
    public XWPFHeader getDefaultHeader() {
383
	}
339
        return defaultHeader;
340
    }
341
    public XWPFFooter getDefaultFooter() {
342
        return defaultFooter;
343
    }
344
345
    /**
346
     * Get the header that applies to the given
347
     *  (1 based) page.
348
     * @param pageNumber The one based page number
349
     */
350
    public XWPFHeader getHeader(int pageNumber) {
351
        if(pageNumber == 1 && firstPageHeader != null) {
352
            return firstPageHeader;
353
        }
354
        if(pageNumber % 2 == 0 && evenPageHeader != null) {
355
            return evenPageHeader;
356
        }
357
        return defaultHeader;
358
    }
359
    /**
360
     * Get the footer that applies to the given
361
     *  (1 based) page.
362
     * @param pageNumber The one based page number
363
     */
364
    public XWPFFooter getFooter(int pageNumber) {
365
        if(pageNumber == 1 && firstPageFooter != null) {
366
            return firstPageFooter;
367
        }
368
        if(pageNumber % 2 == 0 && evenPageFooter != null) {
369
            return evenPageFooter;
370
        }
371
        return defaultFooter;
372
    }
384
373
374
    public void createWatermark(String text) {
375
        XWPFParagraph[] pars = new XWPFParagraph[1];
376
        try {
377
            pars[0] = getWatermarkParagraph(text, 1);
378
            createHeader(DEFAULT, pars);
379
            pars[0] = getWatermarkParagraph(text, 2);
380
            createHeader(FIRST, pars);
381
            pars[0] = getWatermarkParagraph(text, 3);
382
            createHeader(EVEN, pars);
383
        } catch (IOException e) {
384
            // TODO Auto-generated catch block
385
            e.printStackTrace();
386
        }
387
    }
385
388
386
	public void createWatermark(String text) {
389
    /*
387
		XWPFParagraph[] pars = new XWPFParagraph[1];
390
     * This is the default Watermark paragraph; the only variable is the text message
388
		try {
391
     * TODO: manage all the other variables
389
			pars[0] = getWatermarkParagraph(text, 1);
392
     */
390
			createHeader(DEFAULT, pars);
393
    private XWPFParagraph getWatermarkParagraph(String text, int idx) {
391
			pars[0] = getWatermarkParagraph(text, 2);
394
        CTP p = CTP.Factory.newInstance();
392
			createHeader(FIRST, pars);
395
        byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
393
			pars[0] = getWatermarkParagraph(text, 3);
396
        byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
394
			createHeader(EVEN, pars);
397
        p.setRsidP(rsidr);
395
		} catch (IOException e) {
398
        p.setRsidRDefault(rsidrdefault);
396
			// TODO Auto-generated catch block
399
        CTPPr pPr = p.addNewPPr();
397
			e.printStackTrace();
400
        pPr.addNewPStyle().setVal("Header");
398
		}
401
        // start watermark paragraph
399
	}
402
        CTR r = p.addNewR();
400
	
403
        CTRPr rPr = r.addNewRPr();
401
	
404
        rPr.addNewNoProof();
402
	/*
405
        CTPicture pict = r.addNewPict();
403
	 * This is the default Watermark paragraph; the only variable is the text message
406
        CTGroup group = CTGroup.Factory.newInstance();
404
	 * TODO: manage all the other variables
407
        CTShapetype shapetype = group.addNewShapetype();
405
	 */
408
        shapetype.setId("_x0000_t136");
406
	private XWPFParagraph getWatermarkParagraph(String text, int idx) {
409
        shapetype.setCoordsize("1600,21600");
407
		CTP p = CTP.Factory.newInstance();
410
        shapetype.setSpt(136);
408
		byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
411
        shapetype.setAdj("10800");
409
		byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
412
        shapetype.setPath2("m@7,0l@8,0m@5,21600l@6,21600e");
410
		p.setRsidP(rsidr);
413
        CTFormulas formulas = shapetype.addNewFormulas();
411
		p.setRsidRDefault(rsidrdefault);
414
        formulas.addNewF().setEqn("sum #0 0 10800");
412
		CTPPr pPr = p.addNewPPr();
415
        formulas.addNewF().setEqn("prod #0 2 1");
413
		pPr.addNewPStyle().setVal("Header");
416
        formulas.addNewF().setEqn("sum 21600 0 @1");
414
		// start watermark paragraph
417
        formulas.addNewF().setEqn("sum 0 0 @2");
415
		CTR r = p.addNewR();
418
        formulas.addNewF().setEqn("sum 21600 0 @3");
416
		CTRPr rPr = r.addNewRPr();
419
        formulas.addNewF().setEqn("if @0 @3 0");
417
		rPr.addNewNoProof();
420
        formulas.addNewF().setEqn("if @0 21600 @1");
418
		CTPicture pict = r.addNewPict();
421
        formulas.addNewF().setEqn("if @0 0 @2");
419
		CTGroup group = CTGroup.Factory.newInstance();
422
        formulas.addNewF().setEqn("if @0 @4 21600");
420
		CTShapetype shapetype = group.addNewShapetype();
423
        formulas.addNewF().setEqn("mid @5 @6");
421
		shapetype.setId("_x0000_t136");
424
        formulas.addNewF().setEqn("mid @8 @5");
422
		shapetype.setCoordsize("1600,21600");
425
        formulas.addNewF().setEqn("mid @7 @8");
423
		shapetype.setSpt(136);
426
        formulas.addNewF().setEqn("mid @6 @7");
424
		shapetype.setAdj("10800");
427
        formulas.addNewF().setEqn("sum @6 0 @5");
425
		shapetype.setPath2("m@7,0l@8,0m@5,21600l@6,21600e");
428
        CTPath path = shapetype.addNewPath();
426
		CTFormulas formulas = shapetype.addNewFormulas();
429
        path.setTextpathok(STTrueFalse.T);
427
		formulas.addNewF().setEqn("sum #0 0 10800");
430
        path.setConnecttype(STConnectType.CUSTOM);
428
		formulas.addNewF().setEqn("prod #0 2 1");
431
        path.setConnectlocs("@9,0;@10,10800;@11,21600;@12,10800");
429
		formulas.addNewF().setEqn("sum 21600 0 @1");
432
        path.setConnectangles("270,180,90,0");
430
		formulas.addNewF().setEqn("sum 0 0 @2");
433
        CTTextPath shapeTypeTextPath = shapetype.addNewTextpath();
431
		formulas.addNewF().setEqn("sum 21600 0 @3");
434
        shapeTypeTextPath.setOn(STTrueFalse.T);
432
		formulas.addNewF().setEqn("if @0 @3 0");
435
        shapeTypeTextPath.setFitshape(STTrueFalse.T);
433
		formulas.addNewF().setEqn("if @0 21600 @1");
436
        CTHandles handles = shapetype.addNewHandles();
434
		formulas.addNewF().setEqn("if @0 0 @2");
437
        CTH h = handles.addNewH();
435
		formulas.addNewF().setEqn("if @0 @4 21600");
438
        h.setPosition("#0,bottomRight");
436
		formulas.addNewF().setEqn("mid @5 @6");
439
        h.setXrange("6629,14971");
437
		formulas.addNewF().setEqn("mid @8 @5");
440
        CTLock lock = shapetype.addNewLock();
438
		formulas.addNewF().setEqn("mid @7 @8");
441
        lock.setExt(STExt.EDIT);
439
		formulas.addNewF().setEqn("mid @6 @7");
442
        CTShape shape = group.addNewShape();
440
		formulas.addNewF().setEqn("sum @6 0 @5");
443
        shape.setId("PowerPlusWaterMarkObject" + idx);
441
		CTPath path = shapetype.addNewPath();
444
        shape.setSpid("_x0000_s102" + (4+idx));
442
		path.setTextpathok(STTrueFalse.T);
445
        shape.setType("#_x0000_t136");
443
		path.setConnecttype(STConnectType.CUSTOM);
446
        shape.setStyle("position:absolute;margin-left:0;margin-top:0;width:415pt;height:207.5pt;z-index:-251654144;mso-wrap-edited:f;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin");
444
		path.setConnectlocs("@9,0;@10,10800;@11,21600;@12,10800");
447
        shape.setWrapcoords("616 5068 390 16297 39 16921 -39 17155 7265 17545 7186 17467 -39 17467 18904 17467 10507 17467 8710 17545 18904 17077 18787 16843 18358 16297 18279 12554 19178 12476 20701 11774 20779 11228 21131 10059 21248 8811 21248 7563 20975 6316 20935 5380 19490 5146 14022 5068 2616 5068");
445
		path.setConnectangles("270,180,90,0");
448
        shape.setFillcolor("black");
446
		CTTextPath shapeTypeTextPath = shapetype.addNewTextpath();
449
        shape.setStroked(STTrueFalse.FALSE);
447
		shapeTypeTextPath.setOn(STTrueFalse.T);
450
        CTTextPath shapeTextPath = shape.addNewTextpath();
448
		shapeTypeTextPath.setFitshape(STTrueFalse.T);
451
        shapeTextPath.setStyle("font-family:&quot;Cambria&quot;;font-size:1pt");
449
		CTHandles handles = shapetype.addNewHandles();
452
        shapeTextPath.setString(text);
450
		CTH h = handles.addNewH();
453
        pict.set(group);
451
		h.setPosition("#0,bottomRight");
454
        // end watermark paragraph
452
		h.setXrange("6629,14971");
455
        return new XWPFParagraph(p, doc);
453
		CTLock lock = shapetype.addNewLock();
456
    }
454
		lock.setExt(STExt.EDIT);
455
		CTShape shape = group.addNewShape();
456
		shape.setId("PowerPlusWaterMarkObject" + idx);
457
		shape.setSpid("_x0000_s102" + (4+idx));
458
		shape.setType("#_x0000_t136");
459
		shape.setStyle("position:absolute;margin-left:0;margin-top:0;width:415pt;height:207.5pt;z-index:-251654144;mso-wrap-edited:f;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin");
460
		shape.setWrapcoords("616 5068 390 16297 39 16921 -39 17155 7265 17545 7186 17467 -39 17467 18904 17467 10507 17467 8710 17545 18904 17077 18787 16843 18358 16297 18279 12554 19178 12476 20701 11774 20779 11228 21131 10059 21248 8811 21248 7563 20975 6316 20935 5380 19490 5146 14022 5068 2616 5068");
461
		shape.setFillcolor("black");
462
		shape.setStroked(STTrueFalse.FALSE);
463
		CTTextPath shapeTextPath = shape.addNewTextpath();
464
		shapeTextPath.setStyle("font-family:&quot;Cambria&quot;;font-size:1pt");
465
		shapeTextPath.setString(text);
466
		pict.set(group);
467
		// end watermark paragraph
468
		return new XWPFParagraph(p, doc);
469
	}
470
}
457
}
(-)src/java/org/apache/poi/util/IOUtils.java (+9 lines)
Lines 23-28 Link Here
23
import java.io.OutputStream;
23
import java.io.OutputStream;
24
import java.nio.ByteBuffer;
24
import java.nio.ByteBuffer;
25
import java.nio.channels.ReadableByteChannel;
25
import java.nio.channels.ReadableByteChannel;
26
import java.util.zip.CRC32;
27
import java.util.zip.Checksum;
26
28
27
public final class IOUtils {
29
public final class IOUtils {
28
	private IOUtils() {
30
	private IOUtils() {
Lines 129-132 Link Here
129
			}
131
			}
130
		}
132
		}
131
	}
133
	}
134
135
    public static Long calculateChecksum(byte[] data) {
136
        Checksum sum = new CRC32();
137
        sum.update(data, 0, data.length);
138
        Long checksum = new Long(sum.getValue());
139
        return checksum;
140
    }
132
}
141
}
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java (-8 / +7 lines)
Lines 43-53 Link Here
43
 *
43
 *
44
 */
44
 */
45
public class XWPFStyles extends POIXMLDocumentPart{
45
public class XWPFStyles extends POIXMLDocumentPart{
46
	private CTStyles ctStyles;
46
    
47
	protected XWPFLatentStyles latentStyles;
47
    private List<XWPFStyle> listStyle = new ArrayList<XWPFStyle>();
48
	protected List<XWPFStyle> listStyle;
48
    private CTStyles ctStyles;
49
	
49
    XWPFLatentStyles latentStyles;
50
	/**
50
51
    /**
51
     * Construct XWPFStyles from a package part
52
     * Construct XWPFStyles from a package part
52
     *
53
     *
53
     * @param part the package part holding the data of the styles,
54
     * @param part the package part holding the data of the styles,
Lines 56-69 Link Here
56
57
57
	public XWPFStyles(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException{
58
	public XWPFStyles(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException{
58
		super(part, rel);
59
		super(part, rel);
59
		onDocumentRead();
60
	}
60
	}
61
	/**
61
	/**
62
	 * Read document
62
	 * Read document
63
	 */
63
	 */
64
	 @Override
64
	 @Override
65
	protected void onDocumentRead ()throws IOException{
65
	protected void onDocumentRead ()throws IOException{
66
		listStyle = new ArrayList<XWPFStyle>();
67
		StylesDocument stylesDoc;
66
		StylesDocument stylesDoc;
68
		try {
67
		try {
69
			InputStream is = getPackagePart().getInputStream();
68
			InputStream is = getPackagePart().getInputStream();
Lines 84-90 Link Here
84
	    protected void commit() throws IOException {
83
	    protected void commit() throws IOException {
85
	        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
84
	        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
86
	        xmlOptions.setSaveSyntheticDocumentElement(new QName(CTStyles.type.getName().getNamespaceURI(), "styles"));
85
	        xmlOptions.setSaveSyntheticDocumentElement(new QName(CTStyles.type.getName().getNamespaceURI(), "styles"));
87
	        Map map = new HashMap();
86
	        Map<String,String> map = new HashMap<String,String>();
88
	        map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r");
87
	        map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r");
89
	        map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w");
88
	        map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w");
90
	        xmlOptions.setSaveSuggestedPrefixes(map);
89
	        xmlOptions.setSaveSuggestedPrefixes(map);
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRun.java (-203 / +236 lines)
Lines 45-50 Link Here
45
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
45
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
46
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
46
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
47
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
47
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
48
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
48
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
49
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
49
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr;
50
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr;
50
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
51
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
Lines 87-142 Link Here
87
    public XWPFRun(CTR r, XWPFParagraph p) {
88
    public XWPFRun(CTR r, XWPFParagraph p) {
88
        this.run = r;
89
        this.run = r;
89
        this.paragraph = p;
90
        this.paragraph = p;
90
        
91
92
        /**
93
         * reserve already occupied drawing ids, so reserving new ids later will
94
         * not corrupt the document
95
         */
96
        List<CTDrawing> drawingList = r.getDrawingList();
97
        for (CTDrawing ctDrawing : drawingList) {
98
            List<CTAnchor> anchorList = ctDrawing.getAnchorList();
99
            for (CTAnchor anchor : anchorList) {
100
                if (anchor.getDocPr() != null) {
101
                    getDocument().getDrawingIdManager().reserve(anchor.getDocPr().getId());
102
                }
103
            }
104
            List<CTInline> inlineList = ctDrawing.getInlineList();
105
            for (CTInline inline : inlineList) {
106
                if (inline.getDocPr() != null) {
107
                    getDocument().getDrawingIdManager().reserve(inline.getDocPr().getId());
108
                }
109
            }
110
        }
111
91
        // Look for any text in any of our pictures or drawings
112
        // Look for any text in any of our pictures or drawings
92
        StringBuffer text = new StringBuffer();
113
        StringBuffer text = new StringBuffer();
93
        List<XmlObject> pictTextObjs = new ArrayList<XmlObject>();
114
        List<XmlObject> pictTextObjs = new ArrayList<XmlObject>();
94
        pictTextObjs.addAll(r.getPictList());
115
        pictTextObjs.addAll(r.getPictList());
95
        pictTextObjs.addAll(r.getDrawingList());
116
        pictTextObjs.addAll(drawingList);
96
        for(XmlObject o : pictTextObjs) {
117
        for(XmlObject o : pictTextObjs) {
97
           XmlObject[] t = o
118
            XmlObject[] t = o.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//w:t");
98
                 .selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//w:t");
119
            for (int m = 0; m < t.length; m++) {
99
           for (int m = 0; m < t.length; m++) {
120
                NodeList kids = t[m].getDomNode().getChildNodes();
100
              NodeList kids = t[m].getDomNode().getChildNodes();
121
                for (int n = 0; n < kids.getLength(); n++) {
101
              for (int n = 0; n < kids.getLength(); n++) {
122
                    if (kids.item(n) instanceof Text) {
102
                 if (kids.item(n) instanceof Text) {
123
                        if(text.length() > 0)
103
                    if(text.length() > 0)
124
                            text.append("\n");
104
                       text.append("\n");
125
                        text.append(kids.item(n).getNodeValue());
105
                    text.append(kids.item(n).getNodeValue());
126
                    }
106
                 }
127
                }
107
              }
128
            }
108
           }
109
        }
129
        }
110
        pictureText = text.toString();
130
        pictureText = text.toString();
111
        
131
112
        // Do we have any embedded pictures?
132
        // Do we have any embedded pictures?
113
        // (They're a different CTPicture, under the drawingml namespace)
133
        // (They're a different CTPicture, under the drawingml namespace)
114
        pictures = new ArrayList<XWPFPicture>();
134
        pictures = new ArrayList<XWPFPicture>();
115
        for(XmlObject o : pictTextObjs) {
135
        for(XmlObject o : pictTextObjs) {
116
           for(CTPicture pict : getCTPictures(o)) {
136
            for(CTPicture pict : getCTPictures(o)) {
117
              XWPFPicture picture = new XWPFPicture( pict, p );
137
                XWPFPicture picture = new XWPFPicture(pict, this);
118
              pictures.add(picture);
138
                pictures.add(picture);
119
           }
139
            }
120
        }
140
        }
121
    }
141
    }
122
    
142
123
    private List<CTPicture> getCTPictures(XmlObject o) {
143
    private List<CTPicture> getCTPictures(XmlObject o) {
124
       List<CTPicture> pictures = new ArrayList<CTPicture>(); 
144
        List<CTPicture> pictures = new ArrayList<CTPicture>(); 
125
       XmlObject[] picts = o.selectPath("declare namespace pic='"+CTPicture.type.getName().getNamespaceURI()+"' .//pic:pic");
145
        XmlObject[] picts = o.selectPath("declare namespace pic='"+CTPicture.type.getName().getNamespaceURI()+"' .//pic:pic");
126
       for(XmlObject pict : picts) {
146
        for(XmlObject pict : picts) {
127
          if(pict instanceof XmlAnyTypeImpl) {
147
            if(pict instanceof XmlAnyTypeImpl) {
128
             // Pesky XmlBeans bug - see Bugzilla #49934
148
                // Pesky XmlBeans bug - see Bugzilla #49934
129
             try {
149
                try {
130
                pict = CTPicture.Factory.parse( pict.toString() );
150
                    pict = CTPicture.Factory.parse( pict.toString() );
131
             } catch(XmlException e) {
151
                } catch(XmlException e) {
132
                throw new POIXMLException(e);
152
                    throw new POIXMLException(e);
133
             }
153
                }
134
          }
154
            }
135
          if(pict instanceof CTPicture) {
155
            if(pict instanceof CTPicture) {
136
             pictures.add((CTPicture)pict);
156
                pictures.add((CTPicture)pict);
137
          }
157
            }
138
       }
158
        }
139
       return pictures;
159
        return pictures;
140
    }
160
    }
141
161
142
    /**
162
    /**
Lines 155-172 Link Here
155
    public XWPFParagraph getParagraph() {
175
    public XWPFParagraph getParagraph() {
156
        return paragraph;
176
        return paragraph;
157
    }
177
    }
158
    
178
179
    /**
180
     * @return The {@link XWPFDocument} instance, this run belongs to, or
181
     *         <code>null</code> if parent structure (paragraph > document) is not properly set.
182
     */
183
    public XWPFDocument getDocument() {
184
        if (paragraph != null) {
185
            return paragraph.getDocument();
186
        }
187
        return null;
188
    }
189
159
    /**
190
    /**
160
     * For isBold, isItalic etc
191
     * For isBold, isItalic etc
161
     */
192
     */
162
    private boolean isCTOnOff(CTOnOff onoff) {
193
    private boolean isCTOnOff(CTOnOff onoff) {
163
       if(! onoff.isSetVal())
194
        if(! onoff.isSetVal())
164
          return true;
195
            return true;
165
       if(onoff.getVal() == STOnOff.ON)
196
        if(onoff.getVal() == STOnOff.ON)
166
          return true;
197
            return true;
167
       if(onoff.getVal() == STOnOff.TRUE)
198
        if(onoff.getVal() == STOnOff.TRUE)
168
          return true;
199
            return true;
169
       return false;
200
        return false;
170
    }
201
    }
171
202
172
    /**
203
    /**
Lines 177-184 Link Here
177
     */
208
     */
178
    public boolean isBold() {
209
    public boolean isBold() {
179
        CTRPr pr = run.getRPr();
210
        CTRPr pr = run.getRPr();
180
        if(pr == null || !pr.isSetB())
211
        if(pr == null || !pr.isSetB()) {
181
           return false;
212
            return false;
213
        }
182
        return isCTOnOff(pr.getB());
214
        return isCTOnOff(pr.getB());
183
    }
215
    }
184
216
Lines 221-227 Link Here
221
        return run.sizeOfTArray() == 0 ? null : run.getTArray(pos)
253
        return run.sizeOfTArray() == 0 ? null : run.getTArray(pos)
222
                .getStringValue();
254
                .getStringValue();
223
    }
255
    }
224
    
256
225
    /**
257
    /**
226
     * Returns text embedded in pictures
258
     * Returns text embedded in pictures
227
     */
259
     */
Lines 235-241 Link Here
235
     * @param value the literal text which shall be displayed in the document
267
     * @param value the literal text which shall be displayed in the document
236
     */
268
     */
237
    public void setText(String value) {
269
    public void setText(String value) {
238
       setText(value,run.getTList().size());
270
        setText(value,run.getTList().size());
239
    }
271
    }
240
272
241
    /**
273
    /**
Lines 245-257 Link Here
245
     * @param pos - position in the text array (NB: 0 based)
277
     * @param pos - position in the text array (NB: 0 based)
246
     */
278
     */
247
    public void setText(String value, int pos) {
279
    public void setText(String value, int pos) {
248
	if(pos > run.sizeOfTArray()) throw new ArrayIndexOutOfBoundsException("Value too large for the parameter position in XWPFRun.setText(String value,int pos)");
280
        if(pos > run.sizeOfTArray()) throw new ArrayIndexOutOfBoundsException("Value too large for the parameter position in XWPFRun.setText(String value,int pos)");
249
        CTText t = (pos < run.sizeOfTArray() && pos >= 0) ? run.getTArray(pos) : run.addNewT();
281
        CTText t = (pos < run.sizeOfTArray() && pos >= 0) ? run.getTArray(pos) : run.addNewT();
250
        t.setStringValue(value);
282
        t.setStringValue(value);
251
        preserveSpaces(t);
283
        preserveSpaces(t);
252
    }
284
    }
253
285
254
    
255
    /**
286
    /**
256
     * Whether the italic property should be applied to all non-complex script
287
     * Whether the italic property should be applied to all non-complex script
257
     * characters in the contents of this run when displayed in a document.
288
     * characters in the contents of this run when displayed in a document.
Lines 261-267 Link Here
261
    public boolean isItalic() {
292
    public boolean isItalic() {
262
        CTRPr pr = run.getRPr();
293
        CTRPr pr = run.getRPr();
263
        if(pr == null || !pr.isSetI())
294
        if(pr == null || !pr.isSetI())
264
           return false;
295
            return false;
265
        return isCTOnOff(pr.getI());
296
        return isCTOnOff(pr.getI());
266
    }
297
    }
267
298
Lines 306-312 Link Here
306
    public UnderlinePatterns getUnderline() {
337
    public UnderlinePatterns getUnderline() {
307
        CTRPr pr = run.getRPr();
338
        CTRPr pr = run.getRPr();
308
        return (pr != null && pr.isSetU()) ? UnderlinePatterns.valueOf(pr
339
        return (pr != null && pr.isSetU()) ? UnderlinePatterns.valueOf(pr
309
                .getU().getVal().intValue()) : UnderlinePatterns.NONE;
340
            .getU().getVal().intValue()) : UnderlinePatterns.NONE;
310
    }
341
    }
311
342
312
    /**
343
    /**
Lines 339-345 Link Here
339
    public boolean isStrike() {
370
    public boolean isStrike() {
340
        CTRPr pr = run.getRPr();
371
        CTRPr pr = run.getRPr();
341
        if(pr == null || !pr.isSetStrike())
372
        if(pr == null || !pr.isSetStrike())
342
           return false;
373
            return false;
343
        return isCTOnOff(pr.getStrike());
374
        return isCTOnOff(pr.getStrike());
344
    }
375
    }
345
376
Lines 384-391 Link Here
384
     */
415
     */
385
    public VerticalAlign getSubscript() {
416
    public VerticalAlign getSubscript() {
386
        CTRPr pr = run.getRPr();
417
        CTRPr pr = run.getRPr();
387
        return (pr != null && pr.isSetVertAlign()) ? VerticalAlign.valueOf(pr
418
        return (pr != null && pr.isSetVertAlign()) ? VerticalAlign.valueOf(pr.getVertAlign().getVal().intValue()) : VerticalAlign.BASELINE;
388
                .getVertAlign().getVal().intValue()) : VerticalAlign.BASELINE;
389
    }
419
    }
390
420
391
    /**
421
    /**
Lines 460-466 Link Here
460
     * @param size
490
     * @param size
461
     */
491
     */
462
    public void setFontSize(int size) {
492
    public void setFontSize(int size) {
463
	BigInteger bint=new BigInteger(""+size);
493
        BigInteger bint=new BigInteger(""+size);
464
        CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr();
494
        CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr();
465
        CTHpsMeasure ctSize = pr.isSetSz() ? pr.getSz() : pr.addNewSz();
495
        CTHpsMeasure ctSize = pr.isSetSz() ? pr.getSz() : pr.addNewSz();
466
        ctSize.setVal(bint.multiply(new BigInteger("2")));
496
        ctSize.setVal(bint.multiply(new BigInteger("2")));
Lines 503-509 Link Here
503
     * @param val
533
     * @param val
504
     */
534
     */
505
    public void setTextPosition(int val) {
535
    public void setTextPosition(int val) {
506
	BigInteger bint=new BigInteger(""+val);
536
        BigInteger bint=new BigInteger(""+val);
507
        CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr();
537
        CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr();
508
        CTSignedHpsMeasure position = pr.isSetPosition() ? pr.getPosition() : pr.addNewPosition();
538
        CTSignedHpsMeasure position = pr.isSetPosition() ? pr.getPosition() : pr.addNewPosition();
509
        position.setVal(bint);
539
        position.setVal(bint);
Lines 513-519 Link Here
513
     * 
543
     * 
514
     */
544
     */
515
    public void removeBreak() {
545
    public void removeBreak() {
516
	// TODO
546
        // TODO
517
    }
547
    }
518
548
519
    /**
549
    /**
Lines 525-531 Link Here
525
     * @see #addCarriageReturn() 
555
     * @see #addCarriageReturn() 
526
     */
556
     */
527
    public void addBreak() {
557
    public void addBreak() {
528
	run.addNewBr();
558
        run.addNewBr();
529
    } 
559
    } 
530
560
531
    /**
561
    /**
Lines 542-552 Link Here
542
     * @see BreakType
572
     * @see BreakType
543
     */
573
     */
544
    public void addBreak(BreakType type){
574
    public void addBreak(BreakType type){
545
	CTBr br=run.addNewBr();
575
        CTBr br=run.addNewBr();
546
	br.setType(STBrType.Enum.forInt(type.getValue()));
576
        br.setType(STBrType.Enum.forInt(type.getValue()));
547
    }
577
    }
548
578
549
    
550
    /**
579
    /**
551
     * Specifies that a break shall be placed at the current location in the run
580
     * Specifies that a break shall be placed at the current location in the run
552
     * content. A break is a special character which is used to override the
581
     * content. A break is a special character which is used to override the
Lines 560-568 Link Here
560
     * @see BreakClear
589
     * @see BreakClear
561
     */
590
     */
562
    public void addBreak(BreakClear clear){
591
    public void addBreak(BreakClear clear){
563
	CTBr br=run.addNewBr();
592
        CTBr br=run.addNewBr();
564
	br.setType(STBrType.Enum.forInt(BreakType.TEXT_WRAPPING.getValue()));
593
        br.setType(STBrType.Enum.forInt(BreakType.TEXT_WRAPPING.getValue()));
565
	    br.setClear(STBrClear.Enum.forInt(clear.getValue()));
594
        br.setClear(STBrClear.Enum.forInt(clear.getValue()));
566
    }
595
    }
567
596
568
    /**
597
    /**
Lines 578-590 Link Here
578
     * restarted on the next available line in the document.
607
     * restarted on the next available line in the document.
579
     */
608
     */
580
    public void addCarriageReturn() {
609
    public void addCarriageReturn() {
581
	run.addNewCr();
610
        run.addNewCr();
582
    }
611
    }
583
612
584
    public void removeCarriageReturn() {
613
    public void removeCarriageReturn() {
585
	//TODO
614
        //TODO
586
    }   
615
    }    
587
    
616
588
    /**
617
    /**
589
     * Adds a picture to the run. This method handles
618
     * Adds a picture to the run. This method handles
590
     *  attaching the picture data to the overall file.
619
     *  attaching the picture data to the overall file.
Lines 598-697 Link Here
598
     *  
627
     *  
599
     * @param pictureData The raw picture data
628
     * @param pictureData The raw picture data
600
     * @param pictureType The type of the picture, eg {@link Document#PICTURE_TYPE_JPEG}
629
     * @param pictureType The type of the picture, eg {@link Document#PICTURE_TYPE_JPEG}
601
    * @throws IOException 
630
     * @throws IOException 
602
    * @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException 
631
     * @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException 
603
    * @throws IOException 
632
     * @throws IOException 
604
     */
633
     */
605
    public XWPFPicture addPicture(InputStream pictureData, int pictureType, String filename, int width, int height)
634
    public XWPFPicture addPicture(InputStream pictureData, int pictureType, String filename, int width, int height)
606
    throws InvalidFormatException, IOException {
635
    throws InvalidFormatException, IOException {
607
       XWPFDocument doc = paragraph.document;
636
        XWPFDocument doc = paragraph.document;
608
       
637
609
       // Add the picture + relationship
638
        // Add the picture + relationship
610
       int picNumber = doc.addPicture(pictureData, pictureType);
639
        String relationId = doc.addPictureData(pictureData, pictureType);
611
       XWPFPictureData picData = doc.getAllPackagePictures().get(picNumber);
640
        XWPFPictureData picData = (XWPFPictureData) doc.getRelationById(relationId);
612
       
641
613
       // Create the drawing entry for it
642
        // Create the drawing entry for it
614
       try {
643
        try {
615
          CTDrawing drawing = run.addNewDrawing();
644
            CTDrawing drawing = run.addNewDrawing();
616
          CTInline inline = drawing.addNewInline();
645
            CTInline inline = drawing.addNewInline();
617
          
646
618
          // Do the fiddly namespace bits on the inline
647
            // Do the fiddly namespace bits on the inline
619
          // (We need full control of what goes where and as what)
648
            // (We need full control of what goes where and as what)
620
          String xml = 
649
            String xml = 
621
             "<a:graphic xmlns:a=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
650
                "<a:graphic xmlns:a=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
622
             "<a:graphicData uri=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
651
                "<a:graphicData uri=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
623
             "<pic:pic xmlns:pic=\"" + CTPicture.type.getName().getNamespaceURI() + "\" />" +
652
                "<pic:pic xmlns:pic=\"" + CTPicture.type.getName().getNamespaceURI() + "\" />" +
624
             "</a:graphicData>" +
653
                "</a:graphicData>" +
625
             "</a:graphic>";
654
                "</a:graphic>";
626
          inline.set(XmlToken.Factory.parse(xml));
655
            inline.set(XmlToken.Factory.parse(xml));
627
          
656
628
          // Setup the inline
657
            // Setup the inline
629
          inline.setDistT(0);
658
            inline.setDistT(0);
630
          inline.setDistR(0);
659
            inline.setDistR(0);
631
          inline.setDistB(0);
660
            inline.setDistB(0);
632
          inline.setDistL(0);
661
            inline.setDistL(0);
633
          
662
634
          CTNonVisualDrawingProps docPr = inline.addNewDocPr();
663
            CTNonVisualDrawingProps docPr = inline.addNewDocPr();
635
          docPr.setId(picNumber);
664
            long id = getParagraph().document.getDrawingIdManager().reserveNew();
636
          docPr.setName("Picture " + picNumber);
665
            docPr.setId(id);
637
          docPr.setDescr(filename);
666
            /* This name is not visible in Word 2010 anywhere. */
638
          
667
            docPr.setName("Drawing " + id);
639
          CTPositiveSize2D extent = inline.addNewExtent();
668
            docPr.setDescr(filename);
640
          extent.setCx(width);
669
641
          extent.setCy(height);
670
            CTPositiveSize2D extent = inline.addNewExtent();
642
   
671
            extent.setCx(width);
643
          // Grab the picture object
672
            extent.setCy(height);
644
          CTGraphicalObject graphic = inline.getGraphic();
673
645
          CTGraphicalObjectData graphicData = graphic.getGraphicData();
674
            // Grab the picture object
646
          CTPicture pic = getCTPictures(graphicData).get(0);
675
            CTGraphicalObject graphic = inline.getGraphic();
647
          
676
            CTGraphicalObjectData graphicData = graphic.getGraphicData();
648
          // Set it up
677
            CTPicture pic = getCTPictures(graphicData).get(0);
649
          CTPictureNonVisual nvPicPr = pic.addNewNvPicPr();
678
650
          
679
            // Set it up
651
          CTNonVisualDrawingProps cNvPr = nvPicPr.addNewCNvPr();
680
            CTPictureNonVisual nvPicPr = pic.addNewNvPicPr();
652
          cNvPr.setId(picNumber);
681
653
          cNvPr.setName("Picture " + picNumber);
682
            CTNonVisualDrawingProps cNvPr = nvPicPr.addNewCNvPr();
654
          cNvPr.setDescr(filename);
683
            /* use "0" for the id. See ECM-576, 20.2.2.3 */
655
          
684
            cNvPr.setId(0L);
656
          CTNonVisualPictureProperties cNvPicPr = nvPicPr.addNewCNvPicPr();
685
            /* This name is not visible in Word 2010 anywhere */
657
          cNvPicPr.addNewPicLocks().setNoChangeAspect(true);
686
            cNvPr.setName("Picture " + id);
658
          
687
            cNvPr.setDescr(filename);
659
          CTBlipFillProperties blipFill = pic.addNewBlipFill();
688
660
          CTBlip blip = blipFill.addNewBlip();
689
            CTNonVisualPictureProperties cNvPicPr = nvPicPr.addNewCNvPicPr();
661
          blip.setEmbed( picData.getPackageRelationship().getId() );
690
            cNvPicPr.addNewPicLocks().setNoChangeAspect(true);
662
          blipFill.addNewStretch().addNewFillRect();
691
663
          
692
            CTBlipFillProperties blipFill = pic.addNewBlipFill();
664
          CTShapeProperties spPr = pic.addNewSpPr();
693
            CTBlip blip = blipFill.addNewBlip();
665
          CTTransform2D xfrm = spPr.addNewXfrm();
694
            blip.setEmbed( picData.getPackageRelationship().getId() );
666
          
695
            blipFill.addNewStretch().addNewFillRect();
667
          CTPoint2D off = xfrm.addNewOff();
696
668
          off.setX(0);
697
            CTShapeProperties spPr = pic.addNewSpPr();
669
          off.setY(0);
698
            CTTransform2D xfrm = spPr.addNewXfrm();
670
          
699
671
          CTPositiveSize2D ext = xfrm.addNewExt();
700
            CTPoint2D off = xfrm.addNewOff();
672
          ext.setCx(width);
701
            off.setX(0);
673
          ext.setCy(height);
702
            off.setY(0);
674
          
703
675
          CTPresetGeometry2D prstGeom = spPr.addNewPrstGeom();
704
            CTPositiveSize2D ext = xfrm.addNewExt();
676
          prstGeom.setPrst(STShapeType.RECT);
705
            ext.setCx(width);
677
          prstGeom.addNewAvLst();
706
            ext.setCy(height);
678
          
707
679
          // Finish up
708
            CTPresetGeometry2D prstGeom = spPr.addNewPrstGeom();
680
          XWPFPicture xwpfPicture = new XWPFPicture(pic, paragraph);
709
            prstGeom.setPrst(STShapeType.RECT);
681
          pictures.add(xwpfPicture);
710
            prstGeom.addNewAvLst();
682
          return xwpfPicture;
711
683
       } catch(XmlException e) {
712
            // Finish up
684
          throw new IllegalStateException(e);
713
            XWPFPicture xwpfPicture = new XWPFPicture(pic, this);
685
       }
714
            pictures.add(xwpfPicture);
715
            return xwpfPicture;
716
        } catch(XmlException e) {
717
            throw new IllegalStateException(e);
718
        }
686
    }
719
    }
687
    
720
688
    /**
721
    /**
689
     * Returns the embedded pictures of the run. These
722
     * Returns the embedded pictures of the run. These
690
     *  are pictures which reference an external, 
723
     *  are pictures which reference an external, 
691
     *  embedded picture image such as a .png or .jpg
724
     *  embedded picture image such as a .png or .jpg
692
     */
725
     */
693
    public List<XWPFPicture> getEmbeddedPictures() {
726
    public List<XWPFPicture> getEmbeddedPictures() {
694
       return pictures;
727
        return pictures;
695
    }
728
    }
696
729
697
    /**
730
    /**
Lines 714-769 Link Here
714
     *  carriage returns in place of their xml equivalents.
747
     *  carriage returns in place of their xml equivalents.
715
     */
748
     */
716
    public String toString() {
749
    public String toString() {
717
       StringBuffer text = new StringBuffer();
750
        StringBuffer text = new StringBuffer();
718
       
751
719
       // Grab the text and tabs of the text run
752
        // Grab the text and tabs of the text run
720
       // Do so in a way that preserves the ordering
753
        // Do so in a way that preserves the ordering
721
       XmlCursor c = run.newCursor();
754
        XmlCursor c = run.newCursor();
722
       c.selectPath("./*");
755
        c.selectPath("./*");
723
       while (c.toNextSelection()) {
756
        while (c.toNextSelection()) {
724
           XmlObject o = c.getObject();
757
            XmlObject o = c.getObject();
725
           if (o instanceof CTText) {
758
            if (o instanceof CTText) {
726
               String tagName = o.getDomNode().getNodeName();
759
                String tagName = o.getDomNode().getNodeName();
727
               // Field Codes (w:instrText, defined in spec sec. 17.16.23)
760
                // Field Codes (w:instrText, defined in spec sec. 17.16.23)
728
               //  come up as instances of CTText, but we don't want them
761
                //  come up as instances of CTText, but we don't want them
729
               //  in the normal text output
762
                //  in the normal text output
730
               if (!"w:instrText".equals(tagName)) {
763
                if (!"w:instrText".equals(tagName)) {
731
                  text.append(((CTText) o).getStringValue());
764
                    text.append(((CTText) o).getStringValue());
732
               }
765
                }
733
           }
766
            }
734
           
767
735
           if (o instanceof CTPTab) {
768
            if (o instanceof CTPTab) {
736
               text.append("\t");
769
                text.append("\t");
737
           }
770
            }
738
           if (o instanceof CTBr) {
771
            if (o instanceof CTBr) {
739
              text.append("\n");
772
                text.append("\n");
740
           }
773
            }
741
           if (o instanceof CTEmpty) {
774
            if (o instanceof CTEmpty) {
742
              // Some inline text elements get returned not as
775
                // Some inline text elements get returned not as
743
              //  themselves, but as CTEmpty, owing to some odd
776
                //  themselves, but as CTEmpty, owing to some odd
744
              //  definitions around line 5642 of the XSDs
777
                //  definitions around line 5642 of the XSDs
745
              // This bit works around it, and replicates the above
778
                // This bit works around it, and replicates the above
746
              //  rules for that case
779
                //  rules for that case
747
              String tagName = o.getDomNode().getNodeName();
780
                String tagName = o.getDomNode().getNodeName();
748
              if ("w:tab".equals(tagName)) {
781
                if ("w:tab".equals(tagName)) {
749
                 text.append("\t");
782
                    text.append("\t");
750
              }
783
                }
751
              if ("w:br".equals(tagName)) {
784
                if ("w:br".equals(tagName)) {
752
                 text.append("\n");
785
                    text.append("\n");
753
              }
786
                }
754
              if ("w:cr".equals(tagName)) {
787
                if ("w:cr".equals(tagName)) {
755
                 text.append("\n");
788
                    text.append("\n");
756
              }
789
                }
757
           }
790
            }
758
       }
791
        }
759
792
760
       c.dispose();
793
        c.dispose();
761
       
794
762
       // Any picture text?
795
        // Any picture text?
763
       if(pictureText != null && pictureText.length() > 0) {
796
        if(pictureText != null && pictureText.length() > 0) {
764
          text.append("\n").append(pictureText);
797
            text.append("\n").append(pictureText);
765
       }
798
        }
766
       
799
767
       return text.toString();
800
        return text.toString();
768
    }
801
    }
769
}
802
}
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java (-77 / +58 lines)
Lines 19-35 Link Here
19
import java.io.IOException;
19
import java.io.IOException;
20
import java.io.InputStream;
20
import java.io.InputStream;
21
import java.io.OutputStream;
21
import java.io.OutputStream;
22
import java.util.ArrayList;
23
import java.util.HashMap;
22
import java.util.HashMap;
24
import java.util.Map;
23
import java.util.Map;
25
24
26
import javax.xml.namespace.QName;
25
import javax.xml.namespace.QName;
27
26
28
import org.apache.poi.POIXMLDocumentPart;
27
import org.apache.poi.POIXMLDocumentPart;
28
import org.apache.poi.POIXMLException;
29
import org.apache.poi.openxml4j.opc.PackagePart;
29
import org.apache.poi.openxml4j.opc.PackagePart;
30
import org.apache.poi.openxml4j.opc.PackageRelationship;
30
import org.apache.poi.openxml4j.opc.PackageRelationship;
31
import org.apache.xmlbeans.XmlCursor;
31
import org.apache.xmlbeans.XmlCursor;
32
import org.apache.xmlbeans.XmlException;
33
import org.apache.xmlbeans.XmlObject;
32
import org.apache.xmlbeans.XmlObject;
34
import org.apache.xmlbeans.XmlOptions;
33
import org.apache.xmlbeans.XmlOptions;
35
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr;
34
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr;
Lines 46-83 Link Here
46
        super();
45
        super();
47
    }
46
    }
48
47
49
	public XWPFFooter(XWPFDocument doc, CTHdrFtr hdrFtr) throws IOException {
48
    public XWPFFooter(XWPFDocument doc, CTHdrFtr hdrFtr) throws IOException {
50
		super(doc, hdrFtr);
49
        super(doc, hdrFtr);
51
		bodyElements = new ArrayList<IBodyElement>();
50
        XmlCursor cursor = headerFooter.newCursor();
52
		paragraphs = new ArrayList<XWPFParagraph>();
53
		tables = new ArrayList<XWPFTable>();
54
		XmlCursor cursor = headerFooter.newCursor();
55
        cursor.selectPath("./*");
51
        cursor.selectPath("./*");
56
        while (cursor.toNextSelection()) {
52
        while (cursor.toNextSelection()) {
57
            XmlObject o = cursor.getObject();
53
            XmlObject o = cursor.getObject();
58
            if (o instanceof CTP) {
54
            if (o instanceof CTP) {
59
            	XWPFParagraph p = new XWPFParagraph((CTP)o, this);
55
                XWPFParagraph p = new XWPFParagraph((CTP)o, this);
60
            	paragraphs.add(p);
56
                paragraphs.add(p);
61
            	bodyElements.add(p);
57
                bodyElements.add(p);
62
            }
58
            }
63
            if (o instanceof CTTbl) {
59
            if (o instanceof CTTbl) {
64
            	XWPFTable t = new XWPFTable((CTTbl)o, this);
60
                XWPFTable t = new XWPFTable((CTTbl)o, this);
65
            	tables.add(t);
61
                tables.add(t);
66
            	bodyElements.add(t);
62
                bodyElements.add(t);
67
            }
63
            }
68
        }
64
        }
69
        cursor.dispose();
65
        cursor.dispose();
70
        getAllPictures();
66
    }
71
	}
67
68
    public XWPFFooter(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel) throws IOException {
69
        super(parent, part, rel);
70
    }
72
71
73
	public XWPFFooter(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel) throws IOException {
72
    /**
74
		super(parent, part, rel);
73
     * save and commit footer
75
	}
74
     */
76
	
75
    @Override
77
	/**
78
	 * save and commit footer
79
	 */
80
	@Override
81
    protected void commit() throws IOException {
76
    protected void commit() throws IOException {
82
        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
77
        XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
83
        xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "ftr"));
78
        xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "ftr"));
Lines 97-154 Link Here
97
        super._getHdrFtr().save(out, xmlOptions);
92
        super._getHdrFtr().save(out, xmlOptions);
98
        out.close();
93
        out.close();
99
    }
94
    }
100
	
95
101
	  @Override  
96
    @Override  
102
	    protected void onDocumentRead(){
97
    protected void onDocumentRead() throws IOException{
103
		  	bodyElements = new ArrayList<IBodyElement>();
98
        super.onDocumentRead();
104
	        paragraphs = new ArrayList<XWPFParagraph>();
99
        FtrDocument ftrDocument = null;
105
	        tables= new ArrayList<XWPFTable>();
100
        InputStream is;
106
	        FtrDocument ftrDocument = null;
101
        try {
107
			InputStream is;
102
            is = getPackagePart().getInputStream();
108
			try {
103
            ftrDocument = FtrDocument.Factory.parse(is);
109
				is = getPackagePart().getInputStream();
104
            headerFooter = ftrDocument.getFtr();
110
				ftrDocument = FtrDocument.Factory.parse(is);
105
            // parse the document with cursor and add
111
				headerFooter = ftrDocument.getFtr();
106
            // the XmlObject to its lists
112
		        // parse the document with cursor and add
107
            XmlCursor cursor = headerFooter.newCursor();
113
		        // the XmlObject to its lists
108
            cursor.selectPath("./*");
114
				XmlCursor cursor = headerFooter.newCursor();
109
            while (cursor.toNextSelection()) {
115
		        cursor.selectPath("./*");
110
                XmlObject o = cursor.getObject();
116
		        while (cursor.toNextSelection()) {
111
                if (o instanceof CTP) {
117
		            XmlObject o = cursor.getObject();
112
                    XWPFParagraph p = new XWPFParagraph((CTP)o, this);
118
		            if (o instanceof CTP) {
113
                    paragraphs.add(p);
119
		            	XWPFParagraph p = new XWPFParagraph((CTP)o, this);
114
                    bodyElements.add(p);
120
		            	paragraphs.add(p);
115
                }
121
		            	bodyElements.add(p);
116
                if (o instanceof CTTbl) {
122
		            }
117
                    XWPFTable t = new XWPFTable((CTTbl)o, this);
123
		            if (o instanceof CTTbl) {
118
                    tables.add(t);
124
		            	XWPFTable t = new XWPFTable((CTTbl)o, this);
119
                    bodyElements.add(t);
125
		            	tables.add(t);
120
                }
126
		            	bodyElements.add(t);
121
            }
127
		            }
122
            cursor.dispose();
128
		        }
123
        } catch (Exception e) {
129
                cursor.dispose();
124
            throw new POIXMLException(e);
130
		        getAllPictures();
125
        }
131
			} catch (IOException e) {
126
    }
132
				// TODO Auto-generated catch block
133
				e.printStackTrace();
134
			} catch (XmlException e) {
135
				// TODO Auto-generated catch block
136
				e.printStackTrace();
137
			}
138
	  }
139
		/**
140
		 * returns the Part, to which the body belongs, which you need for adding relationship to other parts
141
		 * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
142
		 */
143
		public IBody getPart() {
144
			return this;
145
		}
146
127
147
		/**
128
    /**
148
		 * get the PartType of the body
129
     * get the PartType of the body
149
		 * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
130
     * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
150
		 */
131
     */
151
		public BodyType getPartType() {
132
    public BodyType getPartType() {
152
			return BodyType.FOOTER;
133
        return BodyType.FOOTER;
153
		}
134
    }
154
}
135
}
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java (-419 / +387 lines)
Lines 25-35 Link Here
25
25
26
import org.apache.poi.POIXMLDocumentPart;
26
import org.apache.poi.POIXMLDocumentPart;
27
import org.apache.poi.POIXMLException;
27
import org.apache.poi.POIXMLException;
28
import org.apache.poi.POIXMLRelation;
28
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
29
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
29
import org.apache.poi.openxml4j.opc.PackagePart;
30
import org.apache.poi.openxml4j.opc.PackagePart;
30
import org.apache.poi.openxml4j.opc.PackagePartName;
31
import org.apache.poi.openxml4j.opc.PackagePartName;
31
import org.apache.poi.openxml4j.opc.PackageRelationship;
32
import org.apache.poi.openxml4j.opc.PackageRelationship;
32
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
33
import org.apache.poi.openxml4j.opc.TargetMode;
33
import org.apache.poi.util.IOUtils;
34
import org.apache.poi.util.IOUtils;
34
import org.apache.poi.util.Internal;
35
import org.apache.poi.util.Internal;
35
import org.apache.xmlbeans.XmlCursor;
36
import org.apache.xmlbeans.XmlCursor;
Lines 43-296 Link Here
43
/**
44
/**
44
 * Parent of XWPF headers and footers
45
 * Parent of XWPF headers and footers
45
 */
46
 */
46
public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBody{
47
public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBody {
47
	protected CTHdrFtr headerFooter;
48
    List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>(1);
48
	protected List<XWPFParagraph> paragraphs;
49
    List<XWPFTable> tables= new ArrayList<XWPFTable>(1);
49
	protected List<XWPFTable> tables;
50
    List<XWPFPictureData> pictures = new ArrayList<XWPFPictureData>();
50
	protected List<XWPFPictureData> pictures;
51
    List<IBodyElement> bodyElements = new ArrayList<IBodyElement>(1);
51
	protected XWPFDocument document;
52
52
	protected List<IBodyElement> bodyElements;
53
    CTHdrFtr headerFooter;
53
	
54
    XWPFDocument document;
54
	protected XWPFHeaderFooter(XWPFDocument doc, CTHdrFtr hdrFtr){
55
56
    XWPFHeaderFooter(XWPFDocument doc, CTHdrFtr hdrFtr){
55
        if (doc==null) {
57
        if (doc==null) {
56
            throw new NullPointerException();
58
            throw new NullPointerException();
57
        }
59
        }
58
60
59
        document = doc;
61
        document = doc;
60
		headerFooter = hdrFtr;
62
        headerFooter = hdrFtr;
61
		readHdrFtr();
63
        readHdrFtr();
62
	}
64
    }
63
65
64
    protected XWPFHeaderFooter() {
66
    protected XWPFHeaderFooter() {
65
        headerFooter = CTHdrFtr.Factory.newInstance();
67
        headerFooter = CTHdrFtr.Factory.newInstance();
66
        readHdrFtr();
68
        readHdrFtr();
67
    }
69
    }
68
70
69
70
    public XWPFHeaderFooter(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel) throws IOException {
71
    public XWPFHeaderFooter(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel) throws IOException {
71
		super(parent, part, rel);
72
        super(parent, part, rel);
72
		this.document = (XWPFDocument)getParent();
73
        this.document = (XWPFDocument)getParent();
73
74
74
        if (this.document==null) {
75
        if (this.document==null) {
75
            throw new NullPointerException();
76
            throw new NullPointerException();
76
        }
77
        }
78
    }
79
80
    @Override
81
    protected void onDocumentRead() throws IOException {
82
        for (POIXMLDocumentPart poixmlDocumentPart : getRelations()){
83
            if(poixmlDocumentPart instanceof XWPFPictureData){
84
                XWPFPictureData xwpfPicData = (XWPFPictureData) poixmlDocumentPart;
85
                pictures.add(xwpfPicData);
86
                document.registerPackagePictureData(xwpfPicData);
87
            }
88
        }
89
    }
77
90
78
        onDocumentRead();
79
	}
80
	
81
    @Internal
91
    @Internal
82
	public CTHdrFtr _getHdrFtr() {
92
    public CTHdrFtr _getHdrFtr() {
83
		return headerFooter;
93
        return headerFooter;
84
	}
94
    }
85
95
86
   public List<IBodyElement> getBodyElements(){
96
    public List<IBodyElement> getBodyElements(){
87
        return Collections.unmodifiableList(bodyElements);
97
        return Collections.unmodifiableList(bodyElements);
88
   }
98
    }
89
    
99
90
	/**
100
    /**
91
	 * Returns the paragraph(s) that holds
101
     * Returns the paragraph(s) that holds
92
	 *  the text of the header or footer.
102
     *  the text of the header or footer.
93
	 * Normally there is only the one paragraph, but
103
     * Normally there is only the one paragraph, but
94
	 *  there could be more in certain cases, or 
104
     *  there could be more in certain cases, or 
95
	 *  a table.
105
     *  a table.
96
	 */
106
     */
97
    public List<XWPFParagraph> getParagraphs() {
107
    public List<XWPFParagraph> getParagraphs() {
98
        return Collections.unmodifiableList(paragraphs);
108
        return Collections.unmodifiableList(paragraphs);
99
    }
109
    }
100
	
110
101
	
111
102
	/**
112
    /**
103
	 * Return the table(s) that holds the text
113
     * Return the table(s) that holds the text
104
	 *  of the header or footer, for complex cases
114
     *  of the header or footer, for complex cases
105
	 *  where a paragraph isn't used.
115
     *  where a paragraph isn't used.
106
	 * Normally there's just one paragraph, but some
116
     * Normally there's just one paragraph, but some
107
	 *  complex headers/footers have a table or two
117
     *  complex headers/footers have a table or two
108
	 *  in addition. 
118
     *  in addition. 
109
	 */
119
     */
110
 	public List<XWPFTable> getTables()throws ArrayIndexOutOfBoundsException {
120
    public List<XWPFTable> getTables()throws ArrayIndexOutOfBoundsException {
111
    	return Collections.unmodifiableList(tables);
121
        return Collections.unmodifiableList(tables);
122
    }
123
124
125
126
    /**
127
     * Returns the textual content of the header/footer,
128
     *  by flattening out the text of its paragraph(s)
129
     */
130
    public String getText() {
131
        StringBuffer t = new StringBuffer();
132
133
        for(int i=0; i<paragraphs.size(); i++) {
134
            if(! paragraphs.get(i).isEmpty()) {
135
                String text = paragraphs.get(i).getText();
136
                if(text != null && text.length() > 0) {
137
                    t.append(text);
138
                    t.append('\n');
139
                }
140
            }
141
        }
142
143
        List<XWPFTable> tables = getTables();
144
        for(int i=0; i<tables.size(); i++) {
145
            String text = tables.get(i).getText();
146
            if(text != null && text.length() > 0) {
147
                t.append(text);
148
                t.append('\n');
149
            }
150
        }
151
152
        return t.toString(); 
153
    }
154
155
    /**
156
     * set a new headerFooter
157
     */
158
    public void setHeaderFooter(CTHdrFtr headerFooter){
159
        this.headerFooter = headerFooter;
160
        readHdrFtr();
161
    }
162
163
    /**
164
     * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header
165
     * the method will return this table
166
     * if there is no corresponding {@link XWPFTable} the method will return null 
167
     * @param ctTable
168
     */
169
    public XWPFTable getTable(CTTbl ctTable){
170
        for (XWPFTable table : tables) {
171
            if(table==null)
172
                return null;
173
            if(table.getCTTbl().equals(ctTable))
174
                return table;	
175
        }
176
        return null;
112
    }
177
    }
113
 	
178
114
 	
179
    /**
115
	
180
     * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer
116
	/**
181
     * the method will return this paragraph
117
	 * Returns the textual content of the header/footer,
182
     * if there is no corresponding {@link XWPFParagraph} the method will return null 
118
	 *  by flattening out the text of its paragraph(s)
183
     * @param p is instance of CTP and is searching for an XWPFParagraph
119
	 */
184
     * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer
120
	public String getText() {
185
     * 		   XWPFParagraph with the correspondig CTP p
121
		StringBuffer t = new StringBuffer();
186
     */
122
		
187
    public XWPFParagraph getParagraph(CTP p){
123
		for(int i=0; i<paragraphs.size(); i++) {
188
        for (XWPFParagraph paragraph : paragraphs) {
124
			if(! paragraphs.get(i).isEmpty()) {
189
            if(paragraph.getCTP().equals(p))
125
				String text = paragraphs.get(i).getText();
190
                return paragraph;
126
				if(text != null && text.length() > 0) {
191
        }
127
					t.append(text);
192
        return null;
128
					t.append('\n');
129
				}
130
			}
131
		}
132
		
133
		List<XWPFTable> tables = getTables();
134
		for(int i=0; i<tables.size(); i++) {
135
			String text = tables.get(i).getText();
136
			if(text != null && text.length() > 0) {
137
				t.append(text);
138
				t.append('\n');
139
			}
140
		}
141
		
142
		return t.toString(); 
143
	}
144
	
145
	/**
146
	 * set a new headerFooter
147
	 */
148
	public void setHeaderFooter(CTHdrFtr headerFooter){
149
		this.headerFooter = headerFooter;
150
		readHdrFtr();
151
	}
152
	
153
	/**
154
	 * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header
155
	 * the method will return this table
156
	 * if there is no corresponding {@link XWPFTable} the method will return null 
157
	 * @param ctTable
158
	 */
159
	public XWPFTable getTable(CTTbl ctTable){
160
		for (XWPFTable table : tables) {
161
			if(table==null)
162
				return null;
163
			if(table.getCTTbl().equals(ctTable))
164
				return table;	
165
		}
166
		return null;
167
	}
168
	
169
	/**
170
	 * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer
171
	 * the method will return this paragraph
172
	 * if there is no corresponding {@link XWPFParagraph} the method will return null 
173
	 * @param p is instance of CTP and is searching for an XWPFParagraph
174
	 * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer
175
	 * 		   XWPFParagraph with the correspondig CTP p
176
	 */
177
	public XWPFParagraph getParagraph(CTP p){
178
		for (XWPFParagraph paragraph : paragraphs) {
179
			if(paragraph.getCTP().equals(p))
180
				return paragraph;
181
		}
182
		return null;
183
		
184
	}
185
	
186
	/**
187
	 * Returns the paragraph that holds
188
	 *  the text of the header or footer.
189
	 */
190
	public XWPFParagraph getParagraphArray(int pos) {
191
193
192
		return paragraphs.get(pos);
194
    }
193
	}
195
194
	
196
    /**
195
	/**
197
     * Returns the paragraph that holds
196
	 * get a List of all Paragraphs
198
     *  the text of the header or footer.
197
	 * @return a list of {@link XWPFParagraph} 
199
     */
198
	 */
200
    public XWPFParagraph getParagraphArray(int pos) {
199
	public List<XWPFParagraph> getListParagraph(){
201
200
		return paragraphs;
202
        return paragraphs.get(pos);
201
	}
203
    }
202
	
204
205
    /**
206
     * get a List of all Paragraphs
207
     * @return a list of {@link XWPFParagraph} 
208
     */
209
    public List<XWPFParagraph> getListParagraph(){
210
        return paragraphs;
211
    }
212
203
    public List<XWPFPictureData> getAllPictures() {
213
    public List<XWPFPictureData> getAllPictures() {
204
    	if(pictures == null){
214
        return Collections.unmodifiableList(pictures);
205
    		pictures = new ArrayList<XWPFPictureData>();
206
    		for (POIXMLDocumentPart poixmlDocumentPart : getRelations()){
207
    			if(poixmlDocumentPart instanceof XWPFPictureData){
208
    				pictures.add((XWPFPictureData)poixmlDocumentPart);
209
    			}
210
    		}
211
    	}
212
    return pictures;
213
    }
215
    }
214
    
216
215
    /**
217
    /**
216
     * get all Pictures in this package
218
     * get all Pictures in this package
217
     * @return all Pictures in this package
219
     * @return all Pictures in this package
218
     */
220
     */
219
    public List<XWPFPictureData> getAllPackagePictures(){
221
    public List<XWPFPictureData> getAllPackagePictures(){
220
    	List<XWPFPictureData> pkgpictures = new ArrayList<XWPFPictureData>();
222
        return document.getAllPackagePictures();
221
    	pkgpictures.addAll(getAllPictures());
223
222
    	for (POIXMLDocumentPart poixmlDocumentPart : getRelations()){
223
			if(poixmlDocumentPart instanceof XWPFHeaderFooter){
224
				pkgpictures.addAll(((XWPFHeaderFooter)poixmlDocumentPart).getAllPictures());
225
			}
226
		}
227
    	return pkgpictures;
228
    }
224
    }
229
   
225
230
     /**
226
    /**
231
     * Adds a picture to the document.
227
     * Adds a picture to the document.
232
     *
228
     *
233
     * @param is                The stream to read image from
229
     * @param is                The stream to read image from
234
     * @param format            The format of the picture.
230
     * @param format            The format of the picture.
235
     *
231
     *
236
     * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} .
232
     * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} .
233
     * @throws InvalidFormatException 
237
     */
234
     */
238
    public int addPicture(InputStream is, int format) throws IOException {
235
    public String addPictureData(byte[] pictureData,int format) throws InvalidFormatException
239
        int imageNumber = getNextPicNameNumber(format);
236
    {
240
        XWPFPictureData img = (XWPFPictureData)createRelationship(XWPFPictureData.RELATIONS[format], XWPFFactory.getInstance(), imageNumber, true);
237
        XWPFPictureData xwpfPicData = document.findPackagePictureData(pictureData, format);
241
        OutputStream out = img.getPackagePart().getOutputStream();
238
        POIXMLRelation relDesc = XWPFPictureData.RELATIONS[format];
242
        IOUtils.copy(is, out);
239
243
        out.close();
240
        if (xwpfPicData == null)
244
        pictures.add(img);
241
        {
245
        return getAllPictures().size()-1;
242
            /* Part doesn't exist, create a new one */
246
       
243
            int idx = document.getNextPicNameNumber(format);
244
            xwpfPicData = (XWPFPictureData) createRelationship(relDesc, XWPFFactory.getInstance(),idx);
245
            /* write bytes to new part */
246
            PackagePart picDataPart = xwpfPicData.getPackagePart();
247
            OutputStream out = null;
248
            try {
249
                out = picDataPart.getOutputStream();
250
                out.write(pictureData);
251
            } catch (IOException e) {
252
                throw new POIXMLException(e);
253
            } finally {
254
                try {
255
                    out.close();
256
                } catch (IOException e) {
257
                    // ignore
258
                }
259
            }
260
            
261
            document.registerPackagePictureData(xwpfPicData);
262
            pictures.add(xwpfPicData);
263
            return getRelationId(xwpfPicData);
264
        }
265
        else if (!getRelations().contains(xwpfPicData))
266
        {
267
            /*
268
             * Part already existed, but was not related so far. Create
269
             * relationship to the already existing part and update
270
             * POIXMLDocumentPart data.
271
             */
272
            PackagePart picDataPart = xwpfPicData.getPackagePart();
273
            // TODO add support for TargetMode.EXTERNAL relations.
274
            TargetMode targetMode = TargetMode.INTERNAL;
275
            PackagePartName partName = picDataPart.getPartName();
276
            String relation = relDesc.getRelation();
277
            PackageRelationship relShip = getPackagePart().addRelationship(partName,targetMode,relation);
278
            String id = relShip.getId();
279
            addRelation(id,xwpfPicData);
280
            pictures.add(xwpfPicData);
281
            return id;
282
        }
283
        else 
284
        {
285
            /* Part already existed, get relation id and return it */
286
            return getRelationId(xwpfPicData);
287
        }
247
    }
288
    }
248
    
289
249
    /**
290
    /**
250
     * Adds a picture to the document.
291
     * Adds a picture to the document.
251
     *
292
     *
252
     * @param pictureData       The picture bytes
293
     * @param is                The stream to read image from
253
     * @param format            The format of the picture.
294
     * @param format            The format of the picture.
254
     *
295
     *
255
     * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} .
296
     * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} .
256
     */
297
     * @throws InvalidFormatException 
257
    public int addPicture(byte[] pictureData, int format) {
298
     * @throws IOException 
258
        int imageNumber = getNextPicNameNumber(format);
259
        XWPFPictureData img = (XWPFPictureData)createRelationship(XWPFPictureData.RELATIONS[format], XWPFFactory.getInstance(), imageNumber, false);
260
        try {
261
            OutputStream out = img.getPackagePart().getOutputStream();
262
            out.write(pictureData);
263
            out.close();
264
        } catch (IOException e){
265
            throw new POIXMLException(e);
266
        }
267
        
268
        pictures.add(img);
269
        return getAllPictures().size()-1;
270
    }
271
    
272
    /**
273
     * get the next free ImageNumber
274
     * @param format
275
     * @return the next free ImageNumber
276
     */
299
     */
277
    public int getNextPicNameNumber(int format){
300
    public String addPictureData(InputStream is, int format) throws InvalidFormatException,IOException {
278
    	int img = getAllPackagePictures().size()+1;
301
        byte[] data = IOUtils.toByteArray(is);
279
   		String proposal = XWPFPictureData.RELATIONS[format].getFileName(img);
302
        return addPictureData(data,format);
280
   		try {
281
			PackagePartName createPartName = PackagingURIHelper.createPartName(proposal);
282
			while (this.getPackagePart().getPackage().getPart(createPartName)!= null){
283
				img++;
284
				proposal = XWPFPictureData.RELATIONS[format].getFileName(img);
285
				createPartName = PackagingURIHelper.createPartName(proposal);
286
			}
287
		} catch (InvalidFormatException e) {
288
			// TODO Auto-generated catch block
289
			e.printStackTrace();
290
		}
291
    	return img;
292
    }
303
    }
293
	
304
294
    /**
305
    /**
295
     * returns the PictureData by blipID
306
     * returns the PictureData by blipID
296
     * @param blipID
307
     * @param blipID
Lines 298-543 Link Here
298
     * @throws Exception 
309
     * @throws Exception 
299
     */
310
     */
300
    public XWPFPictureData getPictureDataByID(String blipID) {
311
    public XWPFPictureData getPictureDataByID(String blipID) {
301
    	for(POIXMLDocumentPart part: getRelations()){
312
        POIXMLDocumentPart relatedPart = getRelationById(blipID);
302
    	  if(part.getPackageRelationship() != null){
313
        if (relatedPart != null && relatedPart instanceof XWPFPictureData) {
303
    		  if(part.getPackageRelationship().getId() != null){
314
            return (XWPFPictureData) relatedPart;
304
    			  if(part.getPackageRelationship().getId().equals(blipID)){
315
        }
305
    				  return (XWPFPictureData)part;
316
        return null;	    	
306
    			  }
307
    		  }
308
    	  	}
309
    	}
310
		return null;	    	
311
    }
317
    }
312
    
318
313
    /**
319
    /**
314
     * Add the picture to  drawing relations
320
     * add a new paragraph at position of the cursor
315
     *
321
     * @param cursor
316
     * @param pictureData the picture bytes
322
     * @return the inserted paragraph
317
     * @param format      the picture format
323
     */
324
    public XWPFParagraph insertNewParagraph(XmlCursor cursor){
325
        if(isCursorInHdrF(cursor)){
326
            String uri = CTP.type.getName().getNamespaceURI();
327
            String localPart = "p";
328
            cursor.beginElement(localPart,uri);
329
            cursor.toParent();
330
            CTP p = (CTP)cursor.getObject();
331
            XWPFParagraph newP = new XWPFParagraph(p, this);
332
            XmlObject o = null;
333
            while(!(o instanceof CTP)&&(cursor.toPrevSibling())){
334
                o = cursor.getObject();
335
            }
336
            if((!(o instanceof CTP)) || (CTP)o == p){
337
                paragraphs.add(0, newP);
338
            }
339
            else{
340
                int pos = paragraphs.indexOf(getParagraph((CTP)o))+1;
341
                paragraphs.add(pos,newP);
342
            }
343
            int i=0;
344
            cursor.toCursor(p.newCursor());
345
            while(cursor.toPrevSibling()){
346
                o =cursor.getObject();
347
                if(o instanceof CTP || o instanceof CTTbl)
348
                    i++;
349
            }
350
            bodyElements.add(i, newP);
351
            cursor.toCursor(p.newCursor());
352
            cursor.toEndToken();
353
            return newP;
354
        }
355
        return null;
356
    }
357
358
359
    /**
360
     * 
361
     * @param cursor
362
     * @return the inserted table
363
     */
364
    public XWPFTable insertNewTbl(XmlCursor cursor) {
365
        if(isCursorInHdrF(cursor)){
366
            String uri = CTTbl.type.getName().getNamespaceURI();
367
            String localPart = "tbl";
368
            cursor.beginElement(localPart,uri);
369
            cursor.toParent();
370
            CTTbl t = (CTTbl)cursor.getObject();
371
            XWPFTable newT = new XWPFTable(t, this);
372
            cursor.removeXmlContents();
373
            XmlObject o = null;
374
            while(!(o instanceof CTTbl)&&(cursor.toPrevSibling())){
375
                o = cursor.getObject();
376
            }
377
            if(!(o instanceof CTTbl)){
378
                tables.add(0, newT);
379
            }
380
            else{
381
                int pos = tables.indexOf(getTable((CTTbl)o))+1;
382
                tables.add(pos,newT);
383
            }
384
            int i=0;
385
            cursor = t.newCursor();
386
            while(cursor.toPrevSibling()){
387
                o =cursor.getObject();
388
                if(o instanceof CTP || o instanceof CTTbl)
389
                    i++;
390
            }
391
            bodyElements.add(i, newT);
392
            cursor = t.newCursor();
393
            cursor.toEndToken();
394
            return newT;
395
        }
396
        return null;
397
    }
398
399
    /**
400
     * verifies that cursor is on the right position
401
     * @param cursor
318
     */
402
     */
319
    public PackageRelationship addPictureReference(byte[] pictureData, int format){
403
    private boolean isCursorInHdrF(XmlCursor cursor) {
320
    	int imageNumber = getNextPicNameNumber(format);
404
        XmlCursor verify = cursor.newCursor();
321
        XWPFPictureData img = (XWPFPictureData)createRelationship(XWPFPictureData.RELATIONS[format], XWPFFactory.getInstance(), imageNumber, false);
405
        verify.toParent();
322
        PackageRelationship rel = null;
406
        if(verify.getObject() == this.headerFooter){
323
        try {
407
            return true;
324
            OutputStream out = img.getPackagePart().getOutputStream();
408
        }
325
            out.write(pictureData);
409
        return false;
326
             out.close();
410
    }
327
             rel = img.getPackageRelationship();
411
328
             pictures.add(img);
412
329
         } catch (IOException e){
413
    public POIXMLDocumentPart getOwner(){
330
             throw new POIXMLException(e);
414
        return this;
331
         }
332
          return rel;
333
    }
415
    }
334
          
416
335
      /**
417
    /**
336
       * Add the picture to  drawing relations
418
     * Returns the table at position pos
337
       *
419
     * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int)
338
       * @param is the stream to read picture data from
420
     */
339
       */
421
    public XWPFTable getTableArray(int pos) {
340
      public PackageRelationship addPictureReference(InputStream is, int format){
341
    	  
342
    	  PackageRelationship rel = null;
343
          try {
344
        	  int imageNumber = getNextPicNameNumber(format);
345
        	  XWPFPictureData img = (XWPFPictureData)createRelationship(XWPFPictureData.RELATIONS[format], XWPFFactory.getInstance(), imageNumber, false);
346
        	  OutputStream out = img.getPackagePart().getOutputStream();
347
        	  IOUtils.copy(is, out);
348
        	  out.close();
349
        	  rel = img.getPackageRelationship();
350
        	  pictures.add(img);
351
		} catch (IOException e) {
352
			// TODO Auto-generated catch block
353
			e.printStackTrace();
354
		}
355
        return rel;      
356
      }
357
422
358
      /**
423
        if(pos > 0 && pos < tables.size()){
359
       * add a new paragraph at position of the cursor
424
            return tables.get(pos);
360
       * @param cursor
425
        }
361
       * @return the inserted paragraph
426
        return null;
362
       */
427
    }
363
      public XWPFParagraph insertNewParagraph(XmlCursor cursor){
364
      	if(isCursorInHdrF(cursor)){
365
      		String uri = CTP.type.getName().getNamespaceURI();
366
      		String localPart = "p";
367
      		cursor.beginElement(localPart,uri);
368
      		cursor.toParent();
369
      		CTP p = (CTP)cursor.getObject();
370
      		XWPFParagraph newP = new XWPFParagraph(p, this);
371
      		XmlObject o = null;
372
  	    	while(!(o instanceof CTP)&&(cursor.toPrevSibling())){
373
  	    		o = cursor.getObject();
374
  	    	}
375
  	    	if((!(o instanceof CTP)) || (CTP)o == p){
376
  	    		paragraphs.add(0, newP);
377
  	    	}
378
  	    	else{
379
  	    		int pos = paragraphs.indexOf(getParagraph((CTP)o))+1;
380
  	    		paragraphs.add(pos,newP);
381
  	    	}
382
  	    	int i=0;
383
  	    	cursor.toCursor(p.newCursor());
384
  			while(cursor.toPrevSibling()){
385
  				o =cursor.getObject();
386
  				if(o instanceof CTP || o instanceof CTTbl)
387
  					i++;
388
  			}
389
  			bodyElements.add(i, newP);
390
  	    	cursor.toCursor(p.newCursor());
391
  	    	cursor.toEndToken();
392
  	    	return newP;
393
      	}
394
      	return null;
395
      }
396
      
397
428
398
  	/**
429
    /**
399
       * 
430
     * inserts an existing XWPFTable to the arrays bodyElements and tables
400
       * @param cursor
431
     * @param pos
401
       * @return the inserted table
432
     * @param table
402
       */
433
     */
403
  	public XWPFTable insertNewTbl(XmlCursor cursor) {
434
    public void insertTable(int pos, XWPFTable table) {
404
  		if(isCursorInHdrF(cursor)){
435
        bodyElements.add(pos, table);
405
  			String uri = CTTbl.type.getName().getNamespaceURI();
436
        int i;
406
  			String localPart = "tbl";
437
        for (i = 0; i < headerFooter.getTblList().size(); i++) {
407
      		cursor.beginElement(localPart,uri);
438
            CTTbl tbl = headerFooter.getTblArray(i);
408
  			cursor.toParent();
439
            if(tbl == table.getCTTbl()){
409
  			CTTbl t = (CTTbl)cursor.getObject();
440
                break;
410
  			XWPFTable newT = new XWPFTable(t, this);
441
            }
411
  			cursor.removeXmlContents();
442
        }
412
  			XmlObject o = null;
443
        tables.add(i, table);
413
  			while(!(o instanceof CTTbl)&&(cursor.toPrevSibling())){
414
  				o = cursor.getObject();
415
  			}
416
  			if(!(o instanceof CTTbl)){
417
  				tables.add(0, newT);
418
  			}
419
  			else{
420
  				int pos = tables.indexOf(getTable((CTTbl)o))+1;
421
  				tables.add(pos,newT);
422
  			}
423
  			int i=0;
424
  			cursor = t.newCursor();
425
  			while(cursor.toPrevSibling()){
426
  				o =cursor.getObject();
427
  				if(o instanceof CTP || o instanceof CTTbl)
428
  					i++;
429
  			}
430
  			bodyElements.add(i, newT);
431
  			cursor = t.newCursor();
432
  			cursor.toEndToken();
433
  			return newT;
434
  		}
435
  		return null;
436
  	}
437
  	
438
  	/**
439
  	 * verifies that cursor is on the right position
440
  	 * @param cursor
441
  	 */
442
  	private boolean isCursorInHdrF(XmlCursor cursor) {
443
  		XmlCursor verify = cursor.newCursor();
444
  		verify.toParent();
445
  		if(verify.getObject() == this.headerFooter){
446
  			return true;
447
  		}
448
  		return false;
449
  	}
450
444
451
  	
445
    }
452
  	public POIXMLDocumentPart getOwner(){
446
453
  		return this;
447
    public void readHdrFtr(){
454
  	}
448
        bodyElements = new ArrayList<IBodyElement>();
455
  	
456
	/**
457
	 * Returns the table at position pos
458
	 * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int)
459
	 */
460
	public XWPFTable getTableArray(int pos) {
461
	
462
		if(pos > 0 && pos < tables.size()){
463
			return tables.get(pos);
464
		}
465
		return null;
466
	}
467
	
468
	/**
469
	 * inserts an existing XWPFTable to the arrays bodyElements and tables
470
	 * @param pos
471
	 * @param table
472
	 */
473
	public void insertTable(int pos, XWPFTable table) {
474
		bodyElements.add(pos, table);
475
		int i;
476
    	for (i = 0; i < headerFooter.getTblList().size(); i++) {
477
			CTTbl tbl = headerFooter.getTblArray(i);
478
			if(tbl == table.getCTTbl()){
479
				break;
480
			}
481
		}
482
		tables.add(i, table);
483
		
484
	}
485
	
486
	public void readHdrFtr(){
487
		bodyElements = new ArrayList<IBodyElement>();
488
        paragraphs = new ArrayList<XWPFParagraph>();
449
        paragraphs = new ArrayList<XWPFParagraph>();
489
        tables= new ArrayList<XWPFTable>();
450
        tables= new ArrayList<XWPFTable>();
490
        // parse the document with cursor and add
451
        // parse the document with cursor and add
491
        // the XmlObject to its lists
452
        // the XmlObject to its lists
492
		XmlCursor cursor = headerFooter.newCursor();
453
        XmlCursor cursor = headerFooter.newCursor();
493
        cursor.selectPath("./*");
454
        cursor.selectPath("./*");
494
        while (cursor.toNextSelection()) {
455
        while (cursor.toNextSelection()) {
495
            XmlObject o = cursor.getObject();
456
            XmlObject o = cursor.getObject();
496
            if (o instanceof CTP) {
457
            if (o instanceof CTP) {
497
            	XWPFParagraph p = new XWPFParagraph((CTP)o, this);
458
                XWPFParagraph p = new XWPFParagraph((CTP)o, this);
498
            	paragraphs.add(p);
459
                paragraphs.add(p);
499
            	bodyElements.add(p);
460
                bodyElements.add(p);
500
            }
461
            }
501
            if (o instanceof CTTbl) {
462
            if (o instanceof CTTbl) {
502
            	XWPFTable t = new XWPFTable((CTTbl)o, this);
463
                XWPFTable t = new XWPFTable((CTTbl)o, this);
503
            	tables.add(t);
464
                tables.add(t);
504
            	bodyElements.add(t);
465
                bodyElements.add(t);
505
            }
466
            }
506
        }
467
        }
507
        cursor.dispose();
468
        cursor.dispose();
508
        getAllPictures();
469
    }
509
	}
470
510
	
471
    /**
511
	/**
472
     * get the TableCell which belongs to the TableCell
512
	 * get the TableCell which belongs to the TableCell
473
     * @param cell
513
	 * @param cell
474
     */
514
	 */
475
    public XWPFTableCell getTableCell(CTTc cell) {
515
	public XWPFTableCell getTableCell(CTTc cell) {
476
        XmlCursor cursor = cell.newCursor();
516
		XmlCursor cursor = cell.newCursor();
477
        cursor.toParent();
517
		cursor.toParent();
478
        XmlObject o = cursor.getObject();
518
		XmlObject o = cursor.getObject();
479
        if(!(o instanceof CTRow)){
519
		if(!(o instanceof CTRow)){
480
            return null;
520
			return null;
481
        }
521
		}
482
        CTRow row = (CTRow)o;
522
		CTRow row = (CTRow)o;
483
        cursor.toParent();
523
		cursor.toParent();
484
        o = cursor.getObject();
524
		o = cursor.getObject();
525
        cursor.dispose();
485
        cursor.dispose();
526
		if(! (o instanceof CTTbl)){
486
        if(! (o instanceof CTTbl)){
527
			return null;
487
            return null;
528
		}
488
        }
529
		CTTbl tbl = (CTTbl) o;
489
        CTTbl tbl = (CTTbl) o;
530
		XWPFTable table = getTable(tbl);
490
        XWPFTable table = getTable(tbl);
531
		if(table == null){
491
        if(table == null){
532
			return null;
492
            return null;
533
		}
493
        }
534
		XWPFTableRow tableRow = table.getRow(row);
494
        XWPFTableRow tableRow = table.getRow(row);
535
		if(row == null){
495
        if(row == null){
536
			return null;
496
            return null;
537
		}
497
        }
538
		return tableRow.getTableCell(cell);
498
        return tableRow.getTableCell(cell);
539
	}
499
    }
540
  	
500
541
    public XWPFDocument getXWPFDocument() {
501
    public XWPFDocument getXWPFDocument() {
542
        if (document!=null) {
502
        if (document!=null) {
543
            return document;
503
            return document;
Lines 545-548 Link Here
545
            return (XWPFDocument)getParent();
505
            return (XWPFDocument)getParent();
546
        }
506
        }
547
    }
507
    }
508
509
    /**
510
     * returns the Part, to which the body belongs, which you need for adding relationship to other parts
511
     * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
512
     */
513
    public POIXMLDocumentPart getPart() {
514
        return this;
515
    }
548
}//end class
516
}//end class

Return to bug 51265