source: default/trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/EbnfHtmlFormatterVisitor.java @ 45

Last change on this file since 45 was 45, checked in by zeiss, 13 years ago
  • Property svn:mime-type set to text/plain
File size: 13.9 KB
Line 
1package de.ugoe.cs.swe.bnftools.ui.formatter;
2
3import java.util.ArrayList;
4import java.util.Iterator;
5
6import org.apache.commons.lang.StringEscapeUtils;
7import org.apache.commons.lang.StringUtils;
8import org.eclipse.emf.ecore.EObject;
9import org.eclipse.xtext.parsetree.LeafNode;
10import org.eclipse.xtext.parsetree.NodeUtil;
11
12import de.ugoe.cs.swe.bnftools.ebnf.DefinitionList;
13import de.ugoe.cs.swe.bnftools.ebnf.EtsiBnf;
14import de.ugoe.cs.swe.bnftools.ebnf.Import;
15import de.ugoe.cs.swe.bnftools.ebnf.Rule;
16import de.ugoe.cs.swe.bnftools.ebnf.RuleReference;
17import de.ugoe.cs.swe.bnftools.ebnf.SectionHeading;
18import de.ugoe.cs.swe.bnftools.ebnf.SingleDefinition;
19import de.ugoe.cs.swe.bnftools.ebnf.StringRule;
20import de.ugoe.cs.swe.bnftools.ebnf.Term;
21
22public class EbnfHtmlFormatterVisitor extends EbnfFormatterVisitor {
23
24        private ArrayList<MetaTextEntry> metaTexts = new ArrayList<MetaTextEntry>();
25        private ArrayList<MetaTextEntry> transformedTexts = new ArrayList<MetaTextEntry>();
26        private int lastMetaTextBlock = 0;
27        private boolean isParagraphOpen = false;
28       
29        public EbnfHtmlFormatterVisitor(EObject rootNode, FormatterConfig config) {
30                super(rootNode, config);
31                this.config = config;
32                buf = new StringBuffer();
33        }
34
35        protected void weaveComments() {
36                bufferPositionOriginalText = 0;
37                bufferPositionFormattedTextNoWhitespaces = 0;
38                bufferPositionFormattedText = 0;
39               
40                StringBuffer result = new StringBuffer();
41                formattedTextNoWhitespaces = buf.toString().replaceAll("[ \t\n\r]", "");
42                formattedText = buf.toString();
43
44                MetaTextEntry currentMetaText = null;
45                if (metaTexts.iterator().hasNext())
46                        currentMetaText = metaTexts.iterator().next();
47
48                MetaTextEntry currentTransformedText = null;
49                if (transformedTexts.iterator().hasNext())
50                        currentTransformedText = transformedTexts.iterator().next();
51               
52                while (bufferPositionFormattedTextNoWhitespaces <= formattedTextNoWhitespaces.length()) {
53                        skipWhitespacesOriginalText();
54                        skipWhitespacesFormattedText(result);
55                       
56                        if (!(bufferPositionOriginalText < originalText.length()))
57                                break;
58                       
59                        char formattedPositionNoWhitespaces;
60                        if (bufferPositionFormattedTextNoWhitespaces == formattedTextNoWhitespaces.length()) {
61                                formattedPositionNoWhitespaces = ' ';
62                        } else {
63                                formattedPositionNoWhitespaces = formattedTextNoWhitespaces.charAt(bufferPositionFormattedTextNoWhitespaces);
64                        }
65                        char originalPosition = originalText.charAt(bufferPositionOriginalText);
66                       
67                        String commentPrefix = "<span lang=EN-GB style='color:green;mso-no-proof:no'>";
68                        String commentSuffix = "<o:p></o:p></span>";
69
70                        if (formattedPositionNoWhitespaces != originalPosition) {
71//                              if ((currentMetaText != null) && (bufferPositionFormattedTextNoWhitespaces == currentMetaText.getOffset())) {
72//                                      result.append(currentMetaText.getText());
73//                                      metaTexts.remove(currentMetaText);
74//                                      if (metaTexts.iterator().hasNext())
75//                                              currentMetaText = metaTexts.iterator().next();
76//                                      else
77//                                              currentMetaText = null;
78//                              }
79
80                                if (formattedPositionNoWhitespaces == ';') { // formatted text always outputs the optional semicolon, skip it if necessary
81                                        bufferPositionFormattedTextNoWhitespaces++;
82                                        bufferPositionFormattedText++;
83                                } else if (isCommentNext(originalText, bufferPositionOriginalText)) {
84                                        LeafNode currentComment = allComments.get(allCommentsPosition);
85                                        if (currentComment.getTotalOffset() == bufferPositionOriginalText) {
86                                                if (isMultiLineComment(currentComment.getText())) {
87                                                        int newLinesCount = scanBackNewlinesCount(originalText, bufferPositionOriginalText-1);
88                                                        if (newLinesCount > 0) {
89                                                                if (scanBackNewlinesCount(result.toString(), result.toString().length()-1) == 0) {
90//                                                                      result.append("\n\n");
91//                                                                      result.append("<p>");
92                                                                }
93                                                                result.append("\n<br/><br/>");
94                                                                result.append(commentPrefix + currentComment.getText() + commentSuffix);
95//                                                              result.append("\n");
96                                                                result.append("\n<br/>");
97//                                                              result.append("<p/>");
98                                                        } else {
99                                                                String lastWhiteSpaces = scanBackWhitespaces(result.toString(), result.toString().length()-1);
100                                                                result.delete(result.toString().length() - lastWhiteSpaces.length(), result.toString().length());
101//                                                              result.append(" " + stripEndingNewline(currentComment.getText()));
102                                                                result.append("&nbsp;" + commentPrefix + stripEndingNewline(currentComment.getText()) + commentSuffix);
103                                                                result.append(lastWhiteSpaces);
104                                                        }
105                                                } else if (isSingleLineComment(currentComment.getText())) {
106                                                        int newLinesCount = scanBackNewlinesCount(originalText, bufferPositionOriginalText-1);
107                                                        String lastWhiteSpaces = scanBackWhitespaces(result.toString(), result.toString().length()-1);
108                                                        result.delete(result.toString().length() - lastWhiteSpaces.length(), result.toString().length());
109                                                        if (newLinesCount > 0) {
110//                                                              result.append("\n\n" + stripEndingNewline(currentComment.getText()));
111                                                                result.append("<br/><br/>" + commentPrefix + stripEndingNewline(currentComment.getText()) + commentSuffix);
112                                                        } else {
113//                                                              result.append(" " + stripEndingNewline(currentComment.getText()));
114                                                                result.append("&nbsp;" + commentPrefix + stripEndingNewline(currentComment.getText()) + commentSuffix);
115                                                        }
116                                                        result.append(lastWhiteSpaces);
117                                                }
118                                                bufferPositionOriginalText+=currentComment.getLength();
119                                                allCommentsPosition++;
120                                        }
121                                } else { // disaster handling: return original unformatted text!
122                                        System.err.println("Disaster Recovery: returning original text!!");
123                                        buf = new StringBuffer();
124                                        buf.append(originalText);
125                                        return;
126                                }
127                        } else {
128                                while (lastMetaTextBlock == 0 && (currentMetaText != null) && (bufferPositionFormattedTextNoWhitespaces >= currentMetaText.getOffset())) {
129                                        result.append(currentMetaText.getText());
130                                        metaTexts.remove(currentMetaText);
131                                        if (metaTexts.iterator().hasNext())
132                                                currentMetaText = metaTexts.iterator().next();
133                                        else
134                                                currentMetaText = null;
135                                       
136                                        if ((currentMetaText == null) && (bufferPositionFormattedTextNoWhitespaces != currentMetaText.getOffset()))
137                                                lastMetaTextBlock = 1;
138                                }
139
140                                if (currentTransformedText != null && currentTransformedText.getOffset() == bufferPositionFormattedTextNoWhitespaces) {
141                                        result.append(currentTransformedText.getTransformedText());
142                                        bufferPositionOriginalText += currentTransformedText.getText().length();
143                                        bufferPositionFormattedText += currentTransformedText.getText().length();
144                                        bufferPositionFormattedTextNoWhitespaces += currentTransformedText.getText().replaceAll("[ \t\r\n]", "").length();
145                                        transformedTexts.remove(currentTransformedText);
146                                        currentTransformedText = null;
147                                       
148                                        if (transformedTexts.iterator().hasNext())
149                                                currentTransformedText = transformedTexts.iterator().next();
150                                } else {
151                                        String text = formattedText.substring(bufferPositionFormattedText, bufferPositionFormattedText+1);
152                                        result.append(text);
153                                        bufferPositionOriginalText++;
154                                        bufferPositionFormattedText++;
155                                        bufferPositionFormattedTextNoWhitespaces++;
156                                }
157
158                                while ( lastMetaTextBlock == 1 && currentMetaText != null && bufferPositionFormattedTextNoWhitespaces >= currentMetaText.getOffset()) {
159                                        result.append(currentMetaText.getText());
160                                        metaTexts.remove(currentMetaText);
161                                        if (metaTexts.iterator().hasNext()) {
162                                                currentMetaText = metaTexts.iterator().next();
163                                        } else {
164                                                currentMetaText = null;
165                                        }
166                                       
167                                        if ((currentMetaText == null) || (bufferPositionFormattedTextNoWhitespaces != currentMetaText.getOffset()))
168                                                lastMetaTextBlock = 0;
169                                }
170                        }
171                }
172                while ( bufferPositionFormattedTextNoWhitespaces >= formattedTextNoWhitespaces.length()-1 && currentMetaText != null) {
173                        result.append(currentMetaText.getText());
174                        metaTexts.remove(currentMetaText);
175                        if (metaTexts.iterator().hasNext()) {
176                                currentMetaText = metaTexts.iterator().next();
177                        } else {
178                                currentMetaText = null;
179                        }
180                }
181
182               
183                buf = result;
184        }
185       
186        protected void metaText(String str) {
187                MetaTextEntry metaTextEntry = new MetaTextEntry(str, buf.toString().replaceAll("[ \t\n\r]", "").length());
188                metaTexts.add(metaTextEntry);
189        }
190
191        protected void textTransformed(String original, String transformed) {
192                MetaTextEntry metaText = new MetaTextEntry(original, transformed, buf.toString().replaceAll("[ \t\n\r]", "").length());
193                transformedTexts.add(metaText);
194                buf.append(original);
195                newLineOffsetCounter += original.length();
196        }
197       
198        protected void newLine() {
199                buf.append("\n");
200                if (!isParagraphOpen) {
201                        metaText("\n<p class=PL style='mso-pagination:widow-orphan lines-together;page-break-after: avoid'>\n");
202                        isParagraphOpen = true;
203                } else {
204                        metaText("\n</p>\n");
205                        isParagraphOpen = false;
206                }
207                openParagraph();
208
209                if ((ruleSpacingStack != null) && (!ruleSpacingStack.empty())) {
210                        newLineOffsetCounter = ruleSpacingStack.peek();
211                } else {
212                        newLineOffsetCounter = 0;
213                }
214        }
215       
216        protected void space() {
217                metaText("<span style='mso-spacerun:yes'>&nbsp;</span>");
218                buf.append(" ");
219                newLineOffsetCounter++;
220        }
221       
222        protected void spaces(int count) {
223                metaText("<span style='mso-spacerun:yes'>");
224                buf.append(" ");
225                for (int i=0; i < count; i++) {
226                        metaText("&nbsp;");
227                }
228                metaText("</span>");
229        }
230       
231        protected void wrap() {
232                if ((config.isWrapAfterThreshold()) && (newLineOffsetCounter > config.getWrapThreshold())) {
233                        char last = buf.toString().charAt(buf.toString().length()-1);
234                        if (!((last == '(' || last == '[' || last == '{' ))) {
235                                newLine();
236                                newLine();
237                                if (ruleSpacingStack.size() > 1)
238                                        spaces(ruleSpacingStack.peek() + 1);
239                                else
240                                        spaces(ruleSpacingStack.peek());
241                        }
242                }
243        }
244       
245        private void closeOpenParagraph() {
246                if (isParagraphOpen) {
247                        metaText("\n</p>\n");
248                        isParagraphOpen = false;
249                }
250        }
251
252        private void openParagraph() {
253                if (!isParagraphOpen) {
254                        metaText("\n<p class=PL style='mso-pagination:widow-orphan lines-together;page-break-after: avoid'>\n");
255                        isParagraphOpen = true;
256                }
257        }
258        // -----------------------------------------------------------------------------
259       
260        protected void visitBefore(EtsiBnf node) {
261                parserEtsiBnfNode = NodeUtil.getNodeAdapter(node).getParserNode();
262                collectAllComments(parserEtsiBnfNode);
263                originalText = NodeUtil.getNodeAdapter(node).getParserNode().serialize();
264                originalTextNoWhitespaces = originalText.replaceAll("[ \t\n\r]", "");
265               
266                textTransformed("grammar " + node.getName(), "");
267                if (node.getType() != null)
268                        textTransformed(node.getType(), "");
269                textTransformed(";", "");
270//              metaText("<body lang=EN-US link=blue vlink=purple style='tab-interval:14.15pt'>");
271//              metaText("<div class=WordSection1>");
272//              System.out.println("call!!!");
273               
274//              newLine();
275//              newLine();
276        }
277       
278        protected void visitAfter(EtsiBnf node) {
279                closeOpenParagraph();
280               
281                metaText("</div>\n");
282                metaText("</body>\n");
283                metaText("</html>\n");
284                weaveComments();
285        }
286
287        protected void visitBefore(Import node) {
288                textTransformed("import \"" + node.getImportURI() + "\"","");
289                if (node.getGrammarType() != null) {
290                        textTransformed("/" + node.getGrammarType(), "");
291                }
292                if (node.getLabel() != null) {
293                        space();
294                        textTransformed("label: " + node.getLabel(), "");
295                }
296                textTransformed(";", "");
297//              text("\n");
298        }
299       
300        protected void visitBefore(SectionHeading node) {
301                if (!lastWasSectionHeading && !buf.substring(buf.length()-2).equals("\n\n"))
302                        newLine();
303               
304                lastWasSectionHeading=true;
305               
306                metaText("<h3><span lang=EN-GB>\n");
307                String text = node.getSectionHeader().replaceAll("[\n\r]", "");
308                textTransformed(text, StringEscapeUtils.escapeHtml(text).replaceAll("[\n\r]", ""));
309//              textTransformed(text, text.replaceAll("[\t]", "\\<span style='mso-tab-count:1'\\>"));
310                metaText("\n</span></h3>\n");
311        }
312
313        protected void visitAfter(SectionHeading node) {
314//              newLine();
315                closeOpenParagraph();
316        }
317
318        protected void visitBefore(RuleReference node) {
319                wrap();
320               
321                String prefix = "<u><span style='color:blue'><a href=\"#T" + node.getRuleref().getName().replaceAll("[ \t\n\r]","") + "\">";
322//              metaText(prefix);
323                textTransformed(node.getRuleref().getName(), prefix + node.getRuleref().getName().replaceAll("[ \t\n\r]", "") + "</a></span></u>");
324        }
325
326        protected void visitAfter(RuleReference node) {
327        }
328
329        protected void visitBefore(Rule node) {
330//              if (lastWasSectionHeading)
331               
332                newLine();
333               
334                lastWasSectionHeading=false;
335
336                newLineOffsetCounter = 0;
337
338                if (node.getRulenumber() > 0)
339                        text(node.getRulenumber() + ". ");
340
341                String prefix = "<span lang=EN-GB style='mso-no-proof:no'><a name=\"T" + node.getName() + "\">";
342//              metaText(prefix);
343                textTransformed(node.getName(), prefix + node.getName().replaceAll("[ \t\r\n]", "") + "</a>");
344//              metaText("</a>");
345                text(" ::= ");
346               
347                rightHandSideRuleOffset = newLineOffsetCounter;
348                ruleSpacingStack.push(newLineOffsetCounter);
349        }
350       
351        protected void visitAfter(Rule node) {
352                metaText("<o:p></o:p>\n</span>");
353                text(";");
354                newLine();
355                text("\n");
356                ruleSpacingStack.pop();
357        }
358       
359        protected void visitBefore(StringRule node) {
360                wrap();
361                if (node.getLiteral() != null) {
362//                      text("\"" + node.getLiteral() + "\"");
363                        textTransformed("\"" + node.getLiteral() + "\"", StringEscapeUtils.escapeHtml("\"" + node.getLiteral() + "\"").replaceAll("[ \t\n\r]", "").trim());
364//                      textTransformed("\"" + node.getLiteral() + "\"", "gnabar");
365                } else if (node.getColon() != null) {
366//                      text("\"\"\"");
367                        textTransformed("\"\"\"", StringEscapeUtils.escapeHtml("\"\"\"").replaceAll("[ \t\n\r]", "").trim());
368//                      textTransformed("\"\"\"", "gnabar");
369                }
370        }
371
372        protected void visitAfter(StringRule node) {
373        }
374       
375        protected void visitAfter(Term node) {
376                if (!isLastElement()) {
377                        metaText("<span style='mso-spacerun:yes'>&nbsp;</span>");
378                        newLineOffsetCounter++;
379//                      space();
380                }
381        }
382
383}
Note: See TracBrowser for help on using the repository browser.