1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.wordtemplate.service;
35
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.regex.Matcher;
39 import java.util.regex.Pattern;
40 import org.apache.poi.xwpf.usermodel.BodyElementType;
41 import org.apache.poi.xwpf.usermodel.IBody;
42 import org.apache.poi.xwpf.usermodel.IBodyElement;
43 import org.apache.poi.xwpf.usermodel.XWPFParagraph;
44 import org.apache.poi.xwpf.usermodel.XWPFRun;
45 import org.apache.poi.xwpf.usermodel.XWPFTable;
46 import org.apache.poi.xwpf.usermodel.XWPFTableCell;
47 import org.apache.poi.xwpf.usermodel.XWPFTableRow;
48 import fr.paris.lutece.plugins.wordtemplate.business.IWordTemplateElement;
49 import fr.paris.lutece.plugins.wordtemplate.business.WordTemplate;
50 import java.util.Map;
51 import org.apache.poi.xwpf.usermodel.XWPFDocument;
52 import org.apache.poi.xwpf.usermodel.XWPFFooter;
53 import org.apache.poi.xwpf.usermodel.XWPFHeader;
54
55
56
57
58 public class WordTemplateParser
59 {
60 private static final String INSTRUCTION_PATTERN = "\\$\\{.*?\\}|</?#.*?>";
61
62
63
64
65
66
67
68
69
70 public WordTemplate parse( XWPFDocument document, Map<String, Object> model ) throws Exception
71 {
72 WordTemplatete/business/WordTemplate.html#WordTemplate">WordTemplate wordTemplate = new WordTemplate( );
73 List<IWordTemplateElement> listTemplateElements = new ArrayList<>( );
74
75
76 for ( XWPFHeader header : document.getHeaderList( ) )
77 {
78 listTemplateElements.addAll( findInstr( header ) );
79 }
80
81 for ( XWPFFooter footer : document.getFooterList( ) )
82 {
83 listTemplateElements.addAll( findInstr( footer ) );
84 }
85
86
87 listTemplateElements.addAll( findInstr( document ) );
88
89 wordTemplate.setListInstructions( listTemplateElements );
90
91 return wordTemplate;
92 }
93
94
95
96
97
98 public static void visitBody( IBody body )
99 {
100 for ( IBodyElement bodyElement : body.getBodyElements( ) )
101 {
102 if ( bodyElement.getElementType( ).equals( BodyElementType.PARAGRAPH ) )
103 {
104 for ( XWPFRun run : ( (XWPFParagraph) bodyElement ).getRuns( ) )
105 {
106
107 }
108 }
109 if ( bodyElement.getElementType( ).equals( BodyElementType.TABLE ) )
110 {
111 for ( XWPFTableRow row : ( (XWPFTable) bodyElement ).getRows( ) )
112 {
113 for ( XWPFTableCell cell : row.getTableCells( ) )
114 {
115 visitBody( cell );
116 }
117 }
118 }
119 }
120 }
121
122
123
124
125
126
127 private List<IWordTemplateElement> findInstr( IBody body )
128 {
129 List<IWordTemplateElement> listInstruction = new ArrayList<>( );
130
131 for ( IBodyElement bodyElement : body.getBodyElements( ) )
132 {
133 if ( bodyElement.getElementType( ).equals( BodyElementType.PARAGRAPH ) )
134 {
135 listInstruction.addAll( findInstr( (XWPFParagraph) bodyElement ) );
136 }
137
138 if ( bodyElement.getElementType( ).equals( BodyElementType.TABLE ) )
139 {
140 for ( XWPFTableRow row : ( (XWPFTable) bodyElement ).getRows( ) )
141 {
142 for ( XWPFTableCell cell : row.getTableCells( ) )
143 {
144 findInstr( cell );
145 }
146 }
147 }
148 }
149
150 return listInstruction;
151 }
152
153
154
155
156
157
158 private List<IWordTemplateElement> findInstr( XWPFParagraph paragraph )
159 {
160 List<IWordTemplateElement> listInstruction = new ArrayList<>( );
161 String text = paragraph.getParagraphText( );
162 Pattern pattern = Pattern.compile( INSTRUCTION_PATTERN );
163 Matcher matcher = pattern.matcher( text );
164
165 while ( matcher.find( ) )
166 {
167 int start = matcher.start( );
168 int end = matcher.end( ) - 1;
169 formatInstr( paragraph, start, end );
170 for ( XWPFRun run : paragraph.getRuns( ) )
171 {
172 if ( run.toString( ).equals( matcher.group( ) ) )
173 {
174 InstructionService instructionService = InstructionService.init( );
175 IWordTemplateElement element = instructionService.createInstruction( run.toString( ), run );
176 listInstruction.add( element );
177 break;
178 }
179 }
180 }
181
182 return listInstruction;
183 }
184
185
186
187
188
189
190
191 private void formatInstr( XWPFParagraph paragraph, int start, int end )
192 {
193 boolean startFound = false;
194 boolean endFound = false;
195
196 while ( !endFound )
197 {
198 int pos = 0, numRun = -1, nextPos;
199
200 for ( XWPFRun run : paragraph.getRuns( ) )
201 {
202 numRun++;
203 nextPos = pos + run.toString( ).length( );
204
205 if ( start < pos && end >= nextPos )
206 {
207 XWPFRun prevRun = paragraph.getRuns( ).get( numRun - 1 );
208 prevRun.setText( prevRun.toString( ) + run.toString( ), 0 );
209 paragraph.removeRun( numRun );
210 break;
211 }
212 if ( start >= pos && start < nextPos && !startFound )
213 {
214 int startPosInRun = start - pos;
215 startFound = true;
216 if ( start > pos )
217 {
218 WordService.splitRun( run, startPosInRun );
219 break;
220 }
221 }
222 if ( end >= pos && end < nextPos )
223 {
224 int endPosInRun = end - pos;
225 endFound = true;
226
227 WordService.splitRun( run, endPosInRun + 1 );
228
229 if ( start < pos )
230 {
231 XWPFRun prevRun = paragraph.getRuns( ).get( numRun - 1 );
232 run = paragraph.getRuns( ).get( numRun );
233 prevRun.setText( prevRun.toString( ) + run.toString( ), 0 );
234 paragraph.removeRun( numRun );
235 }
236 break;
237 }
238
239 pos = nextPos;
240 }
241 }
242 }
243 }