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.schema.generator.html;
23 
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileNotFoundException;
28 import java.io.FileOutputStream;
29 import java.io.InputStreamReader;
30 import java.io.PrintStream;
31 import java.util.Collection;
32 import java.util.Iterator;
33 import java.util.Map;
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36 
37 import org.apache.openoffice.ooxml.schema.model.attribute.Attribute;
38 import org.apache.openoffice.ooxml.schema.model.attribute.AttributeGroup;
39 import org.apache.openoffice.ooxml.schema.model.attribute.AttributeGroupReference;
40 import org.apache.openoffice.ooxml.schema.model.attribute.AttributeReference;
41 import org.apache.openoffice.ooxml.schema.model.base.INode;
42 import org.apache.openoffice.ooxml.schema.model.base.INodeVisitor;
43 import org.apache.openoffice.ooxml.schema.model.complex.All;
44 import org.apache.openoffice.ooxml.schema.model.complex.Any;
45 import org.apache.openoffice.ooxml.schema.model.complex.Choice;
46 import org.apache.openoffice.ooxml.schema.model.complex.ComplexContent;
47 import org.apache.openoffice.ooxml.schema.model.complex.ComplexType;
48 import org.apache.openoffice.ooxml.schema.model.complex.ComplexTypeReference;
49 import org.apache.openoffice.ooxml.schema.model.complex.Element;
50 import org.apache.openoffice.ooxml.schema.model.complex.ElementReference;
51 import org.apache.openoffice.ooxml.schema.model.complex.Extension;
52 import org.apache.openoffice.ooxml.schema.model.complex.Group;
53 import org.apache.openoffice.ooxml.schema.model.complex.GroupReference;
54 import org.apache.openoffice.ooxml.schema.model.complex.OccurrenceIndicator;
55 import org.apache.openoffice.ooxml.schema.model.complex.Sequence;
56 import org.apache.openoffice.ooxml.schema.model.schema.Schema;
57 import org.apache.openoffice.ooxml.schema.model.schema.SchemaBase;
58 import org.apache.openoffice.ooxml.schema.model.simple.BuiltIn;
59 import org.apache.openoffice.ooxml.schema.model.simple.List;
60 import org.apache.openoffice.ooxml.schema.model.simple.Restriction;
61 import org.apache.openoffice.ooxml.schema.model.simple.SimpleContent;
62 import org.apache.openoffice.ooxml.schema.model.simple.SimpleType;
63 import org.apache.openoffice.ooxml.schema.model.simple.SimpleTypeReference;
64 import org.apache.openoffice.ooxml.schema.model.simple.Union;
65 
66 /** Create a single HTML page that shows information about all
67  *  complex and simple types.
68  */
69 public class HtmlGenerator
70     implements INodeVisitor
71 {
HtmlGenerator( final SchemaBase aSchemaBase, final Map<String, Schema> aTopLevelSchemas, final File aOutputFile)72     public HtmlGenerator(
73         final SchemaBase aSchemaBase,
74         final Map<String, Schema> aTopLevelSchemas,
75         final File aOutputFile)
76     {
77         maSchemaBase = aSchemaBase;
78         maTopLevelSchemas = aTopLevelSchemas;
79         msIndentation = "";
80         msSingleIndentation = "  ";
81         msSpace = " ";
82         try
83         {
84             maOut = new PrintStream(new FileOutputStream(aOutputFile));
85         } catch (FileNotFoundException aException)
86         {
87             aException.printStackTrace();
88             throw new RuntimeException(aException);
89         }
90     }
91 
92 
93 
94 
95     /** Read a template HTML file, expand its $... references and write the resulting content.
96      */
Generate()97     public void Generate ()
98     {
99         CopyFile("linking-template.html", true);
100         maOut.close();
101     }
102 
103 
104 
105 
CopyFile( final String sBasename, final boolean bIsTemplate)106     private void CopyFile (
107         final String sBasename,
108         final boolean bIsTemplate)
109     {
110         try
111         {
112             final BufferedReader aIn = new BufferedReader(
113                 new InputStreamReader(
114                     new FileInputStream(
115                         new File(
116                             new File("bin/org/apache/openoffice/ooxml/schema/generator/html"),
117                             sBasename))));
118 
119             final Pattern aReferencePattern = Pattern.compile("^(.*?)\\$([^\\$]+)\\$(.*)$");
120             while (true)
121             {
122                 final String sLine = aIn.readLine();
123                 if (sLine == null)
124                     break;
125 
126                 if (bIsTemplate)
127                 {
128                     final Matcher aMatcher = aReferencePattern.matcher(sLine);
129                     if (aMatcher.matches())
130                     {
131                         maOut.println(aMatcher.group(1));
132                         switch(aMatcher.group(2))
133                         {
134                             case "CSS":
135                                 CopyFile("display.css", false);
136                                 break;
137                             case "CODE":
138                                 CopyFile("code.js", false);
139                                 break;
140                             case "DATA":
141                                 WriteJsonData();
142                                 break;
143                         }
144                         maOut.printf("%s\n", aMatcher.group(3));
145                     }
146                     else
147                         maOut.printf("%s\n", sLine);
148                 }
149                 else
150                     maOut.printf("%s\n", sLine);
151             }
152             aIn.close();
153         }
154         catch (final Exception e)
155         {
156             e.printStackTrace();
157         }
158     }
159 
160 
161 
162 
WriteJsonData()163     private void WriteJsonData ()
164     {
165         maOut.printf("Data={\n");
166 
167         WriteTopLevelNodes(maSchemaBase.ComplexTypes.GetSorted());
168         WriteTopLevelNodes(maSchemaBase.SimpleTypes.GetSorted());
169         WriteTopLevelNodes(maSchemaBase.Groups.GetSorted());
170         WriteTopLevelNodes(maSchemaBase.AttributeGroups.GetSorted());
171 
172         maOut.printf("}\n");
173     }
174 
175 
176 
177 
WriteTopLevelNodes(final Iterable<? extends INode> aNodes)178     private void WriteTopLevelNodes (final Iterable<? extends INode> aNodes)
179     {
180         for (final INode aNode : aNodes)
181         {
182             maOut.printf("    \"%s\" : {\n", aNode.GetName().GetDisplayName());
183 
184             final String sSavedIndentation = msIndentation;
185             msIndentation += msSingleIndentation + msSingleIndentation;
186             aNode.AcceptVisitor(this);
187             msIndentation = sSavedIndentation;
188 
189             maOut.printf("    }, \n");
190         }
191     }
192 
193 
194 
195 
196     @Override
Visit(final All aNode)197     public void Visit (final All aNode)
198     {
199         WritePair("type", "all");
200         WriteLocation(aNode);
201         WriteAttributes(aNode);
202         WriteChildren(aNode);
203     }
204 
205 
206 
207 
208     @Override
Visit(final Any aNode)209     public void Visit (final Any aNode)
210     {
211         WritePair("type", "any");
212         WriteLocation(aNode);
213         WriteAttributes(aNode);
214         WriteChildren(aNode);
215     }
216 
217 
218 
219 
220     @Override
Visit(final ComplexContent aNode)221     public void Visit (final ComplexContent aNode)
222     {
223         WritePair("type", "complex-content");
224         WriteLocation(aNode);
225         WriteAttributes(aNode);
226         WriteChildren(aNode);
227     }
228 
229 
230 
231 
232     @Override
Visit(final ComplexType aNode)233     public void Visit (final ComplexType aNode)
234     {
235         WritePair("type", "complex-type");
236         WritePair("name", aNode.GetName().GetDisplayName());
237         WriteLocation(aNode);
238         WriteAttributes(aNode);
239         WriteChildren(aNode);
240     }
241 
242 
243 
244 
245     @Override
Visit(final ComplexTypeReference aReference)246     public void Visit (final ComplexTypeReference aReference)
247     {
248         WritePair("type", "complex-type-reference");
249         WriteLocation(aReference);
250         WritePair("referenced-complex-type", aReference.GetReferencedTypeName().GetDisplayName());
251         WriteAttributes(aReference);
252     }
253 
254 
255 
256 
257     @Override
Visit(final Choice aNode)258     public void Visit (final Choice aNode)
259     {
260         WritePair("type", "choice");
261         WriteLocation(aNode);
262         WriteChildren(aNode);
263         WriteAttributes(aNode);
264     }
265 
266 
267 
268 
269     @Override
Visit(final Element aNode)270     public void Visit (final Element aNode)
271     {
272         WritePair("type", "element");
273         WriteLocation(aNode);
274         WritePair("tag", aNode.GetElementName().GetDisplayName());
275         WritePair("result-type", aNode.GetTypeName().GetDisplayName());
276         WriteAttributes(aNode);
277     }
278 
279 
280 
281 
282     @Override
Visit(final ElementReference aReference)283     public void Visit (final ElementReference aReference)
284     {
285         WritePair("type", "element-type-reference");
286         WriteLocation(aReference);
287         WritePair("referenced-element", aReference.GetReferencedElementName().GetDisplayName());
288         WriteAttributes(aReference);
289     }
290 
291 
292 
293 
294     @Override
Visit(final Extension aNode)295     public void Visit (final Extension aNode)
296     {
297         WritePair("type", "extension");
298         WriteLocation(aNode);
299         WritePair("base-type", aNode.GetBaseTypeName().GetDisplayName());
300         WriteAttributes(aNode);
301         WriteChildren(aNode);
302     }
303 
304 
305 
306 
307     @Override
Visit(final Group aNode)308     public void Visit (final Group aNode)
309     {
310         WritePair("type", "group");
311         WriteLocation(aNode);
312         WritePair("name", aNode.GetName().GetDisplayName());
313         WriteAttributes(aNode);
314         WriteChildren(aNode);
315     }
316 
317 
318 
319 
320     @Override
Visit(final GroupReference aReference)321     public void Visit (final GroupReference aReference)
322     {
323         WritePair("type", "group-reference");
324         WriteLocation(aReference);
325         WritePair("referenced-group", aReference.GetReferencedGroupName().GetDisplayName());
326         WriteAttributes(aReference);
327     }
328 
329 
330 
331 
332     @Override
Visit(final OccurrenceIndicator aNode)333     public void Visit (final OccurrenceIndicator aNode)
334     {
335         WritePair("type", "occurrence");
336         WriteLocation(aNode);
337         WritePair("minimum", aNode.GetDisplayMinimum());
338         WritePair("maximum", aNode.GetDisplayMaximum());
339         WriteAttributes(aNode);
340         WriteChildren(aNode);
341     }
342 
343 
344 
345 
346     @Override
Visit(final Sequence aNode)347     public void Visit (final Sequence aNode)
348     {
349         WritePair("type", "sequence");
350         WriteLocation(aNode);
351         WriteAttributes(aNode);
352         WriteChildren(aNode);
353     }
354 
355 
356 
357 
358     @Override
Visit(final BuiltIn aNode)359     public void Visit (final BuiltIn aNode)
360     {
361         WritePair("type", "builtin");
362         WriteLocation(aNode);
363         WritePair("builtin-type", aNode.GetBuiltInType().GetQualifiedName().GetDisplayName());
364         WriteAttributes(aNode);
365     }
366 
367 
368 
369 
370     @Override
Visit(final List aNode)371     public void Visit (final List aNode)
372     {
373         WritePair("type", "list");
374         WriteLocation(aNode);
375         WriteAttributes(aNode);
376         WriteChildren(aNode);
377     }
378 
379 
380 
381 
382     @Override
Visit(final Restriction aNode)383     public void Visit (final Restriction aNode)
384     {
385         WritePair("type", "restriction");
386         WriteLocation(aNode);
387         WritePair("base-type", aNode.GetBaseType().GetDisplayName());
388         WriteAttributes(aNode);
389 
390         if (aNode.HasFeature(Restriction.EnumerationBit))
391             WritePair("enumeration", Join(aNode.GetEnumeration(), ";"));
392         if (aNode.HasFeature(Restriction.PatternBit))
393             WritePair("pattern", QuoteString(aNode.GetPattern()));
394         if (aNode.HasFeature(Restriction.MinExclusiveBit))
395             WritePair("exclusive-minimum", aNode.GetMinExclusive());
396         if (aNode.HasFeature(Restriction.MinInclusiveBit))
397             WritePair("inclusive-minimum", aNode.GetMinInclusive());
398         if (aNode.HasFeature(Restriction.MaxInclusiveBit))
399             WritePair("inclusive-maximum", aNode.GetMaxInclusive());
400         if (aNode.HasFeature(Restriction.MaxInclusiveBit))
401             WritePair("inclusive-maximum", aNode.GetMaxInclusive());
402         if (aNode.HasFeature(Restriction.LengthBit))
403             WritePair("length", Integer.toString(aNode.GetLength()));
404         if (aNode.HasFeature(Restriction.MinLengthBit))
405             WritePair("minimum-length", Integer.toString(aNode.GetMinimumLength()));
406         if (aNode.HasFeature(Restriction.MaxLengthBit))
407             WritePair("maximum-length", Integer.toString(aNode.GetMaximumLength()));
408         assert(aNode.GetChildCount() == 0);
409     }
410 
411 
412 
413 
414     @Override
Visit(final SimpleContent aNode)415     public void Visit (final SimpleContent aNode)
416     {
417         WritePair("type", "simple-content");
418         WriteLocation(aNode);
419         WriteAttributes(aNode);
420         WriteChildren(aNode);
421     }
422 
423 
424 
425 
426     @Override
Visit(final SimpleType aNode)427     public void Visit (final SimpleType aNode)
428     {
429         WritePair("type", "simple-type");
430         WriteLocation(aNode);
431         WritePair("name", aNode.GetName().GetDisplayName());
432         WriteAttributes(aNode);
433         WriteChildren(aNode);
434     }
435 
436 
437 
438 
439     @Override
Visit(final SimpleTypeReference aReference)440     public void Visit (final SimpleTypeReference aReference)
441     {
442         WritePair("type", "simple-type-reference");
443         WriteLocation(aReference);
444         WritePair("referenced-simple-type", aReference.GetReferencedTypeName().GetDisplayName());
445         WriteAttributes(aReference);
446     }
447 
448 
449 
450 
451     @Override
Visit(final Union aNode)452     public void Visit (final Union aNode)
453     {
454         WritePair("type", "union");
455         WriteLocation(aNode);
456         WriteAttributes(aNode);
457         WriteChildren(aNode);
458     }
459 
460 
461 
462 
463     @Override
Visit(final AttributeGroup aNode)464     public void Visit (final AttributeGroup aNode)
465     {
466         WritePair("type", "attribute-group");
467         WriteLocation(aNode);
468         WritePair("name", aNode.GetName().GetDisplayName());
469         WriteAttributes(aNode);
470         WriteChildren(aNode);
471     }
472 
473 
474 
475 
476     @Override
Visit(final AttributeReference aReference)477     public void Visit (final AttributeReference aReference)
478     {
479         WritePair("type", "attribute-reference");
480         WriteLocation(aReference);
481         WritePair("referenced-attribute", aReference.GetReferencedName().GetDisplayName());
482         WriteAttributes(aReference);
483     }
484 
485 
486 
487 
488     @Override
Visit(final Attribute aNode)489     public void Visit (final Attribute aNode)
490     {
491         WritePair("type", "attribute");
492         WriteLocation(aNode);
493         WritePair("name", aNode.GetName().GetDisplayName());
494         WritePair("default-value", aNode.GetDefault());
495         WritePair("value-type", aNode.GetTypeName().GetDisplayName());
496         WritePair("use", aNode.GetUse().toString());
497         WriteAttributes(aNode);
498         WriteChildren(aNode);
499     }
500 
501 
502 
503 
504     @Override
Visit(final AttributeGroupReference aReference)505     public void Visit (final AttributeGroupReference aReference)
506     {
507         WritePair("type", "attribute-group-reference");
508         WriteLocation(aReference);
509         WritePair("referenced-attribute-group", aReference.GetReferencedName().GetDisplayName());
510         WriteAttributes(aReference);
511     }
512 
513 
514 
515 
WriteChildren( final INode aParent)516     private void WriteChildren (
517         final INode aParent)
518     {
519         if (aParent.GetChildCount() > 0)
520         {
521             maOut.printf("%s\"children\" : [\n", msIndentation);
522             int nIndex = 0;
523             for (final INode aChild : aParent.GetChildren())
524             {
525                 maOut.printf("%s%s{\n", msIndentation, msSingleIndentation, nIndex++);
526 
527                 final String sSavedIndentation = msIndentation;
528                 msIndentation += msSingleIndentation + msSingleIndentation;
529                 aChild.AcceptVisitor(this);
530                 msIndentation = sSavedIndentation;
531 
532                 maOut.printf("%s%s},\n", msIndentation, msSingleIndentation);
533             }
534 
535             maOut.printf("%s]\n", msIndentation);
536         }
537     }
538 
539 
540 
541 
WriteAttributes( final INode aParent)542     private void WriteAttributes (
543         final INode aParent)
544     {
545         if (aParent.GetAttributeCount() > 0)
546         {
547             maOut.printf("%s\"attributes\" : [\n", msIndentation);
548             int nIndex = 0;
549             for (final INode aAttribute: aParent.GetAttributes())
550             {
551 
552                 maOut.printf("%s%s{\n", msIndentation, msSingleIndentation, nIndex++);
553 
554                 final String sSavedIndentation = msIndentation;
555                 msIndentation += msSingleIndentation + msSingleIndentation;
556                 aAttribute.AcceptVisitor(this);
557                 msIndentation = sSavedIndentation;
558 
559                 maOut.printf("%s%s},\n", msIndentation, msSingleIndentation);
560             }
561 
562             maOut.printf("%s],\n", msIndentation);
563         }
564     }
565 
566 
567 
568 
WriteLocation( final INode aNode)569     private void WriteLocation (
570         final INode aNode)
571     {
572         if (aNode.GetLocation() == null)
573             return;
574 
575         WritePair("location", aNode.GetLocation().toString());
576     }
577 
578 
579 
580 
WritePair( final String sKey, final String sValue)581     private void WritePair (
582         final String sKey,
583         final String sValue)
584     {
585         maOut.printf("%s\"%s\"%s:%s\"%s\"%s\n", msIndentation, sKey, msSpace, msSpace, sValue, ",");
586     }
587 
588 
589 
590 
Join(final Collection<String> aValues, final String sSeparator)591     private String Join (final Collection<String> aValues, final String sSeparator)
592     {
593         final Iterator<String> aIterator = aValues.iterator();
594         if ( ! aIterator.hasNext())
595             return "";
596 
597         final StringBuffer aBuffer = new StringBuffer(aIterator.next());
598         while (aIterator.hasNext())
599         {
600             aBuffer.append(sSeparator);
601             aBuffer.append(aIterator.next());
602         }
603         return aBuffer.toString();
604     }
605 
606 
607 
608 
QuoteString(final String sValue)609     private String QuoteString (final String sValue)
610     {
611         return sValue.replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;");
612     }
613 
614 
615 
616 
617     private final SchemaBase maSchemaBase;
618     private final Map<String, Schema> maTopLevelSchemas;
619     private final PrintStream maOut;
620     private String msIndentation;
621     private final String msSingleIndentation;
622     private final String msSpace;
623 }
624