/* * 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.links; import org.gradle.build.docs.dsl.source.model.ClassMetaData; import org.gradle.build.docs.dsl.source.model.EnumConstantMetaData; import org.gradle.build.docs.dsl.source.model.MethodMetaData; import org.gradle.build.docs.model.Attachable; import org.gradle.build.docs.model.ClassMetaDataRepository; import org.gradle.util.CollectionUtils; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ClassLinkMetaData implements Serializable, Attachable<ClassLinkMetaData> { private final String className; private final String simpleName; private final String packageName; private LinkMetaData.Style style; private final Map<String, MethodLinkMetaData> methods = new HashMap<String, MethodLinkMetaData>(); public ClassLinkMetaData(ClassMetaData classMetaData) { this.className = classMetaData.getClassName(); this.simpleName = classMetaData.getSimpleName(); this.packageName = classMetaData.getPackageName(); this.style = classMetaData.isGroovy() ? LinkMetaData.Style.Groovydoc : LinkMetaData.Style.Javadoc; for (MethodMetaData method : classMetaData.getDeclaredMethods()) { addMethod(method, style); } for (EnumConstantMetaData enumConstant : classMetaData.getEnumConstants()) { addEnumConstant(enumConstant, style); } } public LinkMetaData getClassLink() { return new LinkMetaData(style, simpleName, null); } public String getPackageName() { return packageName; } public LinkMetaData getMethod(String method) { MethodLinkMetaData methodMetaData = findMethod(method); String urlFragment = methodMetaData.getUrlFragment(className); String displayName = String.format("%s.%s", simpleName, methodMetaData.getDisplayName()); return new LinkMetaData(methodMetaData.style, displayName, urlFragment); } private MethodLinkMetaData findMethod(String method) { if (method.endsWith("...)")) { // Should reuse the link parsing stuff from JavadocLinkConverter instead method = method.substring(0, method.length() - 4) + "[])"; } MethodLinkMetaData metaData = methods.get(method); if (metaData != null) { return metaData; } List<MethodLinkMetaData> candidates = new ArrayList<MethodLinkMetaData>(); for (MethodLinkMetaData methodLinkMetaData : methods.values()) { if (methodLinkMetaData.name.equals(method)) { candidates.add(methodLinkMetaData); } } if (candidates.isEmpty()) { String message = String.format("No method '%s' found for class '%s'.", method, className); message += "\nThis problem may happen when some apilink from docbook template xmls refers to unknown method." + "\nExample: <apilink class=\"org.gradle.api.Project\" method=\"someMethodThatDoesNotExist\"/>"; throw new RuntimeException(message); } if (candidates.size() != 1) { String message = String.format("Found multiple methods called '%s' in class '%s'. Candidates: %s", method, className, CollectionUtils.join(", ", candidates)); message += "\nThis problem may happen when some apilink from docbook template xmls is incorrect. Example:" + "\nIncorrect: <apilink class=\"org.gradle.api.Project\" method=\"tarTree\"/>" + "\nCorrect: <apilink class=\"org.gradle.api.Project\" method=\"tarTree(Object)\"/>"; throw new RuntimeException(message); } return candidates.get(0); } public LinkMetaData.Style getStyle() { return style; } public void setStyle(LinkMetaData.Style style) { this.style = style; } public void addMethod(MethodMetaData method, LinkMetaData.Style style) { methods.put(method.getOverrideSignature(), new MethodLinkMetaData(method.getName(), method.getOverrideSignature(), style)); } public void addEnumConstant(EnumConstantMetaData enumConstant, LinkMetaData.Style style) { String name = enumConstant.getName(); methods.put(name, new EnumConstantLinkMetaData(name, style)); } public void addBlockMethod(MethodMetaData method) { methods.put(method.getOverrideSignature(), new BlockLinkMetaData(method.getName(), method.getOverrideSignature())); } public void addGetterMethod(String propertyName, MethodMetaData method) { methods.put(method.getOverrideSignature(), new GetterLinkMetaData(propertyName, method.getName(), method.getOverrideSignature())); } public void attach(ClassMetaDataRepository<ClassLinkMetaData> linkMetaDataClassMetaDataRepository) { } private static class MethodLinkMetaData implements Serializable { final String name; final String signature; final LinkMetaData.Style style; private MethodLinkMetaData(String name, String signature, LinkMetaData.Style style) { this.name = name; this.signature = signature; this.style = style; } public String getDisplayName() { return signature; } public String getUrlFragment(String className) { return style == LinkMetaData.Style.Dsldoc ? String.format("%s:%s", className, signature) : signature; } @Override public String toString() { return signature; } } private static class BlockLinkMetaData extends MethodLinkMetaData { private BlockLinkMetaData(String name, String signature) { super(name, signature, LinkMetaData.Style.Dsldoc); } @Override public String getDisplayName() { return String.format("%s{}", name); } } private static class GetterLinkMetaData extends MethodLinkMetaData { private final String propertyName; private GetterLinkMetaData(String propertyName, String methodName, String signature) { super(methodName, signature, LinkMetaData.Style.Dsldoc); this.propertyName = propertyName; } @Override public String getUrlFragment(String className) { return String.format("%s:%s", className, propertyName); } } private static class EnumConstantLinkMetaData extends MethodLinkMetaData { private EnumConstantLinkMetaData(String name, LinkMetaData.Style style) { super(name, name, style); } @Override public String getDisplayName() { return name; } } }