001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.javamoney.moneta.spi;
020
021import javax.annotation.Priority;
022import java.io.Serializable;
023import java.util.Comparator;
024
025/**
026 * Comparator implementation for ordering services loaded based on their increasing priority values.
027 */
028public class PriorityServiceComparator implements Comparator<Object>, Serializable {
029
030    private static final long serialVersionUID = 1L;
031
032    private static final PriorityServiceComparator INSTANCE = new PriorityServiceComparator();
033
034    /** Singleton constructor. */
035    private PriorityServiceComparator(){}
036
037    /**
038     * Get the shared instance of the comparator.
039     * @return the shared instance, never null.
040     */
041    public static PriorityServiceComparator getInstance(){
042        return INSTANCE;
043    }
044
045    @Override
046    public int compare(Object o1, Object o2) {
047        int prio = getPriority(o1) - getPriority(o2);
048        if (prio < 0) {
049            return 1;
050        } else if (prio > 0) {
051            return -1;
052        } else {
053            return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
054        }
055    }
056
057    /**
058     * Checks the given instance for a @Priority annotation. If present the annotation's value is evaluated. If no such
059     * annotation is present, a default priority {@code 1} is returned.
060     *
061     * @param o the instance, not {@code null}.
062     * @return a priority, by default 1.
063     */
064    public static int getPriority(Object o) {
065        return getPriority(o.getClass());
066    }
067
068    /**
069     * Checks the given type optionally annotated with a @Priority. If present the annotation's value is evaluated.
070     * If no such annotation is present, a default priority {@code 1} is returned.
071     *
072     * @param type the type, not {@code null}.
073     * @return a priority, by default 1.
074     */
075    @SuppressWarnings({ "rawtypes", "unchecked" })
076    public static int getPriority(Class type) {
077        int prio = 1;
078                Priority priority = (Priority)type.getAnnotation(Priority.class);
079        if (priority != null) {
080            prio = priority.value();
081        }
082        return prio;
083    }
084}