001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.xbean.spring.generator;
018
019 import java.io.File;
020 import java.io.FileWriter;
021 import java.io.IOException;
022 import java.io.PrintWriter;
023 import java.util.Iterator;
024 import java.util.List;
025
026 /**
027 * @author Dain Sundstrom
028 * @version $Id$
029 * @since 1.0
030 */
031 public class DocumentationGenerator implements GeneratorPlugin {
032 private final File destFile;
033 private LogFacade log;
034
035 public DocumentationGenerator(File destFile) {
036 this.destFile = destFile;
037 }
038
039 public void generate(NamespaceMapping namespaceMapping) throws IOException {
040 String namespace = namespaceMapping.getNamespace();
041
042 // TODO can only handle 1 schema document so far...
043 File file = new File(destFile.getParentFile(), destFile.getName() + ".html");
044 log.log("Generating HTML documentation file: " + file + " for namespace: " + namespace);
045 PrintWriter out = new PrintWriter(new FileWriter(file));
046 try {
047 generateDocumentation(out, namespaceMapping);
048 } finally {
049 out.close();
050 }
051 }
052
053 private void generateDocumentation(PrintWriter out, NamespaceMapping namespaceMapping) {
054 String namespace = namespaceMapping.getNamespace();
055
056 out.println("<!-- NOTE: this file is autogenerated by Apache XBean -->");
057 out.println("<html>");
058 out.println("<head>");
059 out.println("<title>Schema for namespace: " + namespace + "</title>");
060 out.println("<link rel='stylesheet' href='style.css' type='text/css'>");
061 out.println("<link rel='stylesheet' href='http://activemq.org/style.css' type='text/css'>");
062 out.println("<link rel='stylesheet' href='http://activemq.org/style-xb.css' type='text/css'>");
063 out.println("</head>");
064 out.println();
065 out.println("<body>");
066 out.println();
067
068 generateRootElement(out, namespaceMapping);
069
070 generateElementsSummary(out, namespaceMapping);
071 out.println();
072 out.println();
073
074 generateElementsDetail(out, namespaceMapping);
075
076 out.println();
077 out.println("</body>");
078 out.println("</html>");
079 }
080
081 private void generateRootElement(PrintWriter out, NamespaceMapping namespaceMapping) {
082 ElementMapping rootElement = namespaceMapping.getRootElement();
083 if (rootElement != null) {
084 out.println("<h1>Root Element</h1>");
085 out.println("<table>");
086 out.println(" <tr><th>Element</th><th>Description</th><th>Class</th>");
087 generateElementSummary(out, rootElement);
088 out.println("</table>");
089 out.println();
090 }
091 }
092
093 private void generateElementsSummary(PrintWriter out, NamespaceMapping namespaceMapping) {
094 out.println("<h1>Element Summary</h1>");
095 out.println("<table>");
096 out.println(" <tr><th>Element</th><th>Description</th><th>Class</th>");
097 for (Iterator iter = namespaceMapping.getElements().iterator(); iter.hasNext();) {
098 ElementMapping element = (ElementMapping) iter.next();
099 generateElementSummary(out, element);
100 }
101 out.println("</table>");
102 }
103
104 private void generateElementSummary(PrintWriter out, ElementMapping element) {
105 out.println(" <tr>" +
106 "<td><a href='#" + element.getElementName() + "'>" + element.getElementName() + "</a></td>" +
107 "<td>" + element.getDescription() + "</td>" +
108 "<td>" + element.getClassName() + "</td></tr>");
109 }
110
111 private void generateElementsDetail(PrintWriter out, NamespaceMapping namespaceMapping) {
112 out.println("<h1>Element Detail</h1>");
113 for (Iterator iter = namespaceMapping.getElements().iterator(); iter.hasNext();) {
114 ElementMapping element = (ElementMapping) iter.next();
115 generateHtmlElementDetail(out, namespaceMapping, element);
116 }
117 }
118
119 private void generateHtmlElementDetail(PrintWriter out, NamespaceMapping namespaceMapping, ElementMapping element) {
120 out.println("<h2>Element: <a name='" + element.getElementName() + "'>" + element.getElementName() + "</a></h2>");
121
122 boolean hasAttributes = false;
123 boolean hasElements = false;
124 for (Iterator iterator = element.getAttributes().iterator(); iterator.hasNext() && (!hasAttributes || !hasElements);) {
125 AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
126 Type type = attributeMapping.getType();
127 if (namespaceMapping.isSimpleType(type)) {
128 hasAttributes = true;
129 } else {
130 hasElements = true;
131 }
132 }
133
134 if (hasAttributes) {
135 out.println("<table>");
136 out.println(" <tr><th>Attribute</th><th>Type</th><th>Description</th>");
137 for (Iterator iterator = element.getAttributes().iterator(); iterator.hasNext();) {
138 AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
139 Type type = attributeMapping.getType();
140 if (namespaceMapping.isSimpleType(type)) {
141 out.println(" <tr><td>" + attributeMapping.getAttributeName() + "</td><td>" + Utils.getXsdType(type)
142 + "</td><td>" + attributeMapping.getDescription() + "</td></tr>");
143 }
144
145 }
146 out.println("</table>");
147 }
148
149 if (hasElements) {
150 out.println("<table>");
151 out.println(" <tr><th>Element</th><th>Type</th><th>Description</th>");
152 for (Iterator iterator = element.getAttributes().iterator(); iterator.hasNext();) {
153 AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
154 Type type = attributeMapping.getType();
155 if (!namespaceMapping.isSimpleType(type)) {
156 out.print(" <tr><td>" + attributeMapping.getAttributeName() + "</td><td>");
157 printComplexPropertyTypeDocumentation(out, namespaceMapping, type);
158 out.println("</td><td>" + attributeMapping.getDescription() + "</td></tr>");
159 }
160 }
161 out.println("</table>");
162 }
163 }
164
165 private void printComplexPropertyTypeDocumentation(PrintWriter out, NamespaceMapping namespaceMapping, Type type) {
166 if (type.isCollection()) {
167 out.print("(");
168 }
169
170 List types;
171 if (type.isCollection()) {
172 types = Utils.findImplementationsOf(namespaceMapping, type.getNestedType());
173 } else {
174 types = Utils.findImplementationsOf(namespaceMapping, type);
175 }
176
177 for (Iterator iterator = types.iterator(); iterator.hasNext();) {
178 ElementMapping element = (ElementMapping) iterator.next();
179 out.print("<a href='#" + element.getElementName() + "'>" + element.getElementName() + "</a>");
180 if (iterator.hasNext()) {
181 out.print(" | ");
182 }
183 }
184 if (types.size() == 0) {
185 out.print("<spring:bean/>");
186 }
187
188 if (type.isCollection()) {
189 out.print(")*");
190 }
191 }
192
193 public LogFacade getLog() {
194 return log;
195 }
196
197 public void setLog(LogFacade log) {
198 this.log = log;
199 }
200 }