/*
* Copyright (C) 2011 University of Dundee & Open Microscopy Environment.
* All rights reserved.
*
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.formats;
import java.text.Collator;
import java.text.RuleBasedCollator;
import java.util.Comparator;
import java.util.Locale;
import com.esotericsoftware.kryo.serializers.FieldSerializer;
import ome.util.LSID;
import omero.model.DetectorSettings;
import omero.model.IObject;
import omero.model.LightPath;
import omero.model.ObjectiveSettings;
import omero.model.Pixels;
/**
* This comparator takes into account the OME-XML data model hierarchy
* and uses that to define equivalence.
*
* @author Chris Allan <callan at blackcat dot ca>
*
*/
public class OMEXMLModelComparator implements Comparator<LSID>
{
/**
* The collator that we use to alphabetically sort by class name
* within a given level of the OME-XML hierarchy.
*/
@FieldSerializer.Optional("OMEXmlModelComparator.stringComparator")
private RuleBasedCollator stringComparator =
(RuleBasedCollator) Collator.getInstance(Locale.ENGLISH);
public int compare(LSID x, LSID y)
{
// Handle identical LSIDs
if (x.equals(y))
{
return 0;
}
// Parse the LSID for hierarchical equivalence tests.
Class<? extends IObject> xClass = x.getJavaClass();
Class<? extends IObject> yClass = y.getJavaClass();
int[] xIndexes = x.getIndexes();
int[] yIndexes = y.getIndexes();
// Handle the null class (one or more unparsable internal
// references) case.
if (xClass == null || yClass == null)
{
return stringComparator.compare(x.toString(), y.toString());
}
// Assign values to the classes
int xVal = getValue(xClass, xIndexes.length);
int yVal = getValue(yClass, yIndexes.length);
int retval = xVal - yVal;
if (retval == 0)
{
// Handle different classes at the same level in the hierarchy
// by string difference. They need to still be different.
if (!xClass.equals(yClass))
{
return stringComparator.compare(x.toString(), y.toString());
}
// Handle the same classes at the same level in the hierarchy with
// differing numbers of indexes by string difference. They also
// need to still be different.
if (xIndexes.length != yIndexes.length)
{
return stringComparator.compare(x.toString(), y.toString());
}
for (int i = 0; i < xIndexes.length; i++)
{
int difference = xIndexes[i] - yIndexes[i];
if (difference != 0)
{
return difference;
}
}
return 0;
}
return retval;
}
/**
* Assigns a value to a particular class based on its location in the
* OME-XML hierarchy.
* @param klass Class to assign a value to.
* @param indexes Number of class indexes that were present in its LSID.
* @return The value.
*/
public int getValue(Class<? extends IObject> klass, int indexes)
{
// Top-level (Pixels is a special case due to Channel and
// LogicalChannel containership weirdness).
if (klass.equals(Pixels.class))
{
return 1;
}
if (klass.equals(ObjectiveSettings.class)
|| klass.equals(DetectorSettings.class)
|| klass.equals(LightPath.class))
{
return 3;
}
return indexes;
}
}