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

(-)src/ooxml/java/org/apache/poi/POIXMLDocument.java (+89 lines)
Lines 22-27 Link Here
22
import java.io.PushbackInputStream;
22
import java.io.PushbackInputStream;
23
import java.util.HashMap;
23
import java.util.HashMap;
24
import java.util.HashSet;
24
import java.util.HashSet;
25
import java.util.Iterator;
25
import java.util.List;
26
import java.util.List;
26
import java.util.Map;
27
import java.util.Map;
27
import java.util.Set;
28
import java.util.Set;
Lines 34-39 Link Here
34
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
35
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
35
import org.apache.poi.poifs.common.POIFSConstants;
36
import org.apache.poi.poifs.common.POIFSConstants;
36
import org.apache.poi.util.IOUtils;
37
import org.apache.poi.util.IOUtils;
38
import org.apache.poi.util.POILogFactory;
39
import org.apache.poi.util.POILogger;
40
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
37
41
38
public abstract class POIXMLDocument extends POIXMLDocumentPart{
42
public abstract class POIXMLDocument extends POIXMLDocumentPart{
39
    public static final String DOCUMENT_CREATOR = "Apache POI";
43
    public static final String DOCUMENT_CREATOR = "Apache POI";
Lines 51-56 Link Here
51
     * The properties of the OPC package, opened as needed
55
     * The properties of the OPC package, opened as needed
52
     */
56
     */
53
    private POIXMLProperties properties;
57
    private POIXMLProperties properties;
58
    
59
    /** For our own logging use */
60
    private final static POILogger LOGGER = POILogFactory.getLogger(POIXMLDocument.class);
54
61
55
    protected POIXMLDocument(OPCPackage pkg) {
62
    protected POIXMLDocument(OPCPackage pkg) {
56
        super(pkg);
63
        super(pkg);
Lines 178-181 Link Here
178
185
179
        getPackage().save(stream);
186
        getPackage().save(stream);
180
    }
187
    }
188
    
189
190
     /**
191
     * Update the document custom properties. If a property already exists, the value
192
     * is replaced. If the property is new then it will be added.
193
     *
194
     * @param propsMap - the properties in the form of an HashMap(propertyName,value)
195
     *
196
     * @exception IOException if anything can't be written.
197
     */
198
	public void populateCustomProperties(HashMap<String, String> propsMap) {
199
200
		POIXMLProperties summaryInfo = null;
201
                Boolean foundProperty = false;
202
                Boolean isFirstIteration = true;
203
                Boolean initialPropsIsEmpty = false;
204
		
205
		try {
206
207
                        this.getProperties();
208
			summaryInfo = properties;
209
210
			List<CTProperty> propList = summaryInfo.getCustomProperties()
211
					.getUnderlyingProperties().getPropertyList();
212
213
			Iterator<String> iterator = propsMap.keySet().iterator();
214
			int i = 1;
215
			int delta = 0;
216
			while (iterator.hasNext()) {
217
				String key = iterator.next().toString();
218
				String value = propsMap.get(key).toString();
219
                                                                
220
				LOGGER.log(POILogger.INFO, "--> Processing property key {0}, with value {1}", new Object[]{key, value});
221
222
				foundProperty = false;
223
224
				Iterator<CTProperty> propIter = propList.iterator();
225
226
				if (propList.isEmpty()
227
						&& isFirstIteration.booleanValue() == Boolean.TRUE) {
228
					initialPropsIsEmpty = Boolean.TRUE;
229
					isFirstIteration = Boolean.FALSE;
230
				} else {
231
					delta = delta + propList.size();
232
				}
233
234
				if (initialPropsIsEmpty.booleanValue() == Boolean.FALSE) {
235
					while (propIter.hasNext()) {
236
						CTProperty property = propIter.next();
237
						if (property.getName().equalsIgnoreCase(key)) {
238
							property.setLpwstr(value);
239
							LOGGER.log(POILogger.INFO, "--> Replaced property name {0}, with value {1}", new Object[]{property.getName(), property.getLpwstr()});
240
241
							foundProperty = true;
242
						}
243
					}
244
				}
245
246
				if (!foundProperty) {
247
248
					CTProperty prp = summaryInfo.getCustomProperties()
249
							.getUnderlyingProperties().insertNewProperty(i);
250
					prp.setFmtid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
251
					prp.setPid(i + delta + 1);
252
					prp.setName(key);
253
					prp.setLpwstr(value);
254
255
					i++;
256
257
					LOGGER.log(POILogger.INFO, "--> Added property key {0}, with value {1}", new Object[]{key, value});
258
259
				}
260
261
			}
262
263
264
		} catch (Exception e) {
265
                    LOGGER.log(POILogger.ERROR ,e.toString());
266
		}
267
                
268
	}
269
 
181
}
270
}
(-)src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java (+166 lines)
Lines 49-60 Link Here
49
import org.apache.poi.util.IOUtils;
49
import org.apache.poi.util.IOUtils;
50
import org.apache.poi.util.IdentifierManager;
50
import org.apache.poi.util.IdentifierManager;
51
import org.apache.poi.util.Internal;
51
import org.apache.poi.util.Internal;
52
import org.apache.poi.util.POILogFactory;
53
import org.apache.poi.util.POILogger;
52
import org.apache.poi.util.PackageHelper;
54
import org.apache.poi.util.PackageHelper;
53
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
55
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
54
import org.apache.xmlbeans.XmlCursor;
56
import org.apache.xmlbeans.XmlCursor;
55
import org.apache.xmlbeans.XmlException;
57
import org.apache.xmlbeans.XmlException;
56
import org.apache.xmlbeans.XmlObject;
58
import org.apache.xmlbeans.XmlObject;
57
import org.apache.xmlbeans.XmlOptions;
59
import org.apache.xmlbeans.XmlOptions;
60
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
58
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment;
61
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment;
59
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
62
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
60
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
63
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
Lines 85-90 Link Here
85
 */
88
 */
86
public class XWPFDocument extends POIXMLDocument implements Document, IBody {
89
public class XWPFDocument extends POIXMLDocument implements Document, IBody {
87
90
91
        /** For our own logging use */
92
    private final static POILogger LOGGER = POILogFactory.getLogger(XWPFDocument.class);
93
    private final static String EMPTYSPACE = " ";
94
    
88
    private CTDocument1 ctDocument;
95
    private CTDocument1 ctDocument;
89
    private XWPFSettings settings;
96
    private XWPFSettings settings;
90
    /**
97
    /**
Lines 1307-1312 Link Here
1307
		return tableRow.getTableCell(cell);
1314
		return tableRow.getTableCell(cell);
1308
	}
1315
	}
1309
1316
1317
        
1318
1319
        /**
1320
        * Propagate the document custom properties. If the document (Word)
1321
        * has custom properties defined, those will be matched across the text
1322
        * and if there are differences those will be updated.
1323
        *
1324
        * @exception IOException if anything can't be written.
1325
        */
1326
	public void propagateXwpfCustomProperties() {
1327
1328
		LOGGER.log(POILogger.INFO,"--> method propagateDocxProperties started!");
1329
1330
		
1331
		POIXMLProperties summaryInfo = null;
1332
1333
		Boolean go4NextWt = false;
1334
1335
		Boolean processed = false;
1336
1337
		Boolean catchNextWt = false;
1338
1339
1340
		ArrayList<String> toBeprocessedItems = new ArrayList<String>();
1341
		HashMap<String, String> hashmp = new HashMap<String, String>();
1342
		Integer i = 0, j = 0;
1343
		Integer selectedItem = 0;
1344
1345
                summaryInfo = this.getProperties();
1346
                
1347
		List<CTProperty> propList = summaryInfo.getCustomProperties()
1348
				.getUnderlyingProperties().getPropertyList();
1349
1350
		Iterator<CTProperty> propsIterator = propList.iterator();
1351
1352
		while (propsIterator.hasNext()) {
1353
			CTProperty prop = propsIterator.next();
1354
			LOGGER.log(POILogger.INFO, "--> Grouping property name {0} with value= {1}", new Object[]{prop.getName(), prop.getLpwstr()});
1355
			toBeprocessedItems.add(prop.getName());
1356
			hashmp.put(prop.getName(), prop.getLpwstr());
1357
		}
1358
1359
		List<XWPFParagraph> paragraphList = this.getParagraphs();
1360
		Iterator<XWPFParagraph> paragraphIterator = paragraphList.iterator();
1361
1362
		// Iterate over each paragraph:
1363
1364
		processed = false;
1365
		paragraphIterator = paragraphList.iterator();
1366
1367
		while (paragraphIterator.hasNext() && !processed) {
1368
1369
			XWPFParagraph element = paragraphIterator.next();
1370
1371
			LOGGER.log(POILogger.INFO, "--> Processing paragraph: {0}", element.getParagraphText());
1372
			CTP ctp = element.getCTP();
1373
1374
			XmlObject o;
1375
1376
			XmlCursor c = ctp.newCursor();
1377
1378
			for (c.toFirstContentToken(); c.hasNextToken(); c.toNextToken()) {
1379
1380
				o = c.getObject();
1381
1382
				/*
1383
				 * Here we look for Customized properties that are
1384
				 * defined/declared in the XML Text areas. E.g. <w:instrText
1385
				 * xml:space="preserve">DOCPROPERTY dummyProperty \*
1386
				 * MERGEFORMAT</w:instrText>
1387
				 */
1388
				if (c.isText() && c.getTextValue().contains("DOCPROPERTY")) {
1389
1390
					for (i = 0; i < toBeprocessedItems.size(); i++) {
1391
						if (c.getTextValue() != null
1392
								&& c.getTextValue().contains(
1393
										EMPTYSPACE + toBeprocessedItems.get(i)
1394
												+ EMPTYSPACE)) {
1395
1396
							selectedItem = i;
1397
1398
							LOGGER.log(POILogger.INFO,"-->FOUND TEXT PROPERTY DEFINITION VALUE --> "
1399
									+ " with i = {0} and text : {1}", new Object[]{i, c.getTextValue()});
1400
						}
1401
					}
1402
1403
					String tempText = c.getTextValue();
1404
					int len1 = tempText.length();
1405
					int len2 = tempText.lastIndexOf("MERGEFORMAT")
1406
							+ "MERGEFORMAT".length() + 1;
1407
					if (len1 == len2) {
1408
						catchNextWt = true;
1409
						tempText = tempText.substring(0, len2);
1410
					} else {
1411
						catchNextWt = false;
1412
					}
1413
1414
				}
1415
				if (o != null) {
1416
					String tagName1 = o.getDomNode().getNodeName();
1417
1418
					if (catchNextWt) {
1419
						if ("w:t".equals(tagName1)) {
1420
							catchNextWt = false;
1421
							c.getTextValue();
1422
							c.setTextValue(hashmp.get(toBeprocessedItems
1423
									.get(selectedItem)));
1424
1425
							LOGGER.log(POILogger.INFO, "--> CHANGED value--> {0}", c.getTextValue());
1426
						}
1427
					}
1428
1429
				}
1430
1431
				o = c.getObject();
1432
1433
				/*
1434
				 * Here we look for Customized properties that are
1435
				 * defined/declared in the XML Tag Value areas. E.g.
1436
				 * <w:fldSimple w:instr=" DOCPROPERTY dummyProperty \*
1437
				 * MERGEFORMAT ">
1438
				 */
1439
				if (o != null && o.getDomNode() != null) {
1440
1441
					String tagName = o.getDomNode().getNodeName();
1442
					String tagValue = o.getDomNode().getNodeValue();
1443
1444
					for (j = 0; j < toBeprocessedItems.size(); j++) {
1445
						if (tagValue != null
1446
								&& tagValue.contains("DOCPROPERTY")
1447
								&& tagValue.contains(EMPTYSPACE
1448
										+ toBeprocessedItems.get(j)
1449
										+ EMPTYSPACE)) {
1450
							go4NextWt = true;
1451
							selectedItem = j;
1452
1453
							LOGGER.log(POILogger.INFO,"--> FOUND TAG PROPERTY DEFINITION VALUE --> " + " {0}", tagValue);
1454
1455
						}
1456
					}
1457
1458
					if (tagName.contains("w:t")
1459
							&& go4NextWt.booleanValue() == true) {
1460
1461
						c.setTextValue(hashmp.get(toBeprocessedItems
1462
								.get(selectedItem)));
1463
						LOGGER.log(POILogger.INFO, "--> CHANGED value--> {0}", c.getTextValue());
1464
1465
						go4NextWt = false;
1466
					}
1467
1468
					processed = true;
1469
				}
1470
			}
1471
1472
		}
1473
1474
	}
1475
        
1310
    public XWPFDocument getXWPFDocument() {
1476
    public XWPFDocument getXWPFDocument() {
1311
        return this;
1477
        return this;
1312
    }
1478
    }
1313
  + true
1479
  + true
(-)src/testcases/org/apache/poi/properties/OfficePropertiesTest.java (+107 lines)
Line 0 Link Here
1
package org.apache.poi.properties;
2
3
import java.io.File;
4
import java.io.FileInputStream;
5
import java.io.FileOutputStream;
6
import java.io.IOException;
7
import java.util.HashMap;
8
9
10
import org.apache.poi.POIDataSamples;
11
import org.apache.poi.util.POILogFactory;
12
import org.apache.poi.util.POILogger;
13
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
14
import org.apache.poi.xwpf.usermodel.XWPFDocument;
15
import org.junit.BeforeClass;
16
import org.junit.Test;
17
18
19
public class OfficePropertiesTest {
20
21
	static OfficePropertiesTest instance = new OfficePropertiesTest();
22
23
        /** For our own logging use */
24
        private final static POILogger LOGGER = POILogFactory.getLogger(OfficePropertiesTest.class);
25
        
26
        
27
	@BeforeClass
28
	public static void init() throws IOException, ClassNotFoundException {
29
	
30
	}
31
32
	@Test
33
	public void executeTestStrategy() throws Exception {
34
35
		
36
		HashMap<String, String> myTestMap = new HashMap<String, String>();
37
		myTestMap.put("xpto", "New_XPTO");
38
		myTestMap.put("prop1", "New_prop1");
39
		myTestMap.put("prop2", "New_prop2");
40
		myTestMap.put("aaaaaaa", "Nova_aaaaaaa");
41
                FileInputStream fIsDocx = null;
42
                FileInputStream fIsXlsx = null;
43
                FileOutputStream fIsDocxOutput = null;
44
                FileOutputStream fIsXlsxOutput = null;
45
                XSSFWorkbook workbook = null;
46
                
47
                XWPFDocument document = null;
48
49
		System.setProperty("POI.testdata.path","D://Projects//ApachePOI_WriteAccess//trunk//test-data//");
50
                
51
                               
52
                File fl = POIDataSamples.getDocumentInstance().getFile("FldComplex.docx");
53
                
54
                File outputFileDocx = new File("D:/Temp/temp.docx");
55
                
56
                File outputFileXlsx = new File("D:/Temp/temp.xlsx");
57
                                    
58
                
59
                try {
60
                    fIsDocx = new FileInputStream(fl);                    
61
		} catch (IOException e) {
62
			LOGGER.log(POILogger.WARN,"-> IOException! Check file system permissions or Input file does not exist.");
63
		}
64
                
65
                
66
                try {
67
                    fIsDocxOutput = new FileOutputStream(outputFileDocx);
68
		} catch (IOException e) {
69
			LOGGER.log(POILogger.WARN,"-> IOException! Check file system permissions or Output file does not exist.");
70
		}                
71
                
72
                try {
73
			document = new XWPFDocument(fIsDocx);
74
                        document.populateCustomProperties(myTestMap);
75
                        document.propagateXwpfCustomProperties();
76
                        document.write(fIsDocxOutput);
77
		} catch (IOException e) {
78
			LOGGER.log(POILogger.WARN,"-> IOException! ");
79
		} 
80
                
81
                fl = POIDataSamples.getSpreadSheetInstance().getFile("FldSimple.xlsx");
82
                
83
                
84
                try {
85
                    fIsXlsx = new FileInputStream(fl);                    
86
		} catch (IOException e) {
87
			LOGGER.log(POILogger.WARN,"-> IOException! Check file system permissions or Input file does not exist.");
88
		}
89
                
90
                try {
91
                fIsXlsxOutput = new FileOutputStream(outputFileXlsx);
92
		} catch (IOException e) {
93
			LOGGER.log(POILogger.WARN,"-> IOException! Check file system permissions or Output file does not exist.");
94
		}                    
95
                
96
                try {
97
			workbook = new XSSFWorkbook(fIsXlsx);                        
98
                        workbook.populateCustomProperties(myTestMap); 
99
                        workbook.write(fIsXlsxOutput);
100
		} catch (IOException e) {
101
			LOGGER.log(POILogger.WARN,"-> IOException! ");
102
		} 
103
                
104
                
105
	}
106
107
}

Return to bug 51971