//# 0 errors, 99 messages
//#
package net.sourceforge.pebble.decorator;
    //#nofollowdecorator.java:1:1: class: net.sourceforge.pebble.decorator.NoFollowDecorator

import net.sourceforge.pebble.api.decorator.ContentDecoratorContext;
import net.sourceforge.pebble.domain.Comment;
import net.sourceforge.pebble.domain.TrackBack;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Adds a rel="nofollow" attribute into all links within comment
 * and TrackBack content.
 * 
 * @author Simon Brown
 */
public class NoFollowDecorator extends ContentDecoratorSupport {
    //#nofollowdecorator.java:16: method: void net.sourceforge.pebble.decorator.NoFollowDecorator.net.sourceforge.pebble.decorator.NoFollowDecorator()
    //#input(void net.sourceforge.pebble.decorator.NoFollowDecorator()): this
    //#nofollowdecorator.java:16: end of method: void net.sourceforge.pebble.decorator.NoFollowDecorator.net.sourceforge.pebble.decorator.NoFollowDecorator()

  /** the regex used to find HTML links */
  private static Pattern HTML_LINK_PATTERN = Pattern.compile("<a.*?href=.*?>", Pattern.CASE_INSENSITIVE);
    //#nofollowdecorator.java:19: method: net.sourceforge.pebble.decorator.NoFollowDecorator.net.sourceforge.pebble.decorator.NoFollowDecorator__static_init
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): HTML_LINK_PATTERN
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Descendant_Table[net/sourceforge/pebble/decorator/NoFollowDecorator]
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.addNoFollowLinks(Ljava/lang/String;)Ljava/lang/String;
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.decorate(Lnet/sourceforge/pebble/api/decorator/ContentDecoratorContext;Lnet/sourceforge/pebble/domain/BlogEntry;)V
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.decorate(Lnet/sourceforge/pebble/api/decorator/ContentDecoratorContext;Lnet/sourceforge/pebble/domain/Comment;)V
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.decorate(Lnet/sourceforge/pebble/api/decorator/ContentDecoratorContext;Lnet/sourceforge/pebble/domain/StaticPage;)V
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.decorate(Lnet/sourceforge/pebble/api/decorator/ContentDecoratorContext;Lnet/sourceforge/pebble/domain/TrackBack;)V
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.getBlog()Lnet/sourceforge/pebble/domain/Blog;
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.setBlog(Lnet/sourceforge/pebble/domain/Blog;)V
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): net/sourceforge/pebble/api/decorator/ContentDecorator.__Descendant_Table[net/sourceforge/pebble/decorator/NoFollowDecorator]
    //#output(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): net/sourceforge/pebble/decorator/ContentDecoratorSupport.__Descendant_Table[net/sourceforge/pebble/decorator/NoFollowDecorator]
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): init'ed(HTML_LINK_PATTERN)
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Descendant_Table[net/sourceforge/pebble/decorator/NoFollowDecorator] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): net/sourceforge/pebble/api/decorator/ContentDecorator.__Descendant_Table[net/sourceforge/pebble/decorator/NoFollowDecorator] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): net/sourceforge/pebble/decorator/ContentDecoratorSupport.__Descendant_Table[net/sourceforge/pebble/decorator/NoFollowDecorator] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.addNoFollowLinks(Ljava/lang/String;)Ljava/lang/String; == &addNoFollowLinks
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.decorate(Lnet/sourceforge/pebble/api/decorator/ContentDecoratorContext;Lnet/sourceforge/pebble/domain/BlogEntry;)V == &net/sourceforge/pebble/decorator/ContentDecoratorSupport.decorate
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.decorate(Lnet/sourceforge/pebble/api/decorator/ContentDecoratorContext;Lnet/sourceforge/pebble/domain/Comment;)V == &decorate
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.decorate(Lnet/sourceforge/pebble/api/decorator/ContentDecoratorContext;Lnet/sourceforge/pebble/domain/StaticPage;)V == &net/sourceforge/pebble/decorator/ContentDecoratorSupport.decorate
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.decorate(Lnet/sourceforge/pebble/api/decorator/ContentDecoratorContext;Lnet/sourceforge/pebble/domain/TrackBack;)V == &decorate
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.getBlog()Lnet/sourceforge/pebble/domain/Blog; == &net/sourceforge/pebble/decorator/ContentDecoratorSupport.getBlog
    //#post(net.sourceforge.pebble.decorator.NoFollowDecorator__static_init): __Dispatch_Table.setBlog(Lnet/sourceforge/pebble/domain/Blog;)V == &net/sourceforge/pebble/decorator/ContentDecoratorSupport.setBlog
    //#nofollowdecorator.java:19: end of method: net.sourceforge.pebble.decorator.NoFollowDecorator.net.sourceforge.pebble.decorator.NoFollowDecorator__static_init

  /**
   * Decorates the specified comment.
   *
   * @param context the context in which the decoration is running
   * @param comment the comment to be decorated
   */
  public void decorate(ContentDecoratorContext context, Comment comment) {
    comment.setBody(addNoFollowLinks(comment.getBody()));
    //#nofollowdecorator.java:28: method: void net.sourceforge.pebble.decorator.NoFollowDecorator.decorate(ContentDecoratorContext, Comment)
    //#input(void decorate(ContentDecoratorContext, Comment)): HTML_LINK_PATTERN
    //#input(void decorate(ContentDecoratorContext, Comment)): comment
    //#input(void decorate(ContentDecoratorContext, Comment)): comment.__Tag
    //#input(void decorate(ContentDecoratorContext, Comment)): comment.body
    //#input(void decorate(ContentDecoratorContext, Comment)): net/sourceforge/pebble/domain/Comment.__Descendant_Table[net/sourceforge/pebble/domain/Comment]
    //#input(void decorate(ContentDecoratorContext, Comment)): net/sourceforge/pebble/domain/Comment.__Descendant_Table[others]
    //#input(void decorate(ContentDecoratorContext, Comment)): net/sourceforge/pebble/domain/Comment.__Dispatch_Table.getBody()Ljava/lang/String;
    //#input(void decorate(ContentDecoratorContext, Comment)): net/sourceforge/pebble/domain/Comment.__Dispatch_Table.setBody(Ljava/lang/String;)V
    //#input(void decorate(ContentDecoratorContext, Comment)): this
    //#output(void decorate(ContentDecoratorContext, Comment)): comment.body
    //#pre[2] (void decorate(ContentDecoratorContext, Comment)): comment != null
    //#pre[3] (void decorate(ContentDecoratorContext, Comment)): comment.__Tag == net/sourceforge/pebble/domain/Comment
    //#pre[4] (void decorate(ContentDecoratorContext, Comment)): init'ed(comment.body)
    //#pre[1] (void decorate(ContentDecoratorContext, Comment)): (soft) HTML_LINK_PATTERN != null
    //#post(void decorate(ContentDecoratorContext, Comment)): init'ed(comment.body)
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.util.regex.Pattern:matcher
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.lang.StringBuffer
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.util.regex.Matcher:find
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.util.regex.Matcher:start
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.util.regex.Matcher:end
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.lang.StringBuffer:append
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.lang.String:indexOf
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void decorate(ContentDecoratorContext, Comment)): Effects-of-calling:java.lang.StringBuffer:toString
  }
    //#nofollowdecorator.java:29: end of method: void net.sourceforge.pebble.decorator.NoFollowDecorator.decorate(ContentDecoratorContext, Comment)

  /**
   * Decorates the specified TrackBack.
   *
   * @param context   the context in which the decoration is running
   * @param trackBack the TrackBack to be decorated
   */
  public void decorate(ContentDecoratorContext context, TrackBack trackBack) {
    trackBack.setExcerpt(addNoFollowLinks(trackBack.getExcerpt()));
    //#nofollowdecorator.java:38: method: void net.sourceforge.pebble.decorator.NoFollowDecorator.decorate(ContentDecoratorContext, TrackBack)
    //#input(void decorate(ContentDecoratorContext, TrackBack)): HTML_LINK_PATTERN
    //#input(void decorate(ContentDecoratorContext, TrackBack)): net/sourceforge/pebble/domain/TrackBack.__Descendant_Table[net/sourceforge/pebble/domain/TrackBack]
    //#input(void decorate(ContentDecoratorContext, TrackBack)): net/sourceforge/pebble/domain/TrackBack.__Descendant_Table[others]
    //#input(void decorate(ContentDecoratorContext, TrackBack)): net/sourceforge/pebble/domain/TrackBack.__Dispatch_Table.getExcerpt()Ljava/lang/String;
    //#input(void decorate(ContentDecoratorContext, TrackBack)): net/sourceforge/pebble/domain/TrackBack.__Dispatch_Table.setExcerpt(Ljava/lang/String;)V
    //#input(void decorate(ContentDecoratorContext, TrackBack)): this
    //#input(void decorate(ContentDecoratorContext, TrackBack)): trackBack
    //#input(void decorate(ContentDecoratorContext, TrackBack)): trackBack.__Tag
    //#input(void decorate(ContentDecoratorContext, TrackBack)): trackBack.excerpt
    //#output(void decorate(ContentDecoratorContext, TrackBack)): trackBack.excerpt
    //#pre[2] (void decorate(ContentDecoratorContext, TrackBack)): init'ed(trackBack.excerpt)
    //#pre[4] (void decorate(ContentDecoratorContext, TrackBack)): trackBack != null
    //#pre[5] (void decorate(ContentDecoratorContext, TrackBack)): trackBack.__Tag == net/sourceforge/pebble/domain/TrackBack
    //#pre[1] (void decorate(ContentDecoratorContext, TrackBack)): (soft) HTML_LINK_PATTERN != null
    //#post(void decorate(ContentDecoratorContext, TrackBack)): trackBack.excerpt != null
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.util.regex.Pattern:matcher
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.lang.StringBuffer
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.util.regex.Matcher:find
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.util.regex.Matcher:start
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.util.regex.Matcher:end
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.lang.StringBuffer:append
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.lang.String:indexOf
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void decorate(ContentDecoratorContext, TrackBack)): Effects-of-calling:java.lang.StringBuffer:toString
  }
    //#nofollowdecorator.java:39: end of method: void net.sourceforge.pebble.decorator.NoFollowDecorator.decorate(ContentDecoratorContext, TrackBack)

  /**
   * Adds rel="nofollow" links too any links in the specified string.
   *
   * @param   html    a String containing HTML
   * @return  the same String with rel="nofollow" in anchor tags
   */
  private String addNoFollowLinks(String html) {
    if (html == null || html.length() == 0) {
    //#nofollowdecorator.java:48: method: String net.sourceforge.pebble.decorator.NoFollowDecorator.addNoFollowLinks(String)
    //#input(String addNoFollowLinks(String)): HTML_LINK_PATTERN
    //#input(String addNoFollowLinks(String)): html
    //#output(String addNoFollowLinks(String)): return_value
    //#pre[1] (String addNoFollowLinks(String)): (soft) HTML_LINK_PATTERN != null
    //#presumption(String addNoFollowLinks(String)): java.lang.String:indexOf(...)@63 <= 4_294_967_290
    //#presumption(String addNoFollowLinks(String)): java.util.regex.Pattern:matcher(...)@52 != null
    //#post(String addNoFollowLinks(String)): init'ed(return_value)
    //#test_vector(String addNoFollowLinks(String)): html: Addr_Set{null}, Inverse{null}
    //#test_vector(String addNoFollowLinks(String)): java.lang.String:indexOf(...)@63: {-2_147_483_648..-2, 0..4_294_967_290}, {-1}
    //#test_vector(String addNoFollowLinks(String)): java.lang.String:indexOf(...)@72: {-2_147_483_648..-2, 0..4_294_967_295}, {-1}
    //#test_vector(String addNoFollowLinks(String)): java.lang.String:length(...)@48: {1..4_294_967_295}, {0}
    //#test_vector(String addNoFollowLinks(String)): java.util.regex.Matcher:find(...)@55: {1}, {0}
      return html;
    }

    Matcher m = HTML_LINK_PATTERN.matcher(html);
    StringBuffer buf = new StringBuffer();

    while (m.find()) {
      int start = m.start();
      int end = m.end();

      String link = html.substring(start, end);
      buf.append(html.substring(0, start));

      // add the nofollow, if necessary
      int startOfRelIndex = link.indexOf("rel=\"");
      if (startOfRelIndex == -1) {
        // no rel link, add one
        buf.append(link.substring(0, link.length() - 1));
        buf.append(" rel=\"nofollow\">");
      } else {
        int endOfRelIndex = link.indexOf("\"", startOfRelIndex+5);
        String rel = link.substring(startOfRelIndex+5, endOfRelIndex);
        rel = rel.toLowerCase();
        if (rel.indexOf("nofollow") == -1) {
          // rel exists, but without nofollow
          buf.append(link.substring(0, endOfRelIndex));
          buf.append(" nofollow");
          buf.append(link.substring(endOfRelIndex));
        } else {
          // nofollow exists
          buf.append(link);
        }
      }

      html = html.substring(end, html.length());
      m = HTML_LINK_PATTERN.matcher(html);
    }

    buf.append(html);

    return buf.toString();
    //#nofollowdecorator.java:89: end of method: String net.sourceforge.pebble.decorator.NoFollowDecorator.addNoFollowLinks(String)
  }

}
    //#nofollowdecorator.java:: end of class: net.sourceforge.pebble.decorator.NoFollowDecorator
