View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.tools.plugin.extractor.annotations.converter.tag;
20  
21  import java.util.Optional;
22  import java.util.function.UnaryOperator;
23  
24  import org.apache.maven.tools.plugin.extractor.annotations.converter.ConverterContext;
25  import org.apache.maven.tools.plugin.javadoc.FullyQualifiedJavadocReference;
26  import org.apache.maven.tools.plugin.javadoc.JavadocReference;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  /**
31   * Utility methods for dealing with links generated from Javadoc tags.
32   */
33  public class LinkUtils {
34  
35      private static final Logger LOG = LoggerFactory.getLogger(LinkUtils.class);
36  
37      private LinkUtils() {
38          // only static methods
39      }
40  
41      public static String createLink(String referenceValue, ConverterContext context) {
42          return createLink(referenceValue, context, UnaryOperator.identity());
43      }
44  
45      public static String createLink(
46              String referenceValue, ConverterContext context, UnaryOperator<String> labelDecorator) {
47          try {
48              JavadocReference reference = JavadocReference.parse(referenceValue);
49              FullyQualifiedJavadocReference fqReference = context.resolveReference(reference);
50              if (!context.canGetUrl()) {
51                  return getReferenceLabel(fqReference, context, labelDecorator, "no javadoc sites associated");
52              }
53              return createLink(referenceValue, fqReference, context, labelDecorator);
54          } catch (IllegalArgumentException e) {
55              LOG.warn(
56                      "Unresolvable link in javadoc tag with value {} found in {}: {}",
57                      referenceValue,
58                      context.getLocation(),
59                      e.getMessage());
60              return labelDecorator.apply(referenceValue) + "<!-- this link could not be resolved -->";
61          }
62      }
63  
64      private static String createLink(
65              String referenceValue,
66              FullyQualifiedJavadocReference fqReference,
67              ConverterContext context,
68              UnaryOperator<String> labelDecorator) {
69          StringBuilder link = new StringBuilder();
70          try {
71              link.append("<a href=\"");
72              link.append(context.getUrl(fqReference).toString());
73              link.append("\">");
74              String label = getReferenceLabel(fqReference, context);
75              label = labelDecorator.apply(label);
76              link.append(label);
77              link.append("</a>");
78          } catch (IllegalArgumentException e) {
79              LOG.warn(
80                      "Could not get javadoc URL for reference {} at {} (fully qualified {}): {}",
81                      referenceValue,
82                      fqReference,
83                      context.getLocation(),
84                      e.getMessage());
85              return getReferenceLabel(
86                      fqReference, context, labelDecorator, "reference not found in associated javadoc sites");
87          }
88          return link.toString();
89      }
90  
91      private static String getReferenceLabel(
92              FullyQualifiedJavadocReference fqReference,
93              ConverterContext context,
94              UnaryOperator<String> labelDecorator,
95              String htmlComment) {
96          String label = getReferenceLabel(fqReference, context);
97          return labelDecorator.apply(label) + "<!-- " + htmlComment + " -->";
98      }
99  
100     /**
101      * @return the undecorated label of the link
102      * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html#JSWOR656"> javadoc: How
103      *      a Name Appears</a>
104      */
105     private static String getReferenceLabel(FullyQualifiedJavadocReference fqReference, ConverterContext context) {
106         if (fqReference.getLabel().isPresent()) {
107             return fqReference.getLabel().get();
108         } else {
109             Optional<String> packageName;
110             Optional<String> moduleName;
111             Optional<String> className = fqReference.getClassName();
112             if (Optional.of(context.getPackageName()).equals(fqReference.getPackageName())
113                     && context.getModuleName().equals(fqReference.getModuleName())) {
114                 packageName = Optional.empty();
115                 moduleName = Optional.empty();
116                 if (context.isReferencedBy(fqReference)) {
117                     className = Optional.empty();
118                 }
119             } else {
120                 packageName = fqReference.getPackageName();
121                 moduleName = fqReference.getModuleName();
122             }
123             return createLabel(moduleName, packageName, className, fqReference.getMember());
124         }
125     }
126 
127     private static String createLabel(
128             Optional<String> moduleName,
129             Optional<String> packageName,
130             Optional<String> className,
131             Optional<String> member) {
132         StringBuilder sb = new StringBuilder();
133         if (packageName.isPresent() && !"java.lang".equals(packageName.get())) {
134             sb.append(packageName.get());
135         }
136         if (className.isPresent()) {
137             if (sb.length() > 0) {
138                 sb.append('.');
139             }
140             sb.append(className.get());
141         }
142         if (member.isPresent()) {
143             if (sb.length() > 0) {
144                 sb.append('.');
145             }
146             sb.append(member.get());
147         }
148         return sb.toString();
149     }
150 }