View Javadoc
1   /*
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.metaschema.schemagen.xml.impl;
28  
29  import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
30  import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
31  import gov.nist.secauto.metaschema.core.model.IDefinition;
32  import gov.nist.secauto.metaschema.core.model.IModelElement;
33  import gov.nist.secauto.metaschema.core.model.INamedInstance;
34  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
35  import gov.nist.secauto.metaschema.schemagen.SchemaGenerationException;
36  import gov.nist.secauto.metaschema.schemagen.xml.XmlSchemaGenerator;
37  
38  import java.util.ArrayList;
39  import java.util.List;
40  
41  import javax.xml.stream.XMLStreamException;
42  
43  import edu.umd.cs.findbugs.annotations.NonNull;
44  import edu.umd.cs.findbugs.annotations.Nullable;
45  
46  public final class DocumentationGenerator {
47  
48    private final @Nullable String formalName;
49    private final @Nullable MarkupLine description;
50    private final @NonNull List<MarkupMultiline> remarks;
51    private final @NonNull IModelElement modelElement;
52  
53    private DocumentationGenerator(@NonNull IDefinition definition) {
54      this.formalName = definition.getEffectiveFormalName();
55      this.description = definition.getEffectiveDescription();
56  
57      MarkupMultiline remarks = definition.getRemarks();
58      this.remarks = remarks == null ? CollectionUtil.emptyList() : CollectionUtil.singletonList(remarks);
59  
60      this.modelElement = definition;
61    }
62  
63    private DocumentationGenerator(@NonNull INamedInstance instance) {
64      this.formalName = instance.getEffectiveFormalName();
65      this.description = instance.getEffectiveDescription();
66  
67      List<MarkupMultiline> remarks = new ArrayList<>(2);
68      MarkupMultiline remark = instance.getRemarks();
69      if (remark != null) {
70        remarks.add(remark);
71      }
72  
73      remark = instance.getDefinition().getRemarks();
74      if (remark != null) {
75        remarks.add(remark);
76      }
77  
78      this.remarks = CollectionUtil.listOrEmpty(remarks);
79  
80      this.modelElement = instance;
81    }
82  
83    @Nullable
84    public String getFormalName() {
85      return formalName;
86    }
87  
88    @Nullable
89    public MarkupLine getDescription() {
90      return description;
91    }
92  
93    @NonNull
94    public List<MarkupMultiline> getRemarks() {
95      return remarks;
96    }
97  
98    @NonNull
99    public IModelElement getModelElement() {
100     return modelElement;
101   }
102 
103   private void generate(@NonNull XmlGenerationState state) {
104     String formalName = getFormalName();
105     MarkupLine description = getDescription();
106     List<MarkupMultiline> remarks = getRemarks();
107 
108     if (formalName != null || description != null || !remarks.isEmpty()) {
109       generateDocumentation(formalName, description, remarks, state.getNS(getModelElement()), state);
110     }
111   }
112 
113   public static void generateDocumentation(
114       @NonNull IDefinition definition,
115       @NonNull XmlGenerationState state) {
116     new DocumentationGenerator(definition).generate(state);
117   }
118 
119   public static void generateDocumentation(
120       @NonNull INamedInstance instance,
121       @NonNull XmlGenerationState state) {
122     new DocumentationGenerator(instance).generate(state);
123   }
124 
125   public static void generateDocumentation( // NOPMD acceptable complexity
126       @Nullable String formalName,
127       @Nullable MarkupLine description,
128       @NonNull List<MarkupMultiline> remarks,
129       @NonNull String xmlNS, @NonNull XmlGenerationState state) {
130 
131     try {
132       state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "annotation", XmlSchemaGenerator.NS_XML_SCHEMA);
133       if (formalName != null || description != null) {
134         state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "appinfo", XmlSchemaGenerator.NS_XML_SCHEMA);
135 
136         if (formalName != null) {
137           state.writeStartElement(xmlNS, "formal-name");
138           state.writeCharacters(formalName);
139           state.writeEndElement();
140         }
141 
142         if (description != null) {
143           state.writeStartElement(xmlNS, "description");
144           description.writeXHtml(xmlNS, state.getXMLStreamWriter());
145           state.writeEndElement();
146         }
147 
148         state.writeEndElement(); // xs:appInfo
149       }
150 
151       state.writeStartElement(XmlSchemaGenerator.PREFIX_XML_SCHEMA, "documentation", XmlSchemaGenerator.NS_XML_SCHEMA);
152       state.writeNamespace("", XmlSchemaGenerator.NS_XHTML);
153 
154       if (description != null) {
155         // write description
156         state.writeStartElement(XmlSchemaGenerator.NS_XHTML, "p");
157 
158         if (formalName != null) {
159           state.writeStartElement(XmlSchemaGenerator.NS_XHTML, "b");
160           state.writeCharacters(formalName);
161           state.writeEndElement();
162           state.writeCharacters(": ");
163         }
164 
165         description.writeXHtml(XmlSchemaGenerator.NS_XHTML, state.getXMLStreamWriter());
166         state.writeEndElement(); // p
167       }
168 
169       for (MarkupMultiline remark : remarks) {
170         remark.writeXHtml(XmlSchemaGenerator.NS_XHTML, state.getXMLStreamWriter());
171       }
172 
173       state.writeEndElement(); // xs:documentation
174       state.writeEndElement(); // xs:annotation
175     } catch (XMLStreamException ex) {
176       throw new SchemaGenerationException(ex);
177     }
178   }
179 }