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("<", "<").replace(">", ">").replace("\"", """); 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