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
020 package org.apache.wiki;
021
022 import java.util.Arrays;
023 import java.util.Collections;
024 import java.util.Comparator;
025 import java.util.List;
026 import java.util.Properties;
027
028 import org.apache.log4j.Logger;
029 import org.apache.wiki.util.ClassUtil;
030 import 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 */
038 public 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 }