/*
 * $Id: ComparatorFactory.java,v 1.4 2005/09/15 00:48:10 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: ComparatorFactory.java,v $
 * Revision 1.4  2005/09/15 00:48:10  marbobo
 * + Sprachabhängiges Sortieren implementiert
 *
 * Revision 1.3  2005/09/05 22:45:57  marbobo
 * + Neues Komparator hinzugefügt
 *
 * Revision 1.2  2005/09/05 13:52:49  marbobo
 * + Refactoring (Methode umbenannt)
 *
 * Revision 1.1  2005/02/15 09:26:46  bigmac
 * Refactorings
 *
 * Revision 1.5  2004/11/09 14:35:41  marbobo
 * + Umstellung von authorId auf publisherId
 * + Hinzufügen von AuthorName für Dokumente
 * + Nötwendige Änderungen betreffend AuthorName und PublisherId
 *
 * Revision 1.4  2004/09/23 13:23:45  marbobo
 * Neue Vergleichsfunktionen hinzugefügt
 *
 * Revision 1.3  2004/06/27 17:06:25  marbobo
 * + Quellcode maintenance
 *
 * Revision 1.2  2003/12/24 10:12:00  bigmac
 * Projektweite Import-Optimierung
 *
 * Revision 1.1  2003/08/18 21:11:43  marbobo
 * Package verschoben
 *
 * Revision 1.8  2003/08/02 16:55:23  bigmac
 * *** empty log message ***
 *
 * Revision 1.7  2003/07/28 12:37:31  marbobo
 * +Kommentierung von Methoden und des Quellcodes
 * -unnötige Imports entfernt
 *
 */
package vkc.util.sort;

import java.io.Serializable;
import java.text.CollationKey;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;

import vkc.db.entities.VKCGroup;
import vkc.db.entities.VKCUser;
import vkc.search.SearchResultEntry;
import vkc.util.VKCStringUtils;

/**
 * Komparator-Klasse zum Sortieren von Dokumenten (SearchResultEntry-Objekte),
 * von Benutzern (VKCUser-Objekte) und Gruppen (VKCGroup-Objekte)
 *
 * @author marbobo
 */
public final class ComparatorFactory implements Serializable {
    //~ Static fields/initializers ---------------------------------------------
	private static Collator collator = Collator.getInstance();
	
    private static Comparator searchResultAscendingByCreationDate = new Comparator() {
        public int compare(Object obj1, Object obj2) {
            SearchResultEntry result1 = null;

            if (obj1 instanceof SearchResultEntry) {
                result1 = (SearchResultEntry) obj1;
            } else {
                return -1;
            }

            SearchResultEntry result2 = null;

            if (obj2 instanceof SearchResultEntry) {
                result2 = (SearchResultEntry) obj2;
            } else {
                return -1;
            }

            if (result1.getCreationDate() != null && result2.getCreationDate() != null) {
                return  result1.getCreationDate().after(result2.getCreationDate()) ? 1 : 0;
            }
            
            return -1;
        }
    };

    private static Comparator searchResultDescendingByCreationDate = new Comparator() {
        public int compare(Object obj1, Object obj2) {
            SearchResultEntry result1 = null;

            if (obj1 instanceof SearchResultEntry) {
                result1 = (SearchResultEntry) obj1;
            } else {
                return -1;
            }

            SearchResultEntry result2 = null;

            if (obj2 instanceof SearchResultEntry) {
                result2 = (SearchResultEntry) obj2;
            } else {
                return -1;
            }

            if (result1.getCreationDate() != null && result2.getCreationDate() != null) {
                return result1.getCreationDate().before(result2.getCreationDate()) ? 1 : 0;
            }
            
            return -1;
        }
    };

    private static Comparator searchResultAscendingByPublishingDate = new Comparator() {
        public int compare(Object obj1, Object obj2) {
            SearchResultEntry result1 = null;

            if (obj1 instanceof SearchResultEntry) {
                result1 = (SearchResultEntry) obj1;
            } else {
                return -1;
            }

            SearchResultEntry result2 = null;

            if (obj2 instanceof SearchResultEntry) {
                result2 = (SearchResultEntry) obj2;
            } else {
                return -1;
            }

            return  result1.getPublished().after(result2.getPublished()) ? 1 : 0;
        }
    };

    private static Comparator searchResultDescendingByPublishingDate = new Comparator() {
        public int compare(Object obj1, Object obj2) {
            SearchResultEntry result1 = null;

            if (obj1 instanceof SearchResultEntry) {
                result1 = (SearchResultEntry) obj1;
            } else {
                return -1;
            }

            SearchResultEntry result2 = null;

            if (obj2 instanceof SearchResultEntry) {
                result2 = (SearchResultEntry) obj2;
            } else {
                return -1;
            }

            return result1.getPublished().before(result2.getPublished()) ? 1 : 0;
        }
    };

    private static Comparator searchResultAscendingByScore = new Comparator() {
        public int compare(Object obj1, Object obj2) {
            SearchResultEntry result1 = null;

            if (obj1 instanceof SearchResultEntry) {
                result1 = (SearchResultEntry) obj1;
            } else {
                return -1;
            }

            SearchResultEntry result2 = null;

            if (obj2 instanceof SearchResultEntry) {
                result2 = (SearchResultEntry) obj2;
            } else {
                return -1;
            }

            return result1.getScore() > result2.getScore() ? 1 : 0;
        }
    };

    private static Comparator searchResultDescendingByScore = new Comparator() {
        public int compare(Object obj1, Object obj2) {
            SearchResultEntry result1 = null;

            if (obj1 instanceof SearchResultEntry) {
                result1 = (SearchResultEntry) obj1;
            } else {
                return -1;
            }

            SearchResultEntry result2 = null;

            if (obj2 instanceof SearchResultEntry) {
                result2 = (SearchResultEntry) obj2;
            } else {
                return -1;
            }

            return result1.getScore() < result2.getScore() ? 1 : 0;
        }
    };

    private static Comparator searchResultAscendingBySize = new Comparator() {
        public int compare(Object obj1, Object obj2) {
            SearchResultEntry result1 = null;

            if (obj1 instanceof SearchResultEntry) {
                result1 = (SearchResultEntry) obj1;
            } else {
                return -1;
            }

            SearchResultEntry result2 = null;

            if (obj2 instanceof SearchResultEntry) {
                result2 = (SearchResultEntry) obj2;
            } else {
                return -1;
            }

            return Integer.parseInt(result1.getDocSize()) > Integer.parseInt(result2.getDocSize()) ? 1 : 0;
        }
    };

    private static Comparator searchResultDescendingBySize = new Comparator() {
        public int compare(Object obj1, Object obj2) {
            SearchResultEntry result1 = null;

            if (obj1 instanceof SearchResultEntry) {
                result1 = (SearchResultEntry) obj1;
            } else {
                return -1;
            }

            SearchResultEntry result2 = null;

            if (obj2 instanceof SearchResultEntry) {
                result2 = (SearchResultEntry) obj2;
            } else {
                return -1;
            }

            return Integer.parseInt(result1.getDocSize()) < Integer.parseInt(result2.getDocSize()) ? 1 : 0;
        }
    };

    //~ Constructors -----------------------------------------------------------

    /**
     * Creates a new ComparatorFactory object.
     */
    private ComparatorFactory() {
    }

    //~ Methods ----------------------------------------------------------------

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach AuthorNamen aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultAscendingByAuthor(Locale locale) {
        collator = Collator.getInstance(locale);
        
        Comparator searchResultAscendingByAuthor = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                SearchResultEntry result1 = null;

                if (obj1 instanceof SearchResultEntry) {
                    result1 = (SearchResultEntry) obj1;
                } else {
                    return -1;
                }

                SearchResultEntry result2 = null;

                if (obj2 instanceof SearchResultEntry) {
                    result2 = (SearchResultEntry) obj2;
                } else {
                    return -1;
                }

                if (result1.getAuthorName() != null && result2.getAuthorName() != null) {
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result1.getAuthorName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result2.getAuthorName()));
                	
                	return key1.compareTo(key2);
                } 

                return -1;
            }
        };

    	return searchResultAscendingByAuthor;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach AuthorNamen absteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultDescendingByAuthor(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator searchResultDescendingByAuthor = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                SearchResultEntry result1 = null;

                if (obj1 instanceof SearchResultEntry) {
                    result1 = (SearchResultEntry) obj1;
                } else {
                    return -1;
                }

                SearchResultEntry result2 = null;

                if (obj2 instanceof SearchResultEntry) {
                    result2 = (SearchResultEntry) obj2;
                } else {
                    return -1;
                }

                if (result1.getAuthorName() != null && result2.getAuthorName() != null) {
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result1.getAuthorName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result2.getAuthorName()));
                	
                	return key2.compareTo(key1);
                } 

                return -1;
            }
        };

        return searchResultDescendingByAuthor;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Herausgebernamen aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultAscendingByPublisher(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator searchResultAscendingByPublisher = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                SearchResultEntry result1 = null;

                if (obj1 instanceof SearchResultEntry) {
                    result1 = (SearchResultEntry) obj1;
                } else {
                    return -1;
                }

                SearchResultEntry result2 = null;

                if (obj2 instanceof SearchResultEntry) {
                    result2 = (SearchResultEntry) obj2;
                } else {
                    return -1;
                }

            	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result1.getPublisherName()));
            	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result2.getPublisherName()));
            	
            	return key1.compareTo(key2);
            }
        };

        return searchResultAscendingByPublisher;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Herausgebernamen absteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultDescendingByPublisher(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator searchResultDescendingByPublisher = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                SearchResultEntry result1 = null;

                if (obj1 instanceof SearchResultEntry) {
                    result1 = (SearchResultEntry) obj1;
                } else {
                    return -1;
                }

                SearchResultEntry result2 = null;

                if (obj2 instanceof SearchResultEntry) {
                    result2 = (SearchResultEntry) obj2;
                } else {
                    return -1;
                }

            	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result1.getPublisherName()));
            	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result2.getPublisherName()));
            	
            	return key2.compareTo(key1);
            }
        };

        return searchResultDescendingByPublisher;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Titel aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultAscendingByTitle(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator searchResultAscendingByTitle = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                SearchResultEntry result1 = null;

                if (obj1 instanceof SearchResultEntry) {
                    result1 = (SearchResultEntry) obj1;
                } else {
                    return -1;
                }

                SearchResultEntry result2 = null;

                if (obj2 instanceof SearchResultEntry) {
                    result2 = (SearchResultEntry) obj2;
                } else {
                    return -1;
                }

                if (result1.getTitle() != null && result2.getTitle() != null) {
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result1.getTitle()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result2.getTitle()));
                	
                	return key1.compareTo(key2);
                } 

                return -1;
            }
        };

        return searchResultAscendingByTitle;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Titel absteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultDescendingByTitle(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator searchResultDescendingByTitle = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                SearchResultEntry result1 = null;

                if (obj1 instanceof SearchResultEntry) {
                    result1 = (SearchResultEntry) obj1;
                } else {
                    return -1;
                }

                SearchResultEntry result2 = null;

                if (obj2 instanceof SearchResultEntry) {
                    result2 = (SearchResultEntry) obj2;
                } else {
                    return -1;
                }

                if (result1.getTitle() != null && result2.getTitle() != null) {
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result1.getTitle()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result2.getTitle()));
                	
                	return key2.compareTo(key1);
                } 

                return -1;
            }
        };

        return searchResultDescendingByTitle;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Dokumenttype aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultAscendingByType(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator searchResultAscendingByType = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                SearchResultEntry result1 = null;

                if (obj1 instanceof SearchResultEntry) {
                    result1 = (SearchResultEntry) obj1;
                } else {
                    return -1;
                }

                SearchResultEntry result2 = null;

                if (obj2 instanceof SearchResultEntry) {
                    result2 = (SearchResultEntry) obj2;
                } else {
                    return -1;
                }

                if (result1.getDocTypeName() != null && result2.getDocTypeName() != null) {
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result1.getDocTypeName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result2.getDocTypeName()));
                	
                	return key1.compareTo(key2);
                } 

                return -1;
            }
        };

        return searchResultAscendingByType;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Dokumenttype absteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultDescendingByType(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator searchResultDescendingByType = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                SearchResultEntry result1 = null;

                if (obj1 instanceof SearchResultEntry) {
                    result1 = (SearchResultEntry) obj1;
                } else {
                    return -1;
                }

                SearchResultEntry result2 = null;

                if (obj2 instanceof SearchResultEntry) {
                    result2 = (SearchResultEntry) obj2;
                } else {
                    return -1;
                }

                if (result1.getDocTypeName() != null && result2.getDocTypeName() != null) {
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result1.getDocTypeName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(result2.getDocTypeName()));
                	
                	return key2.compareTo(key1);
                } 

                return -1;
            }
        };

        return searchResultDescendingByType;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Erstellungsdatum aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultAscendingByCreationDate() {
        return searchResultAscendingByCreationDate;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Erstellungsdatum absteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultDescendingByCreationDate() {
        return searchResultDescendingByCreationDate;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Publikationsdatum aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultAscendingByPublishingDate() {
        return searchResultAscendingByPublishingDate;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Publikationsdatum absteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultDescendingByPublishingDate() {
        return searchResultDescendingByPublishingDate;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Ranking aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultAscendingByScore() {
        return searchResultAscendingByScore;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Ranking absteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultDescendingByScore() {
        return searchResultDescendingByScore;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Dokumentgröße aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultAscendingBySize() {
        return searchResultAscendingBySize;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse SearchResultEntry.
	 * Elemente werden nach Dokumentgröße absteigend sortiert.
	 * 
	 * @return
	 */
    public static Comparator getSearchResultDescendingBySize() {
        return searchResultDescendingBySize;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse VKCUser.
	 * Elemente werden nach Benutzernamen aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static final Comparator getUserComparatorByUsername(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator userComparatorByUsername = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                VKCUser user1  = null;

                if (obj1 instanceof VKCUser) {
                    user1 = (VKCUser) obj1;
                } else {
                    return -1;
                }

                VKCUser user2 = null;

                if (obj2 instanceof VKCUser) {
                    user2 = (VKCUser) obj2;
                } else {
                    return -1;
                }

            	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(user1.getUser()));
            	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(user2.getUser()));
            	
            	return key1.compareTo(key2);
            }
        };

        return userComparatorByUsername;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse VKCUser.
	 * Elemente werden nach Nachnamen aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static final Comparator getUserComparatorByLastname(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator userComparatorByLastname = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                VKCUser user1 = null;

                if (obj1 instanceof VKCUser) {
                    user1 = (VKCUser) obj1;
                } else {
                    return -1;
                }

                VKCUser user2 = null;

                if (obj2 instanceof VKCUser) {
                    user2 = (VKCUser) obj2;
                } else {
                    return -1;
                }

            	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(user1.getLastname()));
            	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(user2.getLastname()));
            	
            	return key1.compareTo(key2);
            }
        };

        return userComparatorByLastname;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse VKCUser.
	 * Elemente werden nach Vornamen aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static final Comparator getUserComparatorByFirstname(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator userComparatorByFirstname = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                VKCUser user1 = null;

                if (obj1 instanceof VKCUser) {
                    user1 = (VKCUser) obj1;
                } else {
                    return -1;
                }

                VKCUser user2 = null;

                if (obj2 instanceof VKCUser) {
                    user2 = (VKCUser) obj2;
                } else {
                    return -1;
                }

            	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(user1.getFirstname()));
            	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(user2.getFirstname()));
            	
            	return key1.compareTo(key2);
            }
        };

        return userComparatorByFirstname;
    }

	/**
	 * Vergleichsfunktion für Objekte der Klasse VKCGroup.
	 * Elemente werden nach Gruppennamen aufsteigend sortiert.
	 * 
	 * @return
	 */
    public static final Comparator getGroupComparatorByName(Locale locale) {
        collator = Collator.getInstance(locale);

        Comparator groupComparatorByName = new Comparator() {
            public int compare(Object obj1, Object obj2) {
                VKCGroup group1 = null;

                if (obj1 instanceof VKCGroup) {
                    group1 = (VKCGroup) obj1;
                } else {
                    return -1;
                }

                VKCGroup group2 = null;

                if (obj2 instanceof VKCGroup) {
                    group2 = (VKCGroup) obj2;
                } else {
                    return -1;
                }

            	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(group1.getName()));
            	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(group2.getName()));
            	
            	return key1.compareTo(key2);
            }
        };

        return groupComparatorByName;
    }
}