/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.service.importer.support.internal.util;
import java.io.Serializable;
import java.util.Comparator;
import org.eclipse.gemini.blueprint.service.importer.ImportedOsgiServiceProxy;
import org.eclipse.gemini.blueprint.util.OsgiServiceReferenceUtils;
import org.osgi.framework.ServiceReference;
/**
* Default comparator for sorted collections. It uses the service id property of an OSGi service to determine the order.
* Thus, by using this comparator, the services added to a collection will be sorted in the order in which they are
* published to the OSGi platform.
*
* <p/> This comparator version, provides <i>natural</i> ordering for service references for pre OSGI 4.1 platforms,
* using the contract from OSGi 4.1 spec:
*
* <blockquote> If this ServiceReference and the specified ServiceReference have the same service id they are equal.
* This ServiceReference is less than the specified ServiceReference if it has a lower service ranking and greater if it
* has a higher service ranking. Otherwise, if this ServiceReference and the specified ServiceReference have the same
* service ranking, this ServiceReference is less than the specified ServiceReference if it has a higher service id and
* greater if it has a lower service id. </blockquote>
*
* @see Comparator
* @author Costin Leau
*
*/
public class ServiceReferenceComparator implements Comparator, Serializable {
private static final long serialVersionUID = 7552328574956669890L;
private static final int hashCode = ServiceReferenceComparator.class.hashCode() * 13;
public int compare(Object o1, Object o2) {
ServiceReference ref1, ref2;
if (o1 == null || o2 == null) {
if (o1 == o2)
return 0;
else
throw new ClassCastException("Cannot compare null with a non-null object");
}
// look first for service references
if (o1 instanceof ServiceReference) {
ref1 = (ServiceReference) o1;
} else {
ImportedOsgiServiceProxy obj1 = (ImportedOsgiServiceProxy) o1;
ref1 = obj1.getServiceReference();
}
if (o2 instanceof ServiceReference) {
ref2 = (ServiceReference) o2;
} else {
ImportedOsgiServiceProxy obj2 = (ImportedOsgiServiceProxy) o2;
ref2 = obj2.getServiceReference();
}
return compare(ref1, ref2);
}
private int compare(ServiceReference ref1, ServiceReference ref2) {
// compare based on service ranking
int rank1 = OsgiServiceReferenceUtils.getServiceRanking(ref1);
int rank2 = OsgiServiceReferenceUtils.getServiceRanking(ref2);
int result = rank1 - rank2;
if (result == 0) {
long id1 = OsgiServiceReferenceUtils.getServiceId(ref1);
long id2 = OsgiServiceReferenceUtils.getServiceId(ref2);
// when comparing IDs, make sure to return inverse results (i.e. lower
// id, means higher service)
return (int) (id2 - id1);
}
return result;
}
public boolean equals(Object obj) {
return (this == obj || obj instanceof ServiceReferenceComparator);
}
public int hashCode() {
return hashCode;
}
}