File Source: latin1seopermalinkprovider.java

     1  package net.sourceforge.pebble.permalink;
     2  
     3  import net.sourceforge.pebble.api.permalink.PermalinkProvider;
     4  import net.sourceforge.pebble.domain.*;
     5  
     6  import java.text.SimpleDateFormat;
     7  import java.util.HashMap;
     8  import java.util.Iterator;
     9  import java.util.List;
    10  
    11  /**
    12   * Generates permalinks based upon the blog entry title. This implementation
    13   * retains characters from the latin1 character by converting
    14   * them to suitable "url-friendly" counterparts.
    15   *
    16   * It also uses dashes instead of underscores for whitespace as this is
    17   * what Google recommends.
    18  
    19   * For titles without characters from the latin1 character set
    20   * the blog entry ID is used for the permalink instead.
    21   *
    22   * @author Mattias Reichel
    23   */
         /* 
    P/P   *  Method: void net.sourceforge.pebble.permalink.Latin1SeoPermalinkProvider()
          */
    24  public class Latin1SeoPermalinkProvider implements PermalinkProvider {
    25  
    26      /** the regex used to check for a day request */
    27      private static final String DAY_PERMALINK_REGEX = "/\\d\\d\\d\\d/\\d\\d/\\d\\d";
    28  
    29      /** the regex used to check for a monthly blog request */
    30      private static final String MONTH_PERMALINK_REGEX = "/\\d\\d\\d\\d/\\d\\d";
    31  
    32      /** the regex used to check for a blog entry permalink */
    33      private static final String BLOG_ENTRY_PERMALINK_REGEX = "/[\\w-]*";
    34  
    35      /** the Blog associated with this provider instance */
    36      private Blog blog;
    37  
    38      /**
    39       * Gets the blog associated with this provider instance.
    40       *
    41       * @return  a Blog instance
    42       */
    43      public Blog getBlog() {
               /* 
    P/P         *  Method: Blog getBlog()
                * 
                *  Preconditions:
                *    init'ed(this.blog)
                * 
                *  Postconditions:
                *    return_value == this.blog
                *    init'ed(return_value)
                */
    44        return this.blog;
    45      }
    46  
    47      /**
    48       * Sets the blog associated with this provider instance.
    49       *
    50       * @param blog    a Blog instance
    51       */
    52      public void setBlog(Blog blog) {
               /* 
    P/P         *  Method: void setBlog(Blog)
                * 
                *  Postconditions:
                *    this.blog == blog
                *    init'ed(this.blog)
                */
    53        this.blog = blog;
    54      }
    55  
    56      /**
    57       * Gets the permalink for a blog entry.
    58       *
    59       * @return  a URI as a String
    60       */
    61      public synchronized String getPermalink(BlogEntry blogEntry) {
                 /* 
    P/P           *  Method: String getPermalink(BlogEntry)
                  * 
                  *  Presumptions:
                  *    net.sourceforge.pebble.domain.Blog:getBlogEntries(...)@66 != null
                  *    net.sourceforge.pebble.domain.BlogEntry:getTitle(...)@62 != null
                  *    net.sourceforge.pebble.domain.BlogEntry:getTitle(...)@71 != null
                  *    net.sourceforge.pebble.domain.BlogService:getBlogEntry(...)@70 != null
                  * 
                  *  Preconditions:
                  *    blogEntry != null
                  *    (soft) this.blog != null
                  * 
                  *  Presumptions:
                  *    java.util.List:get(...)@70 != null
                  *    java.util.List:indexOf(...)@68 - java.util.List:size(...)@68 in -232..6_442_450_942
                  *    java.util.List:size(...)@68 >= -231+1
                  * 
                  *  Postconditions:
                  *    return_value != null
                  * 
                  *  Test Vectors:
                  *    net.sourceforge.pebble.domain.BlogEntry:getTitle(...)@62: Addr_Set{null}, Inverse{null}
                  *    java.lang.String:equals(...)@71: {0}, {1}
                  *    java.lang.String:length(...)@62: {1..232-1}, {0}
                  */
    62          if (blogEntry.getTitle() == null || blogEntry.getTitle().length() == 0) {
    63              return buildPermalink(blogEntry);
    64          } else {
    65              BlogService service = new BlogService();
    66              List entries = getBlog().getBlogEntries();
    67              int count = 0;
    68              for (int i = entries.size() - 1; i > entries.indexOf(blogEntry.getId()); i--) {
    69                  try {
    70                      BlogEntry entry = service.getBlogEntry(getBlog(), "" + ((BlogEntry)entries.get(i)).getId());
    71                      if (entry.getTitle().equals(blogEntry.getTitle())) {
    72                          count++;
    73                      }
    74                  } catch (BlogServiceException e) {
    75                      // do nothing
    76                  }
    77              }
    78  
    79              if (count == 1) {
    80                  return buildPermalink(blogEntry);
    81              } else {
    82                  return buildPermalink(blogEntry) + "_" + blogEntry.getId();
    83              }
    84          }
    85      }
    86  
    87      private String buildPermalink(BlogEntry blogEntry) {
                 /* 
    P/P           *  Method: String buildPermalink(BlogEntry)
                  * 
                  *  Test Vectors:
                  *    net.sourceforge.pebble.domain.BlogEntry:getTitle(...)@88: Addr_Set{null}, Inverse{null}
                  * 
                  *  Preconditions:
                  *    blogEntry != null
                  * 
                  *  Postconditions:
                  *    return_value != null
                  * 
                  *  Test Vectors:
                  *    java.lang.String:length(...)@104: {1..232-1}, {0}
                  *    java.lang.String:length(...)@89: {1..232-1}, {0}
                  *    java.util.Iterator:hasNext(...)@94: {1}, {0}
                  */
    88          String title = blogEntry.getTitle();
    89          if (title == null || title.length() == 0) {
    90              title = "" + blogEntry.getId();
    91          } else {
    92              title = title.toLowerCase();
    93              title = title.replaceAll("[\\. ,;/\\\\_]", "-"); // Change whitespace and punctuation marks to dashes
    94              for(String search : characterSubstitutions.keySet()) {
    95                  title = title.replaceAll(search, characterSubstitutions.get(search));
    96              }
    97              title = title.replaceAll("[^a-z0-9-]", "");
    98              title = title.replaceAll("-+", "-");
    99              title = title.replaceAll("^-*", "");
   100              title = title.replaceAll("-*$", "");
   101          }
   102  
   103          // if the title has been blanked out, use the blog entry instead
   104          if (title == null || title.length() == 0) {
   105              title = "" + blogEntry.getId();
   106          }
   107  
   108          return "/" + title;
   109      }
   110  
   111  
   112      public boolean isBlogEntryPermalink(String uri) {
                 /* 
    P/P           *  Method: bool isBlogEntryPermalink(String)
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    uri: Addr_Set{null}, Inverse{null}
                  */
   113          if(uri != null) {
   114              return uri.matches(BLOG_ENTRY_PERMALINK_REGEX);
   115          } else {
   116              return false;
   117          }
   118      }
   119  
   120      public BlogEntry getBlogEntry(String uri) {
                 /* 
    P/P           *  Method: BlogEntry getBlogEntry(String)
                  * 
                  *  Presumptions:
                  *    net.sourceforge.pebble.domain.Blog:getBlogEntries(...)@122 != null
                  *    net.sourceforge.pebble.domain.BlogEntry:getLocalPermalink(...)@128 != null
                  *    net.sourceforge.pebble.domain.BlogService:getBlogEntry(...)@125 != null
                  * 
                  *  Preconditions:
                  *    this.blog != null
                  * 
                  *  Presumptions:
                  *    java.util.Iterator:next(...)@125 != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    java.lang.String:endsWith(...)@128: {0}, {1}
                  *    java.util.Iterator:hasNext(...)@123: {1}, {0}
                  */
   121          BlogService service = new BlogService();
   122          Iterator it = getBlog().getBlogEntries().iterator();
   123          while(it.hasNext()) {
   124              try {
   125                  BlogEntry blogEntry = service.getBlogEntry(getBlog(), "" + ((BlogEntry)it.next()).getId());
   126                  // use the local permalink, just in case the entry has been aggregated
   127                  // and an original permalink assigned
   128                  if (blogEntry.getLocalPermalink().endsWith(uri)) {
   129                      return blogEntry;
   130                  }
   131              } catch (BlogServiceException e) {
   132                  // do nothing
   133              }
   134          }
   135  
   136          return null;
   137      }
   138  
   139      /**
   140       * Gets the permalink for a monthly blog.
   141       *
   142       * @param month a Month instance
   143       * @return a URI as a String
   144       */
   145      public String getPermalink(Month month) {
               /* 
    P/P         *  Method: String getPermalink(Month)
                * 
                *  Preconditions:
                *    month != null
                *    this.blog != null
                * 
                *  Postconditions:
                *    init'ed(return_value)
                */
   146        SimpleDateFormat format = new SimpleDateFormat("'/'yyyy'/'MM");
   147        format.setTimeZone(blog.getTimeZone());
   148        return format.format(month.getDate());
   149      }
   150  
   151      /**
   152       * Determines whether the specified URI is a monthly blog permalink.
   153       *
   154       * @param uri   a relative URI
   155       * @return      true if the URI represents a permalink to a monthly blog,
   156       *              false otherwise
   157       */
   158      public boolean isMonthPermalink(String uri) {
               /* 
    P/P         *  Method: bool isMonthPermalink(String)
                * 
                *  Postconditions:
                *    init'ed(return_value)
                * 
                *  Test Vectors:
                *    uri: Addr_Set{null}, Inverse{null}
                */
   159        if (uri != null) {
   160          return uri.matches(MONTH_PERMALINK_REGEX);
   161        } else {
   162          return false;
   163        }
   164      }
   165  
   166      /**
   167       * Gets the monthly blog referred to by the specified URI.
   168       *
   169       * @param uri   a relative URI
   170       * @return  a Month instance, or null if one can't be found
   171       */
   172      public Month getMonth(String uri) {
               /* 
    P/P         *  Method: Month getMonth(String)
                * 
                *  Postconditions:
                *    init'ed(return_value)
                * 
                *  Preconditions:
                *    this.blog != null
                *    uri != null
                */
   173        String year = uri.substring(1, 5);
   174        String month = uri.substring(6, 8);
   175  
   176        return getBlog().getBlogForMonth(Integer.parseInt(year), Integer.parseInt(month));
   177      }
   178  
   179      /**
   180       * Gets the permalink for a day.
   181       *
   182       * @param day a Day instance
   183       * @return a URI as a String
   184       */
   185      public String getPermalink(Day day) {
               /* 
    P/P         *  Method: String getPermalink(Day)
                * 
                *  Preconditions:
                *    day != null
                *    this.blog != null
                * 
                *  Postconditions:
                *    init'ed(return_value)
                */
   186        SimpleDateFormat format = new SimpleDateFormat("'/'yyyy'/'MM'/'dd");
   187        format.setTimeZone(blog.getTimeZone());
   188        return format.format(day.getDate());
   189      }
   190  
   191      /**
   192       * Determines whether the specified URI is a day permalink.
   193       *
   194       * @param uri   a relative URI
   195       * @return      true if the URI represents a permalink to a day,
   196       *              false otherwise
   197       */
   198      public boolean isDayPermalink(String uri) {
               /* 
    P/P         *  Method: bool isDayPermalink(String)
                * 
                *  Postconditions:
                *    init'ed(return_value)
                * 
                *  Test Vectors:
                *    uri: Addr_Set{null}, Inverse{null}
                */
   199        if (uri != null) {
   200          return uri.matches(DAY_PERMALINK_REGEX);
   201        } else {
   202          return false;
   203        }
   204      }
   205  
   206      /**
   207       * Gets the day referred to by the specified URI.
   208       *
   209       * @param uri   a relative URI
   210       * @return  a Day instance, or null if one can't be found
   211       */
   212      public Day getDay(String uri) {
               /* 
    P/P         *  Method: Day getDay(String)
                * 
                *  Postconditions:
                *    init'ed(return_value)
                * 
                *  Preconditions:
                *    this.blog != null
                *    uri != null
                */
   213        String year = uri.substring(1, 5);
   214        String month = uri.substring(6, 8);
   215        String day = uri.substring(9, 11);
   216  
   217        return getBlog().getBlogForDay(Integer.parseInt(year),
   218           Integer.parseInt(month), Integer.parseInt(day));
   219      }
   220  
   221  
   222      /** the List of characters that will be substituted */
   223      private static final HashMap<String,String> characterSubstitutions;
   224      static {
   225  
                 /* 
    P/P           *  Method: net.sourceforge.pebble.permalink.Latin1SeoPermalinkProvider__static_init
                  * 
                  *  Postconditions:
                  *    characterSubstitutions == &new HashMap(Latin1SeoPermalinkProvider__static_init#1)
                  *    new HashMap(Latin1SeoPermalinkProvider__static_init#1) num objects == 1
                  */
   226          characterSubstitutions = new HashMap<String,String>();
   227  
   228          characterSubstitutions.put("\u00B2", "2");
   229          characterSubstitutions.put("\u00B3", "3");
   230  
   231          characterSubstitutions.put("\u00C0", "A");
   232          characterSubstitutions.put("\u00C1", "A");
   233          characterSubstitutions.put("\u00C2", "A");
   234          characterSubstitutions.put("\u00C3", "A");
   235          characterSubstitutions.put("\u00C4", "A");
   236          characterSubstitutions.put("\u00C5", "A");
   237          characterSubstitutions.put("\u00C6", "AE");
   238          characterSubstitutions.put("\u00C7", "C");
   239          characterSubstitutions.put("\u00C8", "E");
   240          characterSubstitutions.put("\u00C9", "E");
   241          characterSubstitutions.put("\u00CA", "E");
   242          characterSubstitutions.put("\u00CB", "E");
   243          characterSubstitutions.put("\u00CC", "I");
   244          characterSubstitutions.put("\u00CD", "I");
   245          characterSubstitutions.put("\u00CE", "I");
   246          characterSubstitutions.put("\u00CF", "I");
   247  
   248          characterSubstitutions.put("\u00D0", "D");
   249          characterSubstitutions.put("\u00D1", "N");
   250          characterSubstitutions.put("\u00D2", "O");
   251          characterSubstitutions.put("\u00D3", "O");
   252          characterSubstitutions.put("\u00D4", "O");
   253          characterSubstitutions.put("\u00D5", "O");
   254          characterSubstitutions.put("\u00D6", "O");
   255          characterSubstitutions.put("\u00D7", "x");
   256          characterSubstitutions.put("\u00D8", "O");
   257          characterSubstitutions.put("\u00D9", "U");
   258          characterSubstitutions.put("\u00DA", "U");
   259          characterSubstitutions.put("\u00DB", "U");
   260          characterSubstitutions.put("\u00DC", "U");
   261          characterSubstitutions.put("\u00DD", "Y");
   262          characterSubstitutions.put("\u00DE", "P");
   263          characterSubstitutions.put("\u00DF", "ss");
   264  
   265          characterSubstitutions.put("\u00E0", "a");
   266          characterSubstitutions.put("\u00E1", "a");
   267          characterSubstitutions.put("\u00E2", "a");
   268          characterSubstitutions.put("\u00E3", "a");
   269          characterSubstitutions.put("\u00E4", "a");
   270          characterSubstitutions.put("\u00E5", "a");
   271          characterSubstitutions.put("\u00E6", "ae");
   272          characterSubstitutions.put("\u00E7", "c");
   273          characterSubstitutions.put("\u00E8", "e");
   274          characterSubstitutions.put("\u00E9", "e");
   275          characterSubstitutions.put("\u00EA", "e");
   276          characterSubstitutions.put("\u00EB", "e");
   277          characterSubstitutions.put("\u00EC", "i");
   278          characterSubstitutions.put("\u00ED", "i");
   279          characterSubstitutions.put("\u00EE", "i");
   280          characterSubstitutions.put("\u00EF", "i");
   281  
   282          characterSubstitutions.put("\u00F0", "d");
   283          characterSubstitutions.put("\u00F1", "n");
   284          characterSubstitutions.put("\u00F2", "o");
   285          characterSubstitutions.put("\u00F3", "o");
   286          characterSubstitutions.put("\u00F4", "o");
   287          characterSubstitutions.put("\u00F5", "o");
   288          characterSubstitutions.put("\u00F6", "o");
   289          //"\u00F7", // division sign (ignore)
   290          characterSubstitutions.put("\u00F8", "o");
   291          characterSubstitutions.put("\u00F9", "u");
   292          characterSubstitutions.put("\u00FA", "u");
   293          characterSubstitutions.put("\u00FB", "u");
   294          characterSubstitutions.put("\u00FC", "u");
   295          characterSubstitutions.put("\u00FD", "y");
   296          characterSubstitutions.put("\u00FE", "p");
   297          characterSubstitutions.put("\u00FF", "y");
   298      }
   299  }








SofCheck Inspector Build Version : 2.22510
latin1seopermalinkprovider.java 2010-Jun-25 19:40:32
latin1seopermalinkprovider.class 2010-Jul-19 20:23:38