001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.broker.region.cursors;
018
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.Iterator;
022import java.util.List;
023import java.util.Map;
024import org.apache.activemq.broker.region.MessageReference;
025import org.apache.activemq.command.MessageId;
026
027public class OrderedPendingList implements PendingList {
028    PendingNode root = null;
029    PendingNode tail = null;
030    final Map<MessageId, PendingNode> map = new HashMap<MessageId, PendingNode>();
031
032    public PendingNode addMessageFirst(MessageReference message) {
033        PendingNode node = new PendingNode(this, message);
034        if (root == null) {
035            root = node;
036            tail = node;
037        } else {
038            root.linkBefore(node);
039        }
040        this.map.put(message.getMessageId(), node);
041        return node;
042    }
043
044    public PendingNode addMessageLast(MessageReference message) {
045        PendingNode node = new PendingNode(this, message);
046        if (root == null) {
047            root = node;
048        } else {
049            tail.linkAfter(node);
050        }
051        tail = node;
052        this.map.put(message.getMessageId(), node);
053        return node;
054    }
055
056    public void clear() {
057        this.root = null;
058        this.tail = null;
059        this.map.clear();
060    }
061
062    public boolean isEmpty() {
063        return this.map.isEmpty();
064    }
065
066    public Iterator<MessageReference> iterator() {
067        return new Iterator<MessageReference>() {
068            private PendingNode current = null;
069            private PendingNode next = root;
070
071            public boolean hasNext() {
072                return next != null;
073            }
074
075            public MessageReference next() {
076                MessageReference result = null;
077                this.current = this.next;
078                result = this.current.getMessage();
079                this.next = (PendingNode) this.next.getNext();
080                return result;
081            }
082
083            public void remove() {
084                if (this.current != null && this.current.getMessage() != null) {
085                    map.remove(this.current.getMessage().getMessageId());
086                }
087                removeNode(this.current);
088            }
089        };
090    }
091
092    public void remove(MessageReference message) {
093        if (message != null) {
094            PendingNode node = this.map.remove(message.getMessageId());
095            removeNode(node);
096        }
097    }
098
099    public int size() {
100        return this.map.size();
101    }
102
103    void removeNode(PendingNode node) {
104        if (node != null) {
105            map.remove(node.getMessage().getMessageId());
106            if (root == node) {
107                root = (PendingNode) node.getNext();
108            }
109            if (tail == node) {
110                tail = (PendingNode) node.getPrevious();
111            }
112            node.unlink();
113        }
114    }
115
116    List<PendingNode> getAsList() {
117        List<PendingNode> result = new ArrayList<PendingNode>(size());
118        PendingNode node = root;
119        while (node != null) {
120            result.add(node);
121            node = (PendingNode) node.getNext();
122        }
123        return result;
124    }
125
126    @Override
127    public String toString() {
128        return "OrderedPendingList(" + System.identityHashCode(this) + ")";
129    }
130
131}