Coverage Report - de.smartics.properties.utils.JavadocCommentHelper
 
Classes in this File Line Coverage Branch Coverage Complexity
JavadocCommentHelper
0%
0/64
0%
0/28
2.9
 
 1  
 /*
 2  
  * Copyright 2012-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.properties.utils;
 17  
 
 18  
 import java.util.Arrays;
 19  
 import java.util.HashSet;
 20  
 import java.util.Set;
 21  
 import java.util.regex.Matcher;
 22  
 import java.util.regex.Pattern;
 23  
 
 24  
 import org.apache.commons.lang.StringUtils;
 25  
 
 26  
 /**
 27  
  * Utilities to normalize Javadoc comments.
 28  
  */
 29  
 public final class JavadocCommentHelper
 30  
 {
 31  
   // ********************************* Fields *********************************
 32  
 
 33  
   // --- constants ------------------------------------------------------------
 34  
 
 35  
   /**
 36  
    * The pattern matches inline Javadoc tags. In group 1 is the text that is to
 37  
    * be used and surrounded with {@link #prefix1} and {@link #suffix1}, if there
 38  
    * is no match for group 2. If group 2 is present, the text is to be used
 39  
    * without prefix/suffix 2.
 40  
    */
 41  0
   private static final Pattern INLINE_PATTERN = Pattern.compile(
 42  
       "\\{@[\\w]+\\s*([#\\.\\w]+(\\([^)]*\\))?)\\s*([^}]+)?\\}",
 43  
       Pattern.MULTILINE);
 44  
 
 45  
   /**
 46  
    * The elements that are of type block.
 47  
    */
 48  0
   private static final Set<String> BLOCK_ELEMENTS = new HashSet<String>(
 49  
       Arrays.asList(new String[] { "address", "blockquote", "center", "del",
 50  
                                   "dir", "div", "dl", "fieldset", "form", "h1",
 51  
                                   "h2", "h3", "h4", "h5", "h5", "hr", "ins",
 52  
                                   "isindex", "menu", "noframes", "noscript",
 53  
                                   "ol", "p", "pre", "table", "ul" }));
 54  
 
 55  
   // --- members --------------------------------------------------------------
 56  
 
 57  
   /**
 58  
    * The prefix for group 1 match.
 59  
    */
 60  
   private final String prefix1;
 61  
 
 62  
   /**
 63  
    * The suffix for group 1 match.
 64  
    */
 65  
   private final String suffix1;
 66  
 
 67  
   /**
 68  
    * The prefix for group 2 match.
 69  
    */
 70  
   private final String prefix2;
 71  
 
 72  
   /**
 73  
    * The suffix for group 2 match.
 74  
    */
 75  
   private final String suffix2;
 76  
 
 77  
   // ****************************** Initializer *******************************
 78  
 
 79  
   // ****************************** Constructors ******************************
 80  
 
 81  
   /**
 82  
    * Default constructor.
 83  
    *
 84  
    * @param prefix1 the prefix for group 1 match.
 85  
    * @param suffix1 the suffix for group 1 match.
 86  
    * @param prefix2 the prefix for group 2 match.
 87  
    * @param suffix2 the suffix for group 2 match.
 88  
    */
 89  
   public JavadocCommentHelper(final String prefix1, final String suffix1,
 90  
       final String prefix2, final String suffix2)
 91  0
   {
 92  0
     this.prefix1 = prefix1;
 93  0
     this.suffix1 = suffix1;
 94  0
     this.prefix2 = prefix2;
 95  0
     this.suffix2 = suffix2;
 96  0
   }
 97  
 
 98  
   // ****************************** Inner Classes *****************************
 99  
 
 100  
   // ********************************* Methods ********************************
 101  
 
 102  
   // --- init -----------------------------------------------------------------
 103  
 
 104  
   // --- create ---------------------------------------------------------------
 105  
 
 106  
   /**
 107  
    * Creates a default helper for normalizing in an HTML context.
 108  
    *
 109  
    * @return the HTML version of the helper.
 110  
    */
 111  
   public static JavadocCommentHelper createHtml()
 112  
   {
 113  0
     return new JavadocCommentHelper("<tt>", "</tt>", "<i>", "</i>");
 114  
   }
 115  
 
 116  
   /**
 117  
    * Creates a default helper for normalizing in text context.
 118  
    *
 119  
    * @return the text version of the helper.
 120  
    */
 121  
   public static JavadocCommentHelper createText()
 122  
   {
 123  0
     return new JavadocCommentHelper("'", "'", "", "");
 124  
   }
 125  
 
 126  
   // --- get&set --------------------------------------------------------------
 127  
 
 128  
   // --- business -------------------------------------------------------------
 129  
 
 130  
   /**
 131  
    * Usually the first paragraph in a Javadoc comment is not tagged as a
 132  
    * paragraph to reduce the markup. This helper probes if the block tag is
 133  
    * present and if not adds it.
 134  
    *
 135  
    * @param fragment the javadoc fragment to check.
 136  
    * @return the cleaned fragment.
 137  
    */
 138  
   public String expandFirstBlock(final String fragment)
 139  
   {
 140  0
     if (StringUtils.isBlank(fragment))
 141  
     {
 142  0
       return fragment;
 143  
     }
 144  
 
 145  0
     final String norm = fragment.trim();
 146  0
     if (isStartingWithTag(norm))
 147  
     {
 148  0
       final String elementName = calcElementName(norm);
 149  0
       if (isBlockElement(elementName))
 150  
       {
 151  0
         final int index = norm.indexOf("</" + elementName);
 152  0
         return createBlock(norm, index);
 153  
       }
 154  0
     }
 155  
     else
 156  
     {
 157  0
       final int index = calcIndexOfFirstBlockElement(norm);
 158  0
       return createBlock(norm, index);
 159  
     }
 160  
 
 161  0
     return fragment;
 162  
   }
 163  
 
 164  
   private static int calcIndexOfFirstBlockElement(final String fragment)
 165  
   {
 166  0
     int index = Integer.MAX_VALUE;
 167  0
     for (final String elementName : BLOCK_ELEMENTS)
 168  
     {
 169  0
       final int currentIndex = fragment.indexOf('<' + elementName);
 170  0
       if (currentIndex != -1)
 171  
       {
 172  0
         index = Math.min(currentIndex, index);
 173  
       }
 174  0
     }
 175  
 
 176  0
     return index != Integer.MAX_VALUE ? index : -1;
 177  
   }
 178  
 
 179  
   private static String createBlock(final String fragment, final int index)
 180  
   {
 181  0
     if (index != -1)
 182  
     {
 183  0
       final String firstBlock = fragment.substring(0, index);
 184  0
       final String rest = fragment.substring(index);
 185  0
       return "<p>" + firstBlock + "</p>\n" + rest;
 186  
     }
 187  
     else
 188  
     {
 189  0
       return "<p>" + fragment + "</p>";
 190  
     }
 191  
   }
 192  
 
 193  
   private static boolean isStartingWithTag(final String fragment)
 194  
   {
 195  0
     return fragment.startsWith("<");
 196  
   }
 197  
 
 198  
   private static String calcElementName(final String fragment)
 199  
   {
 200  0
     final StringBuilder buffer = new StringBuilder();
 201  0
     final int end = fragment.length();
 202  0
     int i = 1;
 203  0
     while (i < end)
 204  
     {
 205  0
       final char ch = fragment.charAt(i++);
 206  0
       if (Character.isLetterOrDigit(ch))
 207  
       {
 208  0
         buffer.append(ch);
 209  
       }
 210  0
     }
 211  
 
 212  0
     final String name = buffer.toString();
 213  0
     return name;
 214  
   }
 215  
 
 216  
   private static boolean isBlockElement(final String elementName)
 217  
   {
 218  0
     return BLOCK_ELEMENTS.contains(elementName);
 219  
   }
 220  
 
 221  
   /**
 222  
    * Replaces Javadoc inline tags.
 223  
    *
 224  
    * @param fragment the fragment with inline tags.
 225  
    * @return the normalized fragment.
 226  
    */
 227  
   public String replaceJavadocInlines(final String fragment)
 228  
   {
 229  0
     if (StringUtils.isBlank(fragment))
 230  
     {
 231  0
       return fragment;
 232  
     }
 233  
 
 234  0
     final StringBuffer buffer = new StringBuffer(fragment.length());
 235  0
     final Matcher matcher = INLINE_PATTERN.matcher(fragment);
 236  
 
 237  0
     while (matcher.find())
 238  
     {
 239  0
       final String group2 = matcher.group(3);
 240  0
       if (group2 != null)
 241  
       {
 242  0
         final String replacement = prefix2 + group2 + suffix2;
 243  0
         matcher.appendReplacement(buffer, replacement);
 244  0
       }
 245  
       else
 246  
       {
 247  0
         String group1 = matcher.group(1);
 248  0
         if (group1.length() > 1 && group1.charAt(0) == '#')
 249  
         {
 250  0
           group1 = group1.substring(1);
 251  
         }
 252  0
         final String replacement = prefix1 + group1 + suffix1;
 253  0
         matcher.appendReplacement(buffer, replacement);
 254  
       }
 255  0
     }
 256  0
     matcher.appendTail(buffer);
 257  
 
 258  0
     return buffer.toString();
 259  
   }
 260  
 
 261  
   // --- object basics --------------------------------------------------------
 262  
 
 263  
 }