1 10 11 package org.mmbase.bridge.util; 12 13 import org.mmbase.bridge.*; 14 import org.mmbase.storage.search.*; 15 import org.mmbase.cache.CachePolicy; 16 import org.mmbase.util.logging.*; 17 18 import java.util.*; 19 20 30 31 public class HugeNodeListIterator implements NodeIterator { 32 33 public static final int DEFAULT_BATCH_SIZE = 10000; 34 35 private static final Logger log = Logging.getLoggerInstance(HugeNodeListIterator.class); 37 38 protected NodeIterator nodeIterator; 39 protected Node nextNode; 40 protected Node previousNode; 41 42 protected Query originalQuery; 43 protected int batchSize = DEFAULT_BATCH_SIZE; 44 45 protected int nextIndex = 0; 46 47 54 public HugeNodeListIterator(Query query, int batchSize) { 55 this.batchSize = batchSize; 56 init(query); 57 } 58 59 65 public HugeNodeListIterator(Query query) { 66 if (query.getMaxNumber() != SearchQuery.DEFAULT_MAX_NUMBER) { 67 batchSize = query.getMaxNumber(); 68 } init(query); 70 } 71 72 75 private void init(Query query) { 76 if (query.getOffset() > 0) { 77 throw new UnsupportedOperationException ("Not implemented for queries with offset"); 78 } 79 Queries.sortUniquely(query); 80 originalQuery = query; 81 executeNextQuery((Query) originalQuery.clone()); 82 } 83 84 85 89 protected void executeQuery(Query currentQuery) { 90 currentQuery.setMaxNumber(batchSize); 91 if (log.isDebugEnabled()) { 92 log.trace("Running query: " + currentQuery); 93 } 94 NodeList list; 95 currentQuery.setCachePolicy(CachePolicy.NEVER); 96 if (originalQuery instanceof NodeQuery) { 97 NodeQuery nq = (NodeQuery) currentQuery; 98 list = nq.getNodeManager().getList(nq); 99 } else { 100 list = currentQuery.getCloud().getList(currentQuery); 101 } 102 if (log.isDebugEnabled()) { 103 log.trace("Query result: " + list.size() + " nodes"); 104 } 105 nodeIterator = list.nodeIterator(); 106 } 107 108 111 protected void executeNextQuery(Query q) { 112 executeQuery(q); 113 previousNode = nextNode; 114 if (nodeIterator.hasNext()) { 115 nextNode = nodeIterator.nextNode(); 116 } else { 117 nextNode = null; 118 } 119 } 120 124 protected void executePreviousQuery(Query q) { 125 executeQuery(q); 126 nextNode = previousNode; 127 while (nodeIterator.hasNext()) { 128 nodeIterator.next(); 129 } 130 if (nodeIterator.hasPrevious()) { 131 previousNode = nodeIterator.nextNode(); 132 } else { 133 previousNode = null; 134 } 135 } 136 137 138 141 public boolean hasNext() { 142 return nextNode != null; 143 } 144 145 148 public boolean hasPrevious() { 149 return previousNode != null; 150 } 151 152 153 156 public Object next() { 157 return nextNode(); 158 } 159 160 163 public Object previous() { 164 return previousNode(); 165 } 166 169 public int previousIndex() { 170 return nextIndex - 1; 171 } 172 175 public int nextIndex() { 176 return nextIndex; 177 } 178 179 186 protected int compares(Node node1, Node node2) { 187 return Queries.compare(node1, node2, originalQuery.getSortOrders()); 188 } 189 190 196 public Node nextNode() { 197 if (nextNode != null) { 198 nextIndex++; 199 previousNode = nextNode; 200 if (nodeIterator.hasNext()) { 201 nextNode = nodeIterator.nextNode(); 202 } else { 203 Query currentQuery = (Query) originalQuery.clone(); 204 205 SortOrder order = (SortOrder) originalQuery.getSortOrders().get(0); 209 Object value = Queries.getSortOrderFieldValue(previousNode, order); 210 Constraint cons; 211 if (order.getDirection() == SortOrder.ORDER_ASCENDING) { 212 cons = currentQuery.createConstraint(order.getField(), FieldCompareConstraint.GREATER_EQUAL, value); 213 } else { 214 cons = currentQuery.createConstraint(order.getField(), FieldCompareConstraint.LESS_EQUAL, value); 215 } 216 Queries.addConstraint(currentQuery, cons); 217 218 executeNextQuery(currentQuery); 219 220 while(nextNode != null && compares(nextNode, previousNode) <= 0) { 223 if (nodeIterator.hasNext()) { 224 nextNode = nodeIterator.nextNode(); 225 } else { 226 nextNode = null; 227 } 228 } 229 } 230 231 return previousNode; } else { 233 throw new NoSuchElementException("No next element"); 234 } 235 } 236 237 242 public Node previousNode() { 243 if (previousNode != null) { 244 nextNode = previousNode; 245 nextIndex --; 246 if (nodeIterator.hasPrevious()) { 247 previousNode = nodeIterator.previousNode(); 248 } else { 249 Query currentQuery = (Query) originalQuery.clone(); 250 SortOrder order = (SortOrder) originalQuery.getSortOrders().get(0); 251 Object value = Queries.getSortOrderFieldValue(nextNode, order); 252 Constraint cons; 253 if (order.getDirection() == SortOrder.ORDER_ASCENDING) { 254 cons = currentQuery.createConstraint(order.getField(), FieldCompareConstraint.LESS_EQUAL, value); 255 } else { 256 cons = currentQuery.createConstraint(order.getField(), FieldCompareConstraint.GREATER_EQUAL, value); 257 } 258 Queries.addConstraint(currentQuery, cons); 259 executePreviousQuery(currentQuery); 260 while(previousNode != null && compares(nextNode, previousNode) >= 0) { 261 if (nodeIterator.hasPrevious()) { 262 previousNode = nodeIterator.previousNode(); 263 } else { 264 previousNode = null; 265 } 266 } 267 268 } 269 return nextNode; 270 } else { 271 throw new NoSuchElementException("No previous element"); 272 } 273 } 274 275 278 public void remove() { 279 throw new UnsupportedOperationException ("Optional operation 'remove' not implemented"); 280 } 281 282 285 public void add(Object o) { 286 throw new UnsupportedOperationException ("Optional operation 'add' not implemented"); 287 } 288 289 292 public void set(Object o) { 293 throw new UnsupportedOperationException ("Optional operation 'set' not implemented"); 294 } 295 296 299 public static void main(String [] args) { 300 Cloud cloud = ContextProvider.getDefaultCloudContext().getCloud("mmbase"); 301 NodeQuery q = cloud.getNodeManager("object").createQuery(); 302 HugeNodeListIterator nodeIterator = new HugeNodeListIterator(q, 20); 303 int i = 0; 304 while (nodeIterator.hasNext()) { 305 Node node = nodeIterator.nextNode(); 306 System.out.println("" + (i++) + ": " + node.getNumber() + " " + node.getNodeManager().getName() + " " + node.getFunctionValue("gui", null).toString()); 307 } 308 309 } 310 311 } 312 | Popular Tags |