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 */
017 package org.apache.activemq.broker.region.cursors;
018
019 import java.util.ArrayList;
020 import java.util.Collection;
021 import java.util.HashMap;
022 import java.util.Iterator;
023 import java.util.List;
024 import java.util.Map;
025 import org.apache.activemq.broker.region.MessageReference;
026 import org.apache.activemq.command.MessageId;
027
028 public 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 }