/* Index ECM Engine - A system for managing the capture (when created
* or received), classification (cataloguing), storage, retrieval,
* revision, sharing, reuse and disposition of documents.
*
* Copyright (C) 2008 Regione Piemonte
* Copyright (C) 2008 Provincia di Torino
* Copyright (C) 2008 Comune di Torino
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package it.doqui.index.ecmengine.business.publishing.util;
import it.doqui.index.ecmengine.business.foundation.repository.NodeSvc;
import java.util.List;
import org.alfresco.service.namespace.QName;
/**
* Classe che implementa l'ordinamento mediante l'algoritmo di merge sort.
*
* @author Doqui
*/
@SuppressWarnings("unchecked")
public final class MergeSort extends Sort {
/**
* Costruttore predefinito.
*
* @param data L'oggetto {@code List} da ordinare.
* @param field {@code QName} della property su cui eseguire l'ordinamento.
* @param bForward true for a forward sort, false for a reverse sort
* @param mode Sort mode da utilizzare (case sensitive/case insensitive).
* @param nodeService Il {@code NodeSvc} da utilizzare nelle operazioni.
*/
public MergeSort(List data, QName field, boolean bForward, String mode,
NodeSvc nodeService) {
super(data, field, bForward, mode, nodeService);
}
/**
* Esecuzione dell'ordinamento.
*
* @see it.doqui.index.ecmengine.business.publishing.util.Sort#sort()
*/
public void sort() {
if (!this.data.isEmpty()) {
mergesort(this.data, 0, this.data.size() - 1);
}
}
/**
* Implementazione dell'algoritmo <i>merge sort</i>.
*
* <p>Implementazione originale disponibile all'URL:</p>
* <ul>
* <li><a href="http://www.cs.ubc.ca/spider/harrison/Java/MergeSortAlgorithm.java.html">
* http://www.cs.ubc.ca/spider/harrison/Java/MergeSortAlgorithm.java.html
* </a></li>
* </ul>
*
* <p>Rispetto alla versione originale:</p>
* <ul>
* <li>è stato implementato l'ordinamento inverso;</li>
* <li>l'algoritmo è stato reso stabile modificando le condizioni di spostamento degli elementi.</li>
* </ul>
*
* @param data La {@code List} di dati da orginare.
* @param lo0 L'estremo inferiore.
* @param hi0 L'estremo superiore.
*/
private void mergesort(final List data, int lo0, int hi0) {
int lo = lo0;
final int hi = hi0;
if (lo >= hi) {
return;
}
final int mid = (lo + hi) / 2;
mergesort(data, lo, mid);
mergesort(data, mid + 1, hi);
int endLo = mid;
int startHi = mid + 1;
while ((lo <= endLo) && (startHi <= hi)) {
if (bForward) {
// ASC order
// Versione originale:
// if (getComparator().compare(this.keys.get(lo), this.keys.get(start_hi)) < 0) {
if (getComparator().compare(this.keys.get(lo), this.keys.get(startHi)) <= 0) {
lo++;
} else {
final Object tmpKey = this.keys.get(startHi);
final Object tmpObj = this.data.get(startHi);
for (int k = startHi - 1; k >= lo; k--) {
this.keys.set(k + 1, this.keys.get(k));
this.data.set(k + 1, this.data.get(k));
}
this.keys.set(lo, tmpKey);
this.data.set(lo, tmpObj);
lo++;
endLo++;
startHi++;
}
} else {
// DESC order
if (getComparator().compare(this.keys.get(lo), this.keys.get(startHi)) >= 0) {
lo++;
} else {
final Object tmpKey = this.keys.get(startHi);
final Object tmpObj = this.data.get(startHi);
for (int k = startHi - 1; k >= lo; k--) {
this.keys.set(k + 1, this.keys.get(k));
this.data.set(k + 1, this.data.get(k));
}
this.keys.set(lo, tmpKey);
this.data.set(lo, tmpObj);
lo++;
endLo++;
startHi++;
}
}
}
}
}