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     */
019    package org.apache.wiki.util;
020    
021    import java.util.AbstractList;
022    import 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     */
033    public class PriorityList<E>
034        extends AbstractList<E>
035    {
036        private CopyOnWriteArrayList<Item<E>> m_elements = new CopyOnWriteArrayList<Item<E>>();
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( E o, int priority )
052        {
053            int i = 0;
054    
055            for( ; i < m_elements.size(); i++ )
056            {
057                Item item = m_elements.get(i);
058    
059                if( item.m_priority < priority )
060                {
061                    break;
062                }
063            }
064    
065            Item<E> newItem = new Item<E>();
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        public boolean add( E o )
079        {
080            add( o, DEFAULT_PRIORITY );
081    
082            return true;
083        }
084    
085        /**
086         *  Returns the object at index "index".
087         *
088         *  @param index The index.
089         *  @return The object at the list at the position "index".
090         */
091        public E get( int index )
092        {
093            return m_elements.get( index ).m_object;
094        }
095    
096        /**
097         *  Returns the current size of the list.
098         *  
099         *  @return size of the list.
100         */
101        public int size()
102        {
103            return m_elements.size();
104        }
105    
106        /**
107         *  Provides a holder for the priority-object 2-tuple.
108         */
109        private static class Item<E>
110        {
111            public int     m_priority;
112            public E       m_object;
113        }
114    }