All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sakaiproject.content.impl.ContentHostingComparator Maven / Gradle / Ivy

There is a newer version: 23.3
Show newest version
/**********************************************************************************
 * $URL$
 * $Id$
 ***********************************************************************************
 *
 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 Sakai Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **********************************************************************************/

package org.sakaiproject.content.impl;

import java.math.BigInteger;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import org.sakaiproject.content.api.ContentCollection;
import org.sakaiproject.content.api.ContentResource;
import org.sakaiproject.entity.api.Entity;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.time.api.Time;

/**
 * 

* ContentHostingComparator can be used to sort stuff (collections, resources) from the content hosting service. *

*/ public class ContentHostingComparator implements Comparator { /** The property name used for the sort. */ String m_property = null; /** true if the sort is to be ascending (false for descending). */ boolean m_ascending = true; /** * true if we're using a sort which accounts for "mixed mode" names, like * 'slide1', 'slide2, ..., 'slide10', 'slide11', which would not sort as * expected under a strict lexicographical sort. */ boolean m_smart_sort = true; /** * That object is used to allow locale-sensitive ordering. */ private static final Collator collator = Collator.getInstance(); public ContentHostingComparator(String property, boolean ascending) { this(property, ascending, true); } /** * Construct. * * @param property * The property name used for the sort. * @param ascending * true if the sort is to be ascending (false for descending). */ public ContentHostingComparator(String property, boolean ascending, boolean is_smart) { m_property = property; m_ascending = ascending; m_smart_sort = is_smart; //sets the collator properties collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); collator.setStrength(Collator.PRIMARY); } // ContentHostingComparator /** * Compare these objects based on my property and ascending settings. Collections sort lower than Resources. * * @param o1 * The first object, ContentCollection or ContentResource * @param o2 * The second object, ContentCollection or ContentResource * @return The compare result: -1 if o1 < o2, 0 if they are equal, and 1 if o1 > o2 */ public int compare(Object o1, Object o2) { String property = m_property; // PROP_CONTENT_PRIORITY is special because it allows // intermixing folders and files. if(property.equals(ResourceProperties.PROP_CONTENT_PRIORITY)) { Entity entity1 = (Entity) o1; Entity entity2 = (Entity) o2; Integer rank1 = null; Integer rank2 = null; try { rank1 = new Integer(entity1.getProperties().getProperty(property)); } catch (NumberFormatException e) { /* ignore, rank1 will be null */ } try { rank2 = new Integer(entity2.getProperties().getProperty(property)); } catch (NumberFormatException e) { /* ignore, rank2 will be null */ } // Priorities can be null if a resource or collection was created before priorities were // introduced. Sort null priorities to the bottom. if (rank1 != null && rank2 != null) { return m_ascending ? rank1.compareTo(rank2) : rank2.compareTo(rank1); } if (rank1 != null) { return m_ascending ? -1 : 1; } if (rank2 != null) { return m_ascending ? 1 : -1; } // If priorities are null for both items, fall back to display name sort. property = ResourceProperties.PROP_DISPLAY_NAME; } // collections sort lower than resources if ((o1 instanceof ContentCollection) && (o2 instanceof ContentResource)) { return (m_ascending ? -1 : 1); } if ((o1 instanceof ContentResource) && (o2 instanceof ContentCollection)) { return (m_ascending ? 1 : -1); } if(property.equals(ResourceProperties.PROP_CONTENT_LENGTH) && o1 instanceof ContentCollection) { int size1 = ((ContentCollection) o1).getMemberCount(); int size2 = ((ContentCollection) o2).getMemberCount(); int rv = ((size1 < size2) ? -1 : ((size1 > size2) ? 1 : 0)); if (!m_ascending) rv = -rv; return rv; } // ok, they are both the same: resources or collections // try a numeric interpretation try { long l1 = ((Entity) o1).getProperties().getLongProperty(property); long l2 = ((Entity) o2).getProperties().getLongProperty(property); int rv = ((l1 < l2) ? -1 : ((l1 > l2) ? 1 : 0)); if (!m_ascending) rv = -rv; return rv; } catch (Exception ignore) { } // try a Time interpretation try { Time t1 = ((Entity) o1).getProperties().getTimeProperty(property); Time t2 = ((Entity) o2).getProperties().getTimeProperty(property); int rv = t1.compareTo(t2); if (!m_ascending) rv = -rv; return rv; } catch (Exception ignore) { } // do a formatted interpretation - case insensitive int rv = 0; if (m_smart_sort) { rv = compareLikeMacFinder( ((Entity) o1).getProperties().getPropertyFormatted(property), ((Entity) o2).getProperties().getPropertyFormatted(property)); } else { rv = ((Entity) o1).getProperties().getPropertyFormatted(property).compareTo (((Entity) o2).getProperties().getPropertyFormatted(property)); } return m_ascending ? rv : -rv; } // compare public int comparerLocalSensitive(String s1, String s2) { Collator c = Collator.getInstance(); c.setStrength(Collator.PRIMARY); return c.compare(s1, s2); } /** * this is public to enable testing?? * @param s1 * @param s2 * @return */ public int compareLikeMacFinder(String s1, String s2) { if (! (containsDigits(s1) || containsDigits(s2))) { return collator.compare(s1,s2); } /* * the strategy here is simple, but certainly not the fastest approach. Each string is * split into a number of components, each component being either a String or a * BigInteger. Then we iterate over the components. As we do this, we must be careful * to call compareTo only on "compatible" types, which here is defined in the simplest * way: identity. If the types aren't compatible, we toString() the components and * compare as Strings. * */ Comparable[] c1 = makeGroups(s1); Comparable[] c2 = makeGroups(s2); int i = 0; while (i < c1.length) { if (i >= c2.length) { return 1; } int v = 0; if (c1[i].getClass().getName().equals("java.lang.String") && c2[i].getClass().getName().equals("java.lang.String")) { v = collator.compare(c1[i].toString(),c2[i].toString()); } else if (c1[i].getClass().equals(c2[i].getClass())) { v = c1[i].compareTo(c2[i]); } else { v = collator.compare(c1[i].toString(),c2[i].toString()); } if (v != 0) { return v; } i++; } // here, c2 must be at least as long as c1 return (c2.length > c1.length) ? -1 : 0; } private boolean containsDigits(String s) { for (int i = 0; i < s.length(); i++) { if (Character.isDigit(s.charAt(i))) { return true; } } return false; } private Comparable[] makeGroups(String s) { List l = new ArrayList(); boolean isNumber = false; StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (sb.length() > 0) { char last = sb.charAt(sb.length()-1); if ((Character.isDigit(c) && Character.isDigit(last)) || (!Character.isDigit(c) && !Character.isDigit(last))) { } else { if (isNumber) { l.add(new BigInteger(sb.toString())); } else { l.add(sb.toString()); } sb.setLength(0); } } sb.append(c); isNumber = Character.isDigit(c); } if (sb.length() > 0) { if (isNumber) { l.add(new BigInteger(sb.toString())); } else { l.add(sb.toString()); } } Comparable[] cs = new Comparable[l.size()]; return l.toArray(cs); } public String toString() { return this.getClass().getName() + ": property(" + m_property + ") ascending(" + m_ascending + ")"; } } // ClassResourcesComparator




© 2015 - 2025 Weber Informatics LLC | Privacy Policy