From 501c3b258aae05190a81467bc19a00ba36bca654 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Thu, 19 Jun 2008 11:47:48 +0000 Subject: [PATCH] Improved HWPF Range.replaceText, from N. Hira in bug #45001 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@669456 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 1 + src/documentation/content/xdocs/status.xml | 1 + .../org/apache/poi/hwpf/usermodel/Range.java | 32 ++--- .../poi/hwpf/data/testRangeReplacement.doc | Bin 0 -> 104448 bytes .../hwpf/usermodel/TestRangeReplacement.java | 119 ++++++++++++++++++ 5 files changed, 138 insertions(+), 15 deletions(-) create mode 100644 src/scratchpad/testcases/org/apache/poi/hwpf/data/testRangeReplacement.doc create mode 100644 src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 94db4f264..169eb16fc 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + 45001 - Improved HWPF Range.replaceText() 44692 - Fixed HSSFPicture.resize() to properly resize pictures if the underlying columns/rows have modified size Support custom image renderers in HSLF Correctly increment the reference count of a blip when a picture is inserted diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 033491645..47f042d43 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 45001 - Improved HWPF Range.replaceText() 44692 - Fixed HSSFPicture.resize() to properly resize pictures if the underlying columns/rows have modified size Support custom image renderers in HSLF Correctly increment the reference count of a blip when a picture is inserted diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java index 6324cd86a..80e9b7526 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/Range.java @@ -635,27 +635,24 @@ public class Range /** * Replace (one instance of) a piece of text with another... * - * @param pPlaceHolder The text to be replaced (e.g., "${company}") - * @param pValue The replacement text (e.g., "Cognocys, Inc.") - * @param pDocument The HWPFDocument in which the placeholder was found - * @param pStartOffset The offset or index where the CharacterRun begins - * @param pPlaceHolderIndex The offset or index of the placeholder, - * relative to the CharacterRun where - * pPlaceHolder was found + * @param pPlaceHolder The text to be replaced (e.g., "${organization}") + * @param pValue The replacement text (e.g., "Apache Software Foundation") + * @param pOffset The offset or index where the text to be replaced begins + * (relative to/within this Range) */ - protected void replaceText(String pPlaceHolder, String pValue, - int pStartOffset, int pPlaceHolderIndex, HWPFDocument pDocument) { - int absPlaceHolderIndex = pStartOffset + pPlaceHolderIndex; + public void replaceText(String pPlaceHolder, String pValue, int pOffset) + { + int absPlaceHolderIndex = getStartOffset() + pOffset; Range subRange = new Range( absPlaceHolderIndex, - (absPlaceHolderIndex + pPlaceHolder.length()), pDocument + (absPlaceHolderIndex + pPlaceHolder.length()), getDocument() ); if (subRange.usesUnicode()) { - absPlaceHolderIndex = pStartOffset + (pPlaceHolderIndex * 2); + absPlaceHolderIndex = getStartOffset() + (pOffset * 2); subRange = new Range( absPlaceHolderIndex, (absPlaceHolderIndex + (pPlaceHolder.length() * 2)), - pDocument + getDocument() ); } @@ -665,13 +662,13 @@ public class Range subRange = new Range( (absPlaceHolderIndex + pValue.length()), (absPlaceHolderIndex + pPlaceHolder.length() + pValue.length()), - pDocument + getDocument() ); if (subRange.usesUnicode()) subRange = new Range( (absPlaceHolderIndex + (pValue.length() * 2)), (absPlaceHolderIndex + (pPlaceHolder.length() * 2) + - (pValue.length() * 2)), pDocument + (pValue.length() * 2)), getDocument() ); subRange.delete(); @@ -942,4 +939,9 @@ public class Range return _end; } + + protected HWPFDocument getDocument() { + + return _doc; + } } diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/testRangeReplacement.doc b/src/scratchpad/testcases/org/apache/poi/hwpf/data/testRangeReplacement.doc new file mode 100644 index 0000000000000000000000000000000000000000..949980d4e14d814fe3017aa5ec876d3805a1594b GIT binary patch literal 104448 zcmeI0Yj9Q77036<0}=`tlSmO`y<#c>1bHebR*Z-tHUff=Rz)vKFcFgAO;A9sv}$V~ zTC8oY*7|6%FI$V+cdepTn|7vC+o>O%b~@JShdR@CTF18I2S|VG?0XM~d-J%t1Q_6d znEyFz@4fcgYyZx^XYcUpZ;yTBv8N{e#bsS*yJEMeuiTA_)fZv^DpRg-&dLGW)7RIR zsosV`QP*KYV0SuCdxs^wyHaHD{1>PUm7_7}J!mW%hsL905KF)viz-nSsz%453Fy6O zB03&TLMNaabRv2mIteAv$!Ib<1=XVWqf^loREMUbX=pk+4b4C^(dlRwnvLe5xo94m zkIq16q6KInIt!hR7NK*{2hh1_F**;`qw~=cbOBn5E<_Dz8EQlqp%0=abTL|vR-l#W z60{1fMwgkI&>XsL+$8#v>t6h9jFs^ zp^fMUltSI82W>((qMOiWv;}QNH=|q7t>`1@HuO<+36Z+!nPBFfJX2v08uGj*uwvp% zJ)dsz??pcTL-}a@y#$70W$khPLAsp%`yWmHNdNwAjKlr+Z*#EUzdetHD_|zYeBf;^ zqsohznRC0syIX4C@22+VR9AP`x}L=4U8$BCOS;x?>S*ok3HOAiRaUp8t2x{W%$`Xh zY@fNny|eIX`#248vHtv^L--BUT*`0kFd}k~E-B%QTZ%6Z0Z{>@cWyb`5q9>gTF= z=PiD_@3C+nIi4M5Ennj#V{K)(TE#QTm$ij^ihDO-`Zla~a+Q`=99!X185nAPN95jCUP zE0gR!J@|Bmd(k*f098b>NMp%rd($RbdZIu7_C+ zCH|NZu18-x%sT-V@$upj-psZ$ja?Sst|B|Q*ku)L;-T*-$`?-9o^}bF2fVFj>K!2M zb_osxt!%c5a3k#ijBU>IiIZ830|udC6)&PAd?mKE&pkE2(a#H)Pcl3X%pa9spVeg6 z#_O^SIlM5^Hl9OW^~|#;TnMRfA$Bm&%dk>JNsztG)(#$L=b1$leG(j@Y&qM{zz#9> z;19~~=3DbJ$l3zS>3{dVvd-knR?Y}3++u1Uzzo8dRpM^nZZ9pnmMX3(#s2BvYueUh z*aRwP4ZF*b9ddsa;g4^~e#3RxmT!l@KmMX?N|aj`mCyT5e%jR7w}Wq4vTH-Kb3s2a z%1b7=+Oc~_%6wn;*6eHb^&JzgNn6rp+jl8r@9XK$`p)(G)gL{xz2ar_t&Ud=VE+lf zd9+pVF2=I^TMoIe#Rh)k&PU#UcX?aI6Ze+6=~JG0-4N{P3D^OA-ivwK--q^h5=V&e z?;ra+@mge9?4xFXFWQ&>Sab)nk>1+v{{}SM{&ri8wk_OR$s@Gg#s?cS_3qre{&V;5 zdIR%uZ?=!V2m3{yB>0wN#+M+Sir|40(h$ILR~m5~iY@0RNv_lexR z5f!7pQGH}&HN~T4HPI#N%;U*NMQ=n+-iYqG^;u0>4y2LgkW~|J zjclKMRK$qexvf5CmQTDmke%Bx^7Ku9tdY9=;KPbmK$j@~{`8H4?7xv`8s05W=l#!0 z5k%lfBES#F|8}zOVfEhQ6H|`YM8&9At`YfoT)umBk6LqUd{ge-d*;>;6e?bi9WN5f z7vq(YoomGXX&tG{hs`ruH2pmNBe!9V67}lW$jYJM$OU)oH!D?&fCvniK-O2pmEJ(XZ7TQSs2G zL>fMm=1VlgtMBvCK;CBt%Z!#D2&6xI#7b80|yeCCn`4h;Z zI%F||?2V|H|A_Jw0TB=Z5fA|p5CIVo0TB=Z5fA|p5CIVof&2-?{~JoS2#A0Ph=2%) zfCwBa0=qfBe2l?wM|Yq*(Z|sz&|T=0=u_y^=ribUbPxJ0+K%o;pF{Vd&!aD(FQWU= zm(T;~LG)$x5c&#w7(Id>MUSDcqOYMH=yCLQ^bPb)^eyyl^aT12`Yw7BeGlzKPobyL zGwA#12k3|BN9f1sC+Mf>XXshOepcl~|IK0I3W%LUACF(_1|LgQK|C8R~ z=ypr**Vv9b9t zqr5qYRTOB}5vP#rg<|Kfi1nR^eOw`d)aS4uVCy8l{ti~sMecQmTIM=kk4w2O*Wxz0 zX6$zCPB+f2c5T?*E|I<`sZF>hx5~|Mm*bP7N5U<1XL4T`mOEUM{ynZWY-ypcnV21v zZHxq^6t?+zk4;2xr|ml0E~c)_Eho}C>Y6Df+>LG~_c`26^RQQhy_?A_;bx&adThkE zbDy3w!)z?-z7b}-sl*w_oGlwaH_O3i(?c)I(PnQsq{uvhXInU?S*>n!*wbdQ(QTmK z^4vSWo5FF|hs;_T+w!t;)^WcS+va7QZEiM)Bx6_%i<}C3)p57CVDn3cH8qLq#EA); z>7{Nu9A>%MkeKRD!=ol~&&+t+1#W@6Al+u~$2_X1#68YT_nsQYw|OL(i9L;iy(J@_ zAc|$5a$DTmFyk%Mb(2*W*=-2l?%J@gr_<@yGe>JNN=DJ@Eq1NDnR1FZY^$f;ZRMF+ zVYkw5wYG|q^!2@czZJaCWz_q(Ve7MnA|{VK8*=KcH| z-@8gv;cBpTZrPoZfuA*)t3eu|JX?@??J#anEBX(WF z7r%@B!uC9W652AX*b`i->q}oYhf(F8#V#LZX@9{u;JaN_zJ>1y<9DzNFK36lzCZUt z>nfpTBl7bN^BB}Q)|eS7VB8Jt)rDST7~Q6CbFybXaV+2JwBu~fnMr0|Xb$7k6c{qNW^`~L)+uyy8@!2Ash0Aw*womtm9$PIgI!P~K z6~s@=VPhV*Nd?TmhPbuqKRHTW_Q=EIv7mtQn;5?*kGbXR62AEKEuTJnV(aAp6*i!G literal 0 HcmV?d00001 diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java new file mode 100644 index 000000000..4b2b9ce37 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRangeReplacement.java @@ -0,0 +1,119 @@ + +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hwpf.usermodel; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.util.List; + +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.model.PicturesTable; +import org.apache.poi.hwpf.usermodel.Picture; + +import junit.framework.TestCase; + +/** + * Test to see if Range.replaceText() works even if the Range contains a + * CharacterRun that uses Unicode characters. + */ +public class TestRangeReplacement extends TestCase { + + // u201c and u201d are "smart-quotes" + private String originalText = + "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the ${organization} and all the POI contributors for their assistance in this matter.\r"; + private String searchText = "${organization}"; + private String replacementText = "Apache Software Foundation"; + private String expectedText = + "It is used to confirm that text replacement works even if Unicode characters (such as \u201c\u2014\u201d (U+2014), \u201c\u2e8e\u201d (U+2E8E), or \u201c\u2714\u201d (U+2714)) are present. Everybody should be thankful to the Apache Software Foundation and all the POI contributors for their assistance in this matter.\r"; + + private String illustrativeDocFile; + + protected void setUp() throws Exception { + + String dirname = System.getProperty("HWPF.testdata.path"); + + illustrativeDocFile = dirname + "/testRangeReplacement.doc"; + } + + /** + * Test just opening the files + */ + public void testOpen() throws Exception { + + HWPFDocument docA = new HWPFDocument(new FileInputStream(illustrativeDocFile)); + } + + /** + * Test (more "confirm" than test) that we have the general structure that we expect to have. + */ + public void testDocStructure() throws Exception { + + HWPFDocument daDoc = new HWPFDocument(new FileInputStream(illustrativeDocFile)); + + Range range = daDoc.getRange(); + + assertEquals(1, range.numSections()); + Section section = range.getSection(0); + + assertEquals(5, section.numParagraphs()); + Paragraph para = section.getParagraph(2); + + assertEquals(5, para.numCharacterRuns()); + String text = para.getCharacterRun(0).text() + para.getCharacterRun(1).text() + + para.getCharacterRun(2).text() + para.getCharacterRun(3).text() + para.getCharacterRun(4).text(); + + assertEquals(originalText, text); + } + + /** + * Test that we can replace text in our Range with Unicode text. + */ + public void testRangeReplacement() throws Exception { + + HWPFDocument daDoc = new HWPFDocument(new FileInputStream(illustrativeDocFile)); + + Range range = daDoc.getRange(); + assertEquals(1, range.numSections()); + + Section section = range.getSection(0); + assertEquals(5, section.numParagraphs()); + + Paragraph para = section.getParagraph(2); + + String text = para.text(); + assertEquals(originalText, text); + + int offset = text.indexOf(searchText); + assertEquals(181, offset); + + para.replaceText(searchText, replacementText, offset); + + // we need to let the model re-calculate the Range before we evaluate it + range = daDoc.getRange(); + + assertEquals(1, range.numSections()); + section = range.getSection(0); + + assertEquals(5, section.numParagraphs()); + para = section.getParagraph(2); + + text = para.text(); + assertEquals(expectedText, text); + } +}