AbstractBuilder.java revision 3233:b5d08bc0d224
1/* 2 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.javadoc.internal.doclets.toolkit.builders; 27 28import java.io.*; 29import java.lang.reflect.*; 30import java.util.*; 31 32import javax.lang.model.element.PackageElement; 33 34import jdk.javadoc.internal.doclets.toolkit.Configuration; 35import jdk.javadoc.internal.doclets.toolkit.Content; 36import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; 37import jdk.javadoc.internal.doclets.toolkit.util.Utils; 38 39import static javax.tools.Diagnostic.Kind.*; 40 41/** 42 * The superclass for all builders. A builder is a class that provides 43 * the structure and content of API documentation. A builder is completely 44 * doclet independent which means that any doclet can use builders to 45 * construct documentation, as long as it impelements the appropriate 46 * writer interfaces. For example, if a doclet wanted to use 47 * {@link ConstantsSummaryBuilder} to build a constant summary, all it has to 48 * do is implement the ConstantsSummaryWriter interface and pass it to the 49 * builder using a WriterFactory. 50 * 51 * <p><b>This is NOT part of any supported API. 52 * If you write code that depends on this, you do so at your own risk. 53 * This code and its internal interfaces are subject to change or 54 * deletion without notice.</b> 55 * 56 * @author Jamie Ho 57 */ 58 59public abstract class AbstractBuilder { 60 public static class Context { 61 /** 62 * The configuration used in this run of the doclet. 63 */ 64 final Configuration configuration; 65 66 /** 67 * Keep track of which packages we have seen for 68 * efficiency purposes. We don't want to copy the 69 * doc files multiple times for a single package. 70 */ 71 final Set<PackageElement> containingPackagesSeen; 72 73 /** 74 * Shared parser for the builder XML file 75 */ 76 final LayoutParser layoutParser; 77 78 Context(Configuration configuration, 79 Set<PackageElement> containingPackagesSeen, 80 LayoutParser layoutParser) { 81 this.configuration = configuration; 82 this.containingPackagesSeen = containingPackagesSeen; 83 this.layoutParser = layoutParser; 84 } 85 } 86 87 /** 88 * The configuration used in this run of the doclet. 89 */ 90 protected final Configuration configuration; 91 92 protected final Utils utils; 93 94 /** 95 * Keep track of which packages we have seen for 96 * efficiency purposes. We don't want to copy the 97 * doc files multiple times for a single package. 98 */ 99 protected final Set<PackageElement> containingPackagesSeen; 100 101 protected final LayoutParser layoutParser; 102 103 /** 104 * True if we want to print debug output. 105 */ 106 protected static final boolean DEBUG = false; 107 108 /** 109 * Construct a Builder. 110 * @param configuration the configuration used in this run 111 * of the doclet. 112 */ 113 public AbstractBuilder(Context c) { 114 this.configuration = c.configuration; 115 this.utils = configuration.utils; 116 this.containingPackagesSeen = c.containingPackagesSeen; 117 this.layoutParser = c.layoutParser; 118 } 119 120 /** 121 * Return the name of this builder. 122 * 123 * @return the name of the builder. 124 */ 125 public abstract String getName(); 126 127 /** 128 * Build the documentation. 129 * 130 * @throws IOException there was a problem writing the output. 131 */ 132 public abstract void build() throws IOException; 133 134 /** 135 * Build the documentation, as specified by the given XML element. 136 * 137 * @param node the XML element that specifies which component to document. 138 * @param contentTree content tree to which the documentation will be added 139 */ 140 protected void build(XMLNode node, Content contentTree) { 141 String component = node.name; 142 try { 143 invokeMethod("build" + component, 144 new Class<?>[]{XMLNode.class, Content.class}, 145 new Object[]{node, contentTree}); 146 } catch (NoSuchMethodException e) { 147 e.printStackTrace(); 148 configuration.reporter.print(ERROR, "Unknown element: " + component); 149 throw new DocletAbortException(e); 150 } catch (InvocationTargetException e) { 151 throw new DocletAbortException(e.getCause()); 152 } catch (Exception e) { 153 e.printStackTrace(); 154 configuration.reporter.print(ERROR, "Exception " + 155 e.getClass().getName() + 156 " thrown while processing element: " + component); 157 throw new DocletAbortException(e); 158 } 159 } 160 161 /** 162 * Build the documentation, as specified by the children of the given XML element. 163 * 164 * @param node the XML element that specifies which components to document. 165 * @param contentTree content tree to which the documentation will be added 166 */ 167 protected void buildChildren(XMLNode node, Content contentTree) { 168 for (XMLNode child : node.children) 169 build(child, contentTree); 170 } 171 172 /** 173 * Given the name and parameters, invoke the method in the builder. This 174 * method is required to invoke the appropriate build method as instructed 175 * by the builder XML file. 176 * 177 * @param methodName the name of the method that we would like to invoke. 178 * @param paramClasses the types for each parameter. 179 * @param params the parameters of the method. 180 */ 181 protected void invokeMethod(String methodName, Class<?>[] paramClasses, 182 Object[] params) 183 throws Exception { 184 if (DEBUG) { 185 configuration.reporter.print(ERROR, "DEBUG: " + 186 this.getClass().getName() + "." + methodName); 187 } 188 Method method = this.getClass().getMethod(methodName, paramClasses); 189 method.invoke(this, params); 190 } 191} 192