    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.apache.wiki.util;
    020
    021import java.util.AbstractList;
    022import java.util.concurrent.CopyOnWriteArrayList;
    023
    024/**
    025 *  Builds a simple, priority-based List implementation.  The list
    026 *  will be sorted according to the priority.  If two items are
    027 *  inserted with the same priority, their order is the insertion order - i.e. the new one
    028 *  is appended last in the insertion list.
    029 *  <p>
    030 *  Priority is an integer, and the list is sorted in descending order
    031 *  (that is, 100 is before 10 is before 0 is before -40).
    032 */
    033public class PriorityList<E>
    034    extends AbstractList<E>
    035{
    036    private final CopyOnWriteArrayList<Item<E>> m_elements = new CopyOnWriteArrayList<>();
    037
    038    /**
    039     *  This is the default priority, which is used if no priority
    040     *  is defined.  It's current value is zero.
    041     */
    042    public static final int DEFAULT_PRIORITY = 0;
    043
    044    /**
    045     *  Adds an object to its correct place in the list, using the
    046     *  given priority.
    047     *
    048     *  @param o Object to add.
    049     *  @param priority Priority.
    050     */
    051    public void add(final E o, final int priority )
    052    {
    053        int i = 0;
    054
    055        for( ; i < m_elements.size(); i++ )
    056        {
    057            final Item< E > item = m_elements.get(i);
    058
    059            if( item.m_priority < priority )
    060            {
    061                break;
    062            }
    063        }
    064
    065        final Item<E> newItem = new Item<>();
    066        newItem.m_priority = priority;
    067        newItem.m_object   = o;
    068
    069        m_elements.add( i, newItem );
    070    }
    071
    072    /**
    073     *  Adds an object using the default priority to the List.
    074     *
    075     *  @param o Object to add.
    076     *  @return true, as per the general Collections.add contract.
    077     */
    078    @Override
    079    public boolean add(final E o )
    080    {
    081        add( o, DEFAULT_PRIORITY );
    082
    083        return true;
    084    }
    085
    086    /**
    087     *  Returns the object at index "index".
    088     *
    089     *  @param index The index.
    090     *  @return The object at the list at the position "index".
    091     */
    092    @Override
    093    public E get(final int index )
    094    {
    095        return m_elements.get( index ).m_object;
    096    }
    097
    098    /**
    099     *  Returns the current size of the list.
    100     *
    101     *  @return size of the list.
    102     */
    103    @Override
    104    public int size()
    105    {
    106        return m_elements.size();
    107    }
    108
    109    /**
    110     *  Provides a holder for the priority-object 2-tuple.
    111     */
    112    private static class Item<E>
    113    {
    114        public int     m_priority;
    115        public E       m_object;
    116    }
    117}