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; 025 026import org.apache.activemq.broker.region.MessageReference; 027import org.apache.activemq.command.MessageId; 028 029public class OrderedPendingList implements PendingList { 030 031 private PendingNode root = null; 032 private PendingNode tail = null; 033 private final Map<MessageId, PendingNode> map = new HashMap<MessageId, PendingNode>(); 034 035 public PendingNode addMessageFirst(MessageReference message) { 036 PendingNode node = new PendingNode(this, message); 037 if (root == null) { 038 root = node; 039 tail = node; 040 } else { 041 root.linkBefore(node); 042 root = node; 043 } 044 this.map.put(message.getMessageId(), node); 045 return node; 046 } 047 048 public PendingNode addMessageLast(MessageReference message) { 049 PendingNode node = new PendingNode(this, message); 050 if (root == null) { 051 root = node; 052 } else { 053 tail.linkAfter(node); 054 } 055 tail = node; 056 this.map.put(message.getMessageId(), node); 057 return node; 058 } 059 060 public void clear() { 061 this.root = null; 062 this.tail = null; 063 this.map.clear(); 064 } 065 066 public boolean isEmpty() { 067 return this.map.isEmpty(); 068 } 069 070 public Iterator<MessageReference> iterator() { 071 return new Iterator<MessageReference>() { 072 private PendingNode current = null; 073 private PendingNode next = root; 074 075 public boolean hasNext() { 076 return next != null; 077 } 078 079 public MessageReference next() { 080 MessageReference result = null; 081 this.current = this.next; 082 result = this.current.getMessage(); 083 this.next = (PendingNode) this.next.getNext(); 084 return result; 085 } 086 087 public void remove() { 088 if (this.current != null && this.current.getMessage() != null) { 089 map.remove(this.current.getMessage().getMessageId()); 090 } 091 removeNode(this.current); 092 } 093 }; 094 } 095 096 public PendingNode remove(MessageReference message) { 097 PendingNode node = null; 098 if (message != null) { 099 node = this.map.remove(message.getMessageId()); 100 removeNode(node); 101 } 102 return node; 103 } 104 105 public int size() { 106 return this.map.size(); 107 } 108 109 void removeNode(PendingNode node) { 110 if (node != null) { 111 map.remove(node.getMessage().getMessageId()); 112 if (root == node) { 113 root = (PendingNode) node.getNext(); 114 } 115 if (tail == node) { 116 tail = (PendingNode) node.getPrevious(); 117 } 118 node.unlink(); 119 } 120 } 121 122 List<PendingNode> getAsList() { 123 List<PendingNode> result = new ArrayList<PendingNode>(size()); 124 PendingNode node = root; 125 while (node != null) { 126 result.add(node); 127 node = (PendingNode) node.getNext(); 128 } 129 return result; 130 } 131 132 @Override 133 public String toString() { 134 return "OrderedPendingList(" + System.identityHashCode(this) + ")"; 135 } 136 137 @Override 138 public boolean contains(MessageReference message) { 139 if (message != null) { 140 return this.map.containsKey(message.getMessageId()); 141 } 142 return false; 143 } 144 145 @Override 146 public Collection<MessageReference> values() { 147 return getValues(this); 148 } 149 150 public static Collection<MessageReference> getValues(final PendingList pendingList) { 151 List<MessageReference> messageReferences = new ArrayList<MessageReference>(); 152 Iterator<MessageReference> iterator = pendingList.iterator(); 153 while (iterator.hasNext()) { 154 messageReferences.add(iterator.next()); 155 } 156 return messageReferences; 157 } 158 159 @Override 160 public void addAll(PendingList pendingList) { 161 if (pendingList != null) { 162 for(MessageReference messageReference : pendingList) { 163 addMessageLast(messageReference); 164 } 165 } 166 } 167 168 @Override 169 public MessageReference get(MessageId messageId) { 170 PendingNode node = map.get(messageId); 171 if (node != null) { 172 return node.getMessage(); 173 } 174 return null; 175 } 176 177 public void insertAtHead(List<MessageReference> list) { 178 if (list != null && !list.isEmpty()) { 179 PendingNode newHead = null; 180 PendingNode appendNode = null; 181 for (MessageReference ref : list) { 182 PendingNode node = new PendingNode(this, ref); 183 this.map.put(ref.getMessageId(), node); 184 if (newHead == null) { 185 newHead = node; 186 appendNode = node; 187 continue; 188 } 189 appendNode.linkAfter(node); 190 appendNode = node; 191 } 192 // insert this new list at root 193 if (root == null) { 194 root = newHead; 195 tail = appendNode; 196 } else { 197 appendNode.linkAfter(root); 198 root = newHead; 199 } 200 } 201 } 202 203}