001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019 020package org.apache.wiki; 021 022import java.util.Arrays; 023import java.util.Collections; 024import java.util.Comparator; 025import java.util.List; 026import java.util.Properties; 027 028import org.apache.log4j.Logger; 029import org.apache.wiki.util.ClassUtil; 030import org.apache.wiki.util.comparators.JavaNaturalComparator; 031 032/** 033 * Wrapper class for managing and using the PageNameComparator. 034 * <p> 035 * <b>Note</b> - this class is deliberately not null safe. Never call any of the 036 * methods with a null argument! 037 */ 038public class PageSorter implements Comparator 039{ 040 private static Logger log = Logger.getLogger( PageSorter.class ); 041 042 // The name of the property that specifies the desired page name comparator 043 protected static final String PROP_PAGE_NAME_COMPARATOR = "jspwiki.pageNameComparator.class"; 044 045 private Comparator<String> m_comparator; 046 047 /** 048 * Default constructor uses Java "natural" ordering. 049 */ 050 public PageSorter() 051 { 052 m_comparator = JavaNaturalComparator.DEFAULT_JAVA_COMPARATOR; 053 } 054 055 /** 056 * Construct with a particular comparator. 057 * 058 * @param comparator the Comparator to use 059 */ 060 public PageSorter( Comparator<String> comparator ) 061 { 062 m_comparator = comparator; 063 } 064 065 /** 066 * Compare two page names (Object version). Arguments must be either String 067 * or WikiPage. 068 * 069 * @throws IllegalArgumentException if incorrect argument types. 070 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) 071 */ 072 public int compare( Object o1, Object o2 ) 073 { 074 if( o1 instanceof String ) 075 { 076 if( o2 instanceof String ) 077 return m_comparator.compare( (String) o1, (String) o2 ); 078 if( o2 instanceof WikiPage ) 079 return m_comparator.compare( (String) o1, ((WikiPage) o2).getName() ); 080 } 081 else if( o1 instanceof WikiPage ) 082 { 083 if( o2 instanceof WikiPage ) 084 return m_comparator.compare( ((WikiPage) o1).getName(), ((WikiPage) o2).getName() ); 085 if( o2 instanceof String ) 086 return m_comparator.compare( ((WikiPage) o1).getName(), (String) o2 ); 087 } 088 089 throw new IllegalArgumentException( "Can only compare String or WikiPage" ); 090 } 091 092 /** 093 * Compare two page names (String version). 094 * 095 * @param pageName1 the first page name 096 * @param pageName2 the second page name 097 * @return see java.util.Comparator 098 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) 099 */ 100 public int compare( String pageName1, String pageName2 ) 101 { 102 return m_comparator.compare( pageName1, pageName2 ); 103 } 104 105 /** 106 * Compare two pages (WikiPage version). Compares them by name first. If the 107 * same name, compares their versions. 108 * 109 * @param page1 the first page 110 * @param page2 the second page 111 * @return see java.util.Comparator 112 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) 113 */ 114 public int compare( WikiPage page1, WikiPage page2 ) 115 { 116 if( page1 == page2 ) 117 return 0; // the same object 118 119 int res = m_comparator.compare( page1.getName(), page2.getName() ); 120 if( res == 0 ) 121 res = page1.getVersion() - page2.getVersion(); 122 return res; 123 } 124 125 @Override 126 public boolean equals( Object o ) 127 { 128 if( !(o instanceof PageSorter) ) 129 return false; // Definitely not equal 130 131 PageSorter that = (PageSorter) o; 132 if( this == that || m_comparator == that.m_comparator ) 133 return true; // Essentially the same object 134 return m_comparator.equals( that.m_comparator ); 135 } 136 137 /** 138 * Called by WikiEngine to initialise this instance. Tries to use class 139 * given by the PROP_PAGE_NAME_COMPARATOR property as the page name 140 * comparator. Uses a default comparator if this property is not set or 141 * there is any problem loading the specified class. 142 * 143 * @param props this WikiEngine's properties. 144 */ 145 @SuppressWarnings( "unchecked" ) 146 public void initialize( Properties props ) 147 { 148 // Default is Java natural order 149 m_comparator = JavaNaturalComparator.DEFAULT_JAVA_COMPARATOR; 150 String className = props.getProperty( PROP_PAGE_NAME_COMPARATOR ); 151 if( className != null && className.length() > 0 ) 152 try 153 { 154 m_comparator = (Comparator<String>) ClassUtil.findClass( "org.apache.wiki.util.comparators", className ) 155 .newInstance(); 156 } 157 catch( Exception e ) 158 { 159 log.error( "Falling back to default \"natural\" comparator", e ); 160 } 161 } 162 163 /** 164 * Sorts the specified list into ascending order based on the 165 * PageNameComparator. The actual sort is done using 166 * <code>Collections.sort()</code>. 167 * 168 * @param nameList the page names to be sorted 169 */ 170 public void sort( List<String> nameList ) 171 { 172 Collections.sort( nameList, m_comparator ); 173 } 174 175 /** 176 * Sorts the specified array into ascending order based on the 177 * PageNameComparator. The actual sort is done using 178 * <code>Arrays.sort()</code>. 179 * 180 * @param nameArray the page names to be sorted 181 */ 182 public void sort( String[] nameArray ) 183 { 184 Arrays.sort( nameArray, m_comparator ); 185 } 186 187 /** 188 * Sorts the specified list into ascending order based on the 189 * PageNameComparator. The actual sort is done using 190 * <code>Collections.sort()</code>. 191 * 192 * @param pageList the pages to be sorted 193 */ 194 @SuppressWarnings( "unchecked" ) 195 public void sortPages( List<Object> pageList ) 196 { 197 Collections.sort( pageList, this ); 198 } 199 200 /** 201 * Sorts the specified array into ascending order based on the 202 * PageNameComparator. The actual sort is done using 203 * <code>Arrays.sort()</code>. 204 * 205 * @param pageArray the pages to be sorted 206 */ 207 @SuppressWarnings( "unchecked" ) 208 public void sortPages( Object[] pageArray ) 209 { 210 Arrays.sort( pageArray, this ); 211 } 212}