/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.build.docs.dsl.docbook;
import groovy.lang.GroovySystem;
import org.apache.commons.lang.StringUtils;
import org.gradle.build.docs.dsl.source.model.EnumConstantMetaData;
import org.gradle.build.docs.dsl.source.model.MethodMetaData;
import org.gradle.build.docs.dsl.source.model.TypeMetaData;
import org.gradle.internal.jvm.Jvm;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.util.HashSet;
import java.util.Set;
public class LinkRenderer {
private final Document document;
private final DslDocModel model;
private final Set<String> primitiveTypes = new HashSet<String>();
private final String groovyVersion;
private final String javaVersion;
public LinkRenderer(Document document, DslDocModel model, String groovyVersion, String javaVersion) {
this.document = document;
this.model = model;
this.groovyVersion = groovyVersion;
this.javaVersion = javaVersion;
primitiveTypes.add("boolean");
primitiveTypes.add("byte");
primitiveTypes.add("short");
primitiveTypes.add("int");
primitiveTypes.add("long");
primitiveTypes.add("char");
primitiveTypes.add("float");
primitiveTypes.add("double");
primitiveTypes.add("void");
}
public LinkRenderer(Document document, DslDocModel model) {
this(document, model, GroovySystem.getVersion(), Jvm.current().getJavaVersion().getMajorVersion());
}
Node link(TypeMetaData type, final GenerationListener listener) {
final Element linkElement = document.createElement("classname");
type.visitSignature(new TypeMetaData.SignatureVisitor() {
public void visitText(String text) {
linkElement.appendChild(document.createTextNode(text));
}
public void visitType(String name) {
linkElement.appendChild(addType(name, listener));
}
});
linkElement.normalize();
if (linkElement.getChildNodes().getLength() == 1 && linkElement.getFirstChild() instanceof Element) {
return linkElement.getFirstChild();
}
return linkElement;
}
private Node addType(String className, GenerationListener listener) {
if (model.isKnownType(className)) {
Element linkElement = document.createElement("apilink");
linkElement.setAttribute("class", className);
return linkElement;
}
if (primitiveTypes.contains(className)) {
Element classNameElement = document.createElement("classname");
classNameElement.appendChild(document.createTextNode(className));
return classNameElement;
}
if (className.startsWith("java.")) {
Element linkElement = document.createElement("ulink");
linkElement.setAttribute("url", String.format("http://download.oracle.com/javase/%s/docs/api/%s.html", javaVersion,
className.replace(".", "/")));
Element classNameElement = document.createElement("classname");
classNameElement.appendChild(document.createTextNode(StringUtils.substringAfterLast(className, ".")));
linkElement.appendChild(classNameElement);
return linkElement;
}
if (className.startsWith("groovy.")) {
Element linkElement = document.createElement("ulink");
linkElement.setAttribute("url", String.format("http://docs.groovy-lang.org/%s/html/gapi/%s.html", groovyVersion, className.replace(
".", "/")));
Element classNameElement = document.createElement("classname");
classNameElement.appendChild(document.createTextNode(StringUtils.substringAfterLast(className, ".")));
linkElement.appendChild(classNameElement);
return linkElement;
}
//this if is a bit cheesy but 1-letter classname surely means a generic type and the warning will be useless
if (className.length() > 1) {
listener.warning(String.format("Could not generate link for unknown class '%s'", className));
}
Element element = document.createElement("classname");
element.appendChild(document.createTextNode(className));
return element;
}
public Node link(MethodMetaData method, GenerationListener listener) {
if (model.isKnownType(method.getOwnerClass().getClassName())) {
Element apilink = document.createElement("apilink");
apilink.setAttribute("class", method.getOwnerClass().getClassName());
apilink.setAttribute("method", method.getOverrideSignature());
return apilink;
} else {
listener.warning(String.format("Could not generate link for method %s", method));
Element element = document.createElement("UNKNOWN-METHOD");
element.appendChild(document.createTextNode(String.format("%s.%s()", method.getOwnerClass().getClassName(),
method.getName())));
return element;
}
}
public Node link(EnumConstantMetaData enumConstant, GenerationListener listener) {
if (model.isKnownType(enumConstant.getOwnerClass().getClassName())) {
Element apilink = document.createElement("apilink");
apilink.setAttribute("class", enumConstant.getOwnerClass().getClassName());
apilink.setAttribute("method", enumConstant.getName());
return apilink;
} else {
listener.warning(String.format("Could not generate link for enum constant %s", enumConstant));
Element element = document.createElement("UNKNOWN-ENUM");
element.appendChild(document.createTextNode(enumConstant.toString()));
return element;
}
}
}