class OrderManagerImpl implements OrderManager {

    @Override
    public synchronized int moveBelow(OrderParticipantKey participant, OrderParticipantKey reference)
    {
        if (!isManaged(participant) || !isManaged(reference))
        {
            LOGGER.error("Attempting to reorder unmanaged participants.");
            return -1;
        }

        if (Utilities.sameInstance(participant, reference))
        {
            LOGGER.error("Participant cannot be moved above itself.");
            return myParticipantToOrder.get(participant);
        }

        int currentOrder = myParticipantToOrder.get(participant);
        int referenceOrder = myParticipantToOrder.get(reference);

        if (referenceOrder == currentOrder + 1)
        {
            // The participant is already in the desired spot.
            return currentOrder;
        }
        removeParticipant(participant);

        int assignedOrder;
        TObjectIntMap<OrderParticipantKey> moved = new TObjectIntHashMap<>(Math.abs(referenceOrder - currentOrder));
        if (currentOrder < referenceOrder)
        {
            // Move the ones from currentOrder + 1 to referenceOrder - 1 down
            // one
            // and insert at referenceOrder - 1.
            for (int i = currentOrder + 1; i < referenceOrder; ++i)
            {
                if (myOrderToParticipants.containsKey(i))
                {
                    OrderParticipantKey move = myOrderToParticipants.get(i);
                    removeParticipant(move);
                    insertParticipant(move, i - 1);
                    moved.put(move, i - 1);
                }
            }

            assignedOrder = referenceOrder - 1;
        }
        else
        {
            // Move the ones from referenceOrder to currentOrder - 1 up one
            // and insert at referenceOrder
            for (int i = currentOrder - 1; i >= referenceOrder; --i)
            {
                if (myOrderToParticipants.containsKey(i))
                {
                    OrderParticipantKey move = myOrderToParticipants.get(i);
                    removeParticipant(move);
                    insertParticipant(move, i + 1);
                    moved.put(move, i + 1);
                }
            }
            assignedOrder = referenceOrder;
        }
        insertParticipant(participant, assignedOrder);
        moved.put(participant, assignedOrder);
        notifyParticipantChanged(moved, ParticipantChangeType.ORDER_CHANGED);

        saveOrders();

        return assignedOrder;
    }

    public  OrderManagerImpl(OrderManagerConfig config);
    public  OrderManagerImpl(String family, OrderCategory category, TIntObjectMap<OrderParticipantKey> participants);

}