1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements.  See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership.  The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License.  You may obtain a copy of the License at
10 *
11 *   http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied.  See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21 
22 package org.apache.openoffice.ooxml.viewer.xml;
23 
24 import java.awt.Color;
25 import java.util.HashMap;
26 import java.util.Map;
27 
28 import org.apache.openoffice.ooxml.viewer.tokenview.DocumentFactory;
29 import org.apache.openoffice.ooxml.viewer.tokenview.Style;
30 import org.apache.openoffice.ooxml.viewer.tokenview.TokenView;
31 
32 public class DocumentTokenFormatter
33 {
DocumentTokenFormatter( final XMLScanner aScanner, final TokenView<TokenType> aView)34     DocumentTokenFormatter (
35         final XMLScanner aScanner,
36         final TokenView<TokenType> aView)
37     {
38         maScanner = aScanner;
39         maView = aView.GetDocumentFactory();
40 
41         maTagStartEndStyle = new Style().SetForegroundColor(new Color(0x87CEFA));  // Light Sky Blue
42         maNamespaceNameStyle = new Style().SetForegroundColor(new Color(0x7B68EE)); // Medium Slate Blue
43         maIdentifierStyle = new Style()
44             .SetForegroundColor(new Color(0x7B68EE))  // Medium Slate Blue
45             .SetBold();
46         maTextStyle = new Style().SetForegroundColor(new Color(0xF08080)); // Light Coral
47         maAttributeValueStyle = new Style().SetForegroundColor(new Color(0xFFA07A)); // Light Salmon
48 
49         msIndentation = "";
50 
51         maNamespaceMap = new HashMap<String,String>();
52     }
53 
54 
55 
56 
Parse()57     public void Parse ()
58     {
59         try
60         {
61             ParseIntro();
62             AppendText("\n", TokenType.WHITESPACE, null, -1);
63             while (true)
64             {
65                 switch (maScanner.Peek().Type)
66                 {
67                     case EOF:
68                         return;
69 
70                     case TAG_START:
71                     case END_TAG_START:
72                         ParseTag();
73                         AppendText("\n", TokenType.WHITESPACE, null, -1);
74                         break;
75 
76                     default:
77                         ParseText();
78                 }
79             }
80         }
81         catch(final Exception aException)
82         {
83             aException.printStackTrace();
84         }
85         maView.FinishText();
86     }
87 
88 
89 
90 
GetNamespaceMap()91     Map<String,String> GetNamespaceMap ()
92     {
93         return maNamespaceMap;
94     }
95 
96 
97 
98 
ParseIntro()99     private void ParseIntro ()
100     {
101         final Token aStartToken = maScanner.Next();
102         ExpectToken(aStartToken, TokenType.INTRO_START);
103         ShowToken(aStartToken);
104 
105         ParseTagContent();
106 
107         final Token aEndToken = maScanner.Next();
108         ExpectToken(aEndToken, TokenType.INTRO_END);
109         ShowToken(aEndToken);
110     }
111 
112 
113 
114 
ParseTag()115     private void ParseTag ()
116     {
117         final Token aStartToken = maScanner.Next();
118         ExpectToken(aStartToken, TokenType.TAG_START, TokenType.END_TAG_START);
119         if (aStartToken.Type == TokenType.TAG_START)
120             maView.BeginGroup();
121         if (aStartToken.Type == TokenType.END_TAG_START)
122             DecreaseIndentation();
123         ShowToken(aStartToken);
124 
125         ParseTagContent();
126 
127         final Token aEndToken = maScanner.Next();
128         if (aStartToken.Type == TokenType.TAG_START)
129             ExpectToken(aEndToken, TokenType.TAG_END, TokenType.ELEMENT_END);
130         else
131             ExpectToken(aEndToken, TokenType.TAG_END);
132         ShowToken(aEndToken);
133 
134         if (aStartToken.Type != TokenType.END_TAG_START
135             && aEndToken.Type != TokenType.ELEMENT_END)
136         {
137             IncreaseIndentation();
138         }
139         else
140         {
141             maView.EndGroup();
142         }
143     }
144 
145 
146 
147 
ParseTagContent()148     private void ParseTagContent ()
149     {
150         ParseQualifiedName();
151 
152         if (maScanner.Peek().Type != TokenType.IDENTIFIER)
153             return;
154 
155         IncreaseIndentation();
156         while (true)
157         {
158             final Token aToken = maScanner.Peek();
159             if (aToken.Type != TokenType.IDENTIFIER)
160                 break;
161 
162             if (mbStartNewLineBeforeEachAttribute
163                 || mbStartNewLineBeforeNamespaceDefinition && aToken.Text.startsWith("xmlns"))
164             {
165                 AppendText("\n", TokenType.WHITESPACE, null, -1);
166                 AppendText("  ", TokenType.WHITESPACE, null, -1);
167             }
168             else
169             {
170                 AppendText(" ", TokenType.WHITESPACE, null, -1);
171             }
172 
173             ParseQualifiedName();
174             final Token aAssignToken = maScanner.Next();
175             ExpectToken(aAssignToken, TokenType.ATTRIBUTE_DEFINE);
176             ShowToken(aAssignToken);
177 
178             final Token aValueToken = maScanner.Next();
179             ExpectToken(aValueToken, TokenType.ATTRIBUTE_VALUE);
180             ShowToken(aValueToken, maAttributeValueStyle);
181 
182             if (msLastNamespaceName.equals("xmlns"))
183                 SaveNamespaceDefinition(msLastName, StripValueQuotes(aValueToken.Text));
184         }
185         DecreaseIndentation();
186     }
187 
188 
189 
190 
ParseQualifiedName()191     private void ParseQualifiedName ()
192     {
193         final Token aNameToken = maScanner.Next();
194         ExpectToken(aNameToken, TokenType.IDENTIFIER);
195         if (maScanner.Peek().Type == TokenType.COLON)
196         {
197             final Token aSeparatorToken = maScanner.Next();
198             final Token aSecondNameToken = maScanner.Next();
199             ExpectToken(aSecondNameToken, TokenType.IDENTIFIER);
200             ShowToken(aNameToken, maNamespaceNameStyle);
201             ShowToken(aSeparatorToken);
202             ShowToken(aSecondNameToken, maIdentifierStyle);
203 
204             msLastNamespaceName = aNameToken.Text;
205             msLastName = aSecondNameToken.Text;
206         }
207         else
208         {
209             ShowToken(aNameToken, maIdentifierStyle);
210 
211             msLastNamespaceName = "";
212             msLastName = aNameToken.Text;
213         }
214     }
215 
216 
217 
218 
ParseText()219     private void ParseText ()
220     {
221         final Token aTextToken = maScanner.Next();
222         ExpectToken(aTextToken, TokenType.TEXT);
223         ShowToken(aTextToken, maTextStyle);
224         AppendText("\n", TokenType.WHITESPACE, null, -1);
225     }
226 
227 
228 
229 
ExpectToken(final Token aToken, final TokenType ... aExcpectedTypes)230     private TokenType ExpectToken (final Token aToken, final TokenType ... aExcpectedTypes)
231     {
232         for (final TokenType eType : aExcpectedTypes)
233             if (aToken.Type == eType)
234                 return eType;
235 
236         if (aExcpectedTypes.length == 1)
237         {
238             throw new RuntimeException(
239                     String.format(
240                             "expected '%s' but got %s",
241                             aExcpectedTypes[0].toString(),
242                             aToken.toString()));
243         }
244         else
245         {
246             String sList = null;
247             for (final TokenType eType : aExcpectedTypes)
248             {
249                 if (sList != null)
250                     sList += String.format(", '%s'", eType.toString());
251                 else
252                     sList = String.format("'%s'", eType.toString());
253             }
254                     throw new RuntimeException(
255                     String.format(
256                             "expected one of %s but got %s",
257                             sList,
258                             aToken.toString()));
259         }
260     }
261 
262 
263 
264 
ShowToken(final Token aToken)265     private void ShowToken (final Token aToken)
266     {
267         AppendText(aToken.Text, aToken.Type, GetStyle(aToken.Type), aToken.Offset);
268     }
269 
270 
271 
272 
ShowToken( final Token aToken, final Style aStyle)273     private void ShowToken (
274         final Token aToken,
275         final Style aStyle)
276     {
277         AppendText(aToken.Text, aToken.Type, aStyle, aToken.Offset);
278     }
279 
280 
281 
282 
AppendText( final String sText, final TokenType eTokenType, final Style aStyle, final int nOffset)283     private void AppendText (
284         final String sText,
285         final TokenType eTokenType,
286         final Style aStyle,
287         final int nOffset)
288     {
289         try
290         {
291             if (mbIsAtBeginningOfLine)
292             {
293                 AddText(msIndentation, TokenType.WHITESPACE, aStyle, -1);
294                 mbIsAtBeginningOfLine = false;
295             }
296             AddText(sText, eTokenType, aStyle, nOffset);
297             mbIsAtBeginningOfLine = sText.endsWith("\n");
298         }
299         catch (RuntimeException e)
300         {
301             e.printStackTrace();
302         }
303     }
304 
305 
306 
307 
AddText( final String sText, final TokenType eTokenType, final Style aStyle, final int nOffset)308     private void AddText (
309         final String sText,
310         final TokenType eTokenType,
311         final Style aStyle,
312         final int nOffset)
313     {
314         maView.AddText(sText, eTokenType, aStyle, nOffset);
315     }
316 
317 
318 
319 
IncreaseIndentation()320     private void IncreaseIndentation ()
321     {
322         msIndentation += "    ";
323     }
324 
325 
326 
327 
DecreaseIndentation()328     private void DecreaseIndentation ()
329     {
330         if ( ! msIndentation.isEmpty())
331             msIndentation = msIndentation.substring(4);
332     }
333 
334 
335 
336 
GetStyle(final TokenType eType)337     private Style GetStyle (final TokenType eType)
338     {
339         switch(eType)
340         {
341             case TAG_START:
342             case TAG_END:
343             case END_TAG_START:
344             case INTRO_START:
345             case INTRO_END:
346             case ELEMENT_END:
347                 return maTagStartEndStyle;
348 
349             case IDENTIFIER:
350                 return maIdentifierStyle;
351 
352             case TEXT:
353                 return maTextStyle;
354 
355             case ATTRIBUTE_VALUE:
356                 return maAttributeValueStyle;
357 
358             default:
359                 return null;
360         }
361     }
362 
363 
364 
365 
StripValueQuotes(final String sQuotedValue)366     private String StripValueQuotes (final String sQuotedValue)
367     {
368         final String sValue = sQuotedValue.substring(1, sQuotedValue.length()-1);
369         return sValue;
370     }
371 
372 
373 
374 
SaveNamespaceDefinition(final String sShortName, final String sLongName)375     private void SaveNamespaceDefinition (final String sShortName, final String sLongName)
376     {
377         maNamespaceMap.put(sShortName, sLongName);
378     }
379 
380 
381 
382 
383     private final XMLScanner maScanner;
384     private final DocumentFactory<TokenType> maView;
385     private final Style maTagStartEndStyle;
386     private final Style maNamespaceNameStyle;
387     private final Style maIdentifierStyle;
388     private final Style maTextStyle;
389     private final Style maAttributeValueStyle;
390     private String msIndentation;
391     private boolean mbIsAtBeginningOfLine;
392 
393     private String msLastNamespaceName;
394     private String msLastName;
395     private Map<String,String> maNamespaceMap;
396 
397     private final boolean mbStartNewLineBeforeEachAttribute = false;
398     private final boolean mbStartNewLineBeforeNamespaceDefinition = true;
399 }
400