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.Collection;
021import java.util.HashMap;
022import java.util.Iterator;
023import java.util.List;
024import java.util.Map;
025import org.apache.activemq.broker.region.MessageReference;
026import org.apache.activemq.command.MessageId;
027
028public class OrderedPendingList implements PendingList {
029
030    private PendingNode root = null;
031    private PendingNode tail = null;
032    private final Map<MessageId, PendingNode> map = new HashMap<MessageId, PendingNode>();
033
034    public PendingNode addMessageFirst(MessageReference message) {
035        PendingNode node = new PendingNode(this, message);
036        if (root == null) {
037            root = node;
038            tail = node;
039        } else {
040            root.linkBefore(node);
041        }
042        this.map.put(message.getMessageId(), node);
043        return node;
044    }
045
046    public PendingNode addMessageLast(MessageReference message) {
047        PendingNode node = new PendingNode(this, message);
048        if (root == null) {
049            root = node;
050        } else {
051            tail.linkAfter(node);
052        }
053        tail = node;
054        this.map.put(message.getMessageId(), node);
055        return node;
056    }
057
058    public void clear() {
059        this.root = null;
060        this.tail = null;
061        this.map.clear();
062    }
063
064    public boolean isEmpty() {
065        return this.map.isEmpty();
066    }
067
068    public Iterator<MessageReference> iterator() {
069        return new Iterator<MessageReference>() {
070            private PendingNode current = null;
071            private PendingNode next = root;
072
073            public boolean hasNext() {
074                return next != null;
075            }
076
077            public MessageReference next() {
078                MessageReference result = null;
079                this.current = this.next;
080                result = this.current.getMessage();
081                this.next = (PendingNode) this.next.getNext();
082                return result;
083            }
084
085            public void remove() {
086                if (this.current != null && this.current.getMessage() != null) {
087                    map.remove(this.current.getMessage().getMessageId());
088                }
089                removeNode(this.current);
090            }
091        };
092    }
093
094    public PendingNode remove(MessageReference message) {
095        PendingNode node = null;
096        if (message != null) {
097            node = this.map.remove(message.getMessageId());
098            removeNode(node);
099        }
100        return node;
101    }
102
103    public int size() {
104        return this.map.size();
105    }
106
107    void removeNode(PendingNode node) {
108        if (node != null) {
109            map.remove(node.getMessage().getMessageId());
110            if (root == node) {
111                root = (PendingNode) node.getNext();
112            }
113            if (tail == node) {
114                tail = (PendingNode) node.getPrevious();
115            }
116            node.unlink();
117        }
118    }
119
120    List<PendingNode> getAsList() {
121        List<PendingNode> result = new ArrayList<PendingNode>(size());
122        PendingNode node = root;
123        while (node != null) {
124            result.add(node);
125            node = (PendingNode) node.getNext();
126        }
127        return result;
128    }
129
130    @Override
131    public String toString() {
132        return "OrderedPendingList(" + System.identityHashCode(this) + ")";
133    }
134
135    @Override
136    public boolean contains(MessageReference message) {
137        if(map.values().contains(message)) {
138            return true;
139        } else {
140            return false;
141        }
142    }
143
144    @Override
145    public Collection<MessageReference> values() {
146        List<MessageReference> messageReferences = new ArrayList<MessageReference>();
147        for(PendingNode pendingNode : map.values()) {
148            messageReferences.add(pendingNode.getMessage());
149        }
150        return messageReferences;
151    }
152
153    @Override
154    public void addAll(PendingList pendingList) {
155        for(MessageReference messageReference : pendingList) {
156            addMessageLast(messageReference);
157        }
158    }
159}