View Javadoc

1   /*
2    * Copyright 2007-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.exceptions.report.renderer.html;
17  
18  import static de.smartics.exceptions.report.utils.StringFunction.indexOfFirstWhiteSpace;
19  import static de.smartics.exceptions.report.utils.StringFunction.indexOfSecondWhiteSpace;
20  
21  import org.apache.commons.lang.StringUtils;
22  
23  import com.thoughtworks.qdox.model.DocletTag;
24  import com.thoughtworks.qdox.model.JavaAnnotatedElement;
25  import com.thoughtworks.qdox.model.JavaClass;
26  import com.thoughtworks.qdox.model.JavaField;
27  
28  /**
29   * Base implementation that renders the see, link and linkplain tags as HTML.
30   */
31  public abstract class AbstractHtmlLinkTagRenderer
32  {
33    // ********************************* Fields *********************************
34  
35    // --- constants ------------------------------------------------------------
36  
37    // --- members --------------------------------------------------------------
38  
39    /**
40     * The value of the flag is <code>true</code> if the text is written as is,
41     * <code>false</code> if it should be rendered in code font.
42     */
43    private final boolean plain;
44  
45    // ****************************** Initializer *******************************
46  
47    // ****************************** Constructors ******************************
48  
49    /**
50     * Default constructor.
51     *
52     * @param plain the value of the flag is <code>true</code> if the text is
53     *          written as is, <code>false</code> if it should be rendered in code
54     *          font.
55     */
56    protected AbstractHtmlLinkTagRenderer(final boolean plain)
57    {
58      this.plain = plain;
59    }
60  
61    // ****************************** Inner Classes *****************************
62  
63    // ********************************* Methods ********************************
64  
65    // --- init -----------------------------------------------------------------
66  
67    // --- get&set --------------------------------------------------------------
68  
69    // --- business -------------------------------------------------------------
70  
71    /**
72     * Renders the tag to the buffer.
73     *
74     * @param buffer the buffer to write to.
75     * @param tag the tag to render.
76     * @return a reference to the {@code buffer}.
77     */
78    public StringBuilder render(final StringBuilder buffer, final DocletTag tag)
79    {
80      final String label = getLabel(tag);
81  
82      final String linkTarget = calcLinkTarget(tag);
83      if (StringUtils.isBlank(label))
84      {
85        renderIntro(buffer, linkTarget);
86  
87        final JavaClass classDoc = Utils.referencedClass(tag);
88        if (classDoc != null)
89        {
90          buffer.append(classDoc.getName());
91        }
92        final String memberString = Utils.referencedMemberName(tag);
93        if (StringUtils.isNotBlank(memberString))
94        {
95          if (classDoc != null && !tag.getValue().startsWith("#"))
96          {
97            buffer.append('.');
98          }
99          buffer.append(memberString);
100       }
101 
102       renderExtro(buffer, linkTarget);
103     }
104     else
105     {
106       renderIntro(buffer, linkTarget);
107       buffer.append(label);
108       renderExtro(buffer, linkTarget);
109     }
110 
111     return buffer;
112   }
113 
114   private void renderIntro(final StringBuilder buffer, final String linkTarget)
115   {
116     if (!plain)
117     {
118       buffer.append("<code>");
119     }
120     if (linkTarget != null)
121     {
122       buffer.append("<a href=\"" + linkTarget + "\">");
123     }
124   }
125 
126   private void renderExtro(final StringBuilder buffer, final String linkTarget)
127   {
128     if (linkTarget != null)
129     {
130       buffer.append("</a>");
131     }
132     if (!plain)
133     {
134       buffer.append("</code>");
135     }
136   }
137 
138   private String calcLinkTarget(final DocletTag tag)
139   {
140     final String text = tag.getValue();
141     final String linkTarget;
142     final int length = text.length();
143     if (length > 1 && text.startsWith("#")) // NOPMD
144     {
145       final JavaAnnotatedElement context = tag.getContext();
146       if (context instanceof JavaField)
147       {
148         final JavaClass type = ((JavaField) context).getDeclaringClass();
149         final String fqn = type.getFullyQualifiedName();
150         final String id = getTarget(tag);
151         linkTarget = "#" + fqn + '_' + id;
152       }
153       else
154       {
155         linkTarget = null;
156       }
157     }
158     else if (length > 1 && text.contains("#"))
159     {
160       final JavaClass classDoc = Utils.referencedClass(tag);
161       if (classDoc != null && classDoc.isA("de.smartics.exceptions.core.Code"))
162       {
163         final String id = Utils.referencedMemberName(tag);
164         final String fqn = classDoc.getFullyQualifiedName();
165         linkTarget = "#" + fqn + '_' + id;
166       }
167       else
168       {
169         linkTarget = null;
170       }
171     }
172     else
173     {
174       linkTarget = null;
175     }
176     return linkTarget;
177   }
178 
179   private String getTarget(final DocletTag tag)
180   {
181     final String value = tag.getValue();
182 
183     final int index = indexOfFirstWhiteSpace(value);
184     final String target;
185     if (index != -1 && index + 1 < value.length())
186     {
187       target = value.substring(0, index);
188     }
189     else
190     {
191       target = value;
192     }
193     final String normalized = StringUtils.remove(target, '#');
194     return normalized;
195   }
196 
197   private String getLabel(final DocletTag tag)
198   {
199     final String value = tag.getValue();
200 
201     final int index = indexOfSecondWhiteSpace(value);
202     if (index != -1 && index + 1 < value.length())
203     {
204       final String label = value.substring(index + 1);
205       return label;
206     }
207     return null;
208   }
209 
210   // --- object basics --------------------------------------------------------
211 
212 }