1 2 12 package com.versant.core.jdo; 13 14 import com.versant.core.common.PCList; 15 import com.versant.core.common.QueryResultContainer; 16 import com.versant.core.server.CompiledQuery; 17 import com.versant.core.server.QueryResultWrapper; 18 19 import java.io.Serializable ; 20 import java.util.*; 21 22 import com.versant.core.common.BindingSupportImpl; 23 24 31 public final class ForwardQueryResult extends QueryResultBase 32 implements Serializable { 33 34 37 private static final int STATUS_NON_INITIALISED = 0; 38 41 private static final int STATUS_RESOLVED = 1; 42 45 private static final int STATUS_SPARSE = 2; 46 49 private static final int STATUS_CLOSED = 3; 50 53 private int status; 54 55 58 private int size; 59 63 private boolean countOnSize; 64 private PCList backingArray; 65 66 private final PMProxy pm; 67 70 private Object [] params; 71 private final List openWrapperIters = new ArrayList(); 72 73 private final QueryDetails queryDetails; 74 private final CompiledQuery compiledQuery; 75 76 79 private Object [] window; 80 private int windowSize; 81 private boolean noMoreDataInResultSet; 83 84 private int index; 85 private int maxAvailableIndex = -1; 86 private QueryResultWrapper qrw; 87 88 public ForwardQueryResult(PMProxy pmProxy, QueryDetails queryDetails, 89 CompiledQuery compiledQuery, Object [] params) { 90 this.pm = pmProxy; 91 this.queryDetails = queryDetails; 92 this.compiledQuery = compiledQuery; 93 this.setParams(params); 94 countOnSize = queryDetails.isCountOnSize(); 95 } 96 97 100 public boolean isCompiledQueryEqual(ForwardQueryResult qc) { 101 return compiledQuery.equals(qc.compiledQuery); 102 } 103 104 public void setParams(Object [] params) { 105 this.params = params; 106 } 107 108 111 public void close() { 112 if (status == STATUS_CLOSED) return; 113 114 if (qrw != null) { 115 pm.closeQuery(qrw); 116 qrw = null; 117 } 118 window = null; 119 120 backingArray = null; 121 for (int i = 0; i < openWrapperIters.size(); i++) { 122 ((JDOListIterator)openWrapperIters.get(i)).close(); 123 } 124 openWrapperIters.clear(); 125 status = STATUS_CLOSED; 126 } 127 128 132 public int size() { 133 if (status != STATUS_RESOLVED) { 134 if (countOnSize) { 135 countOnSize = false; 136 return countRows(); 137 } else { 138 resolve(); 139 } 140 } 141 return size; 142 } 143 144 public boolean isEmpty() { 145 if (status != STATUS_RESOLVED) { 146 resolve(); 147 } 148 return backingArray.isEmpty(); 149 } 150 151 public boolean contains(Object o) { 152 if (status != STATUS_RESOLVED) { 153 resolve(); 154 } 155 return backingArray.contains(o); 156 } 157 158 public Iterator iterator() { 159 checkClosed(); 160 Iterator result = null; 161 if (status == STATUS_RESOLVED) { 162 result = getLocalIter(); 163 } else { 164 result = createInternalIter(); 165 } 166 return result; 167 } 168 169 174 private ListIterator getLocalIter() { 175 ListIterator lIter = backingArray.listIterator(); 176 openWrapperIters.add(lIter); 177 return lIter; 178 } 179 180 185 private ListIterator createInternalIter() { 186 return createInternalIterImp(false); 187 } 188 189 private ListIterator createInternalIterImp(boolean doNotFlush) { 190 checkClosed(); 191 QueryIterator queryIterator = new QueryIterator(pm, compiledQuery, params, doNotFlush); 192 openWrapperIters.add(queryIterator); 193 return queryIterator; 194 } 195 196 public Iterator createInternalIterNoFlush() { 197 return createInternalIterImp(true); 198 } 199 200 public ListIterator listIterator() { 201 return (ListIterator)iterator(); 202 } 203 204 public ListIterator listIterator(int index) { 205 throw BindingSupportImpl.getInstance().notImplemented(""); 206 } 207 208 211 public Object [] toArray() { 212 toArrayImp(); 213 return backingArray.toArray(); 214 } 215 216 public Object [] toArray(Object [] a) { 217 toArrayImp(); 218 return backingArray.toArray(a); 219 } 220 221 private void toArrayImp() { 222 if (status != STATUS_RESOLVED) { 223 resolve(); 224 } 225 } 226 227 private void resolve() { 228 if (status == STATUS_RESOLVED) return; 229 checkClosed(); 230 if (status == STATUS_SPARSE) { 231 throw BindingSupportImpl.getInstance().invalidOperation( 232 "Any operation that will fully resolve" + 233 " the query may not be called once a 'get' operation was performed"); 234 } 235 236 if (!queryDetails.isIgnoreCache()) { 237 pm.flushIfDepOn(compiledQuery.getEvictionClassBits()); 238 } 239 240 QueryResultContainer qContainer = pm.getAllQueryResults( 241 compiledQuery, params); 242 pm.addToCache(qContainer.container); 243 244 backingArray = new PCList(qContainer.toResolvedObject(pm), 0, 245 qContainer.size()); 246 size = backingArray.size(); 247 status = STATUS_RESOLVED; 248 qContainer.reset(); 249 pm.processLocalCacheReferenceQueue(); 250 } 251 252 private void checkClosed() { 253 if (status == STATUS_CLOSED) { 254 throw BindingSupportImpl.getInstance().invalidOperation("Query result has been closed"); 255 } 256 } 257 258 261 private int countRows() { 262 checkClosed(); 263 if (!queryDetails.isIgnoreCache()) { 264 pm.flushIfDepOn(compiledQuery.getEvictionClassBits()); 265 } 266 return pm.getQueryRowCount(compiledQuery, params); 267 } 268 269 272 public Object get(int index) { 273 if (index < 0) { 274 throw BindingSupportImpl.getInstance().illegalArgument( 275 "Index smaller than zero is not allowed"); 276 } 277 Object result = null; 278 switch (status) { 279 case STATUS_RESOLVED: 280 result = backingArray.get(index); 281 break; 282 case STATUS_SPARSE: 283 result = internalGet(index, maxAvailableIndex); 284 break; 285 case STATUS_NON_INITIALISED: 286 if (queryDetails.prefetchAll()) { 287 resolve(); 288 result = backingArray.get(index); 289 } else { 290 if (!queryDetails.isIgnoreCache()) { 291 pm.flushIfDepOn(compiledQuery.getEvictionClassBits()); 292 } 293 294 QueryResultWrapper qrsIF = 295 this.pm.executeQuery(compiledQuery, params); 296 QueryResultContainer qContainer = 297 this.pm.getNextQueryResult(qrsIF, index); 298 299 300 if (qContainer.allResults) { 301 pm.addToCache(qContainer.container); 302 303 status = STATUS_RESOLVED; 304 backingArray = new PCList(qContainer.toResolvedObject(pm), 0, 305 qContainer.size()); 306 size = backingArray.size(); 307 status = STATUS_RESOLVED; 308 309 qContainer.reset(); 310 result = backingArray.get(index); 311 pm.processLocalCacheReferenceQueue(); 312 } else { 313 status = STATUS_SPARSE; 314 qrw = qrsIF; 315 addNewData(qContainer, index); 316 result = internalGet(index, maxAvailableIndex); 317 } 318 } 319 break; 320 default: 321 checkClosed(); 322 throw BindingSupportImpl.getInstance().internal( 323 "Status does not exist. Status = '" + status + "'"); 324 } 325 return result; 326 } 327 328 private Object internalGet(int requestedIndex, final int maxAvailableIndex) { 329 if (requestedIndex > maxAvailableIndex && !noMoreDataInResultSet) { 330 getMoreData(requestedIndex); 331 return getNextData(0); 332 } else { 333 return getNextData(windowSize - ((maxAvailableIndex - requestedIndex) + 1)); 334 } 335 336 } 337 338 private Object getNextData(int windowIndex) { 339 if (windowIndex == windowSize) 340 throw BindingSupportImpl.getInstance().arrayIndexOutOfBounds("index '" 341 + index + "' is too big"); 342 343 if (windowIndex < 0) { 344 throw BindingSupportImpl.getInstance().unsupported( 345 "May only request index greater than the previously requested index." + 346 "\nIf this is required then use VersantQuery.setRandomAccess."); 347 } 348 349 Object result = QueryResultBase.resolveRow(window[windowIndex], pm); 350 window[windowIndex] = null; 351 return result; 352 } 353 354 private void getMoreData(int requestedIndex) { 355 addNewData(pm.getNextQueryResult(qrw, requestedIndex - maxAvailableIndex - 1), requestedIndex); 357 } 358 359 private void addNewData(QueryResultContainer container, int requestedIndex) { 360 pm.addToCache(container.container); 361 362 window = container.getDataArray(); 363 windowSize = container.size(); 364 noMoreDataInResultSet = container.isqFinished(); 365 366 index = requestedIndex; 367 maxAvailableIndex = index + windowSize - 1; 368 container.reset(); 369 } 370 371 public int indexOf(Object o) { 372 if (status != STATUS_RESOLVED) { 373 resolve(); 374 } 375 return backingArray.indexOf(o); 376 } 377 378 public int lastIndexOf(Object o) { 379 if (status != STATUS_RESOLVED) { 380 resolve(); 381 } 382 return backingArray.lastIndexOf(o); 383 } 384 385 public List subList(int fromIndex, int toIndex) { 386 if (status != STATUS_RESOLVED) { 387 resolve(); 388 } 389 return backingArray.subList(fromIndex, toIndex); 390 } 391 392 public boolean containsAll(Collection c) { 393 if (status != STATUS_RESOLVED) { 394 resolve(); 395 } 396 return backingArray.containsAll(c); 397 } 398 399 public boolean equals(Object obj) { 400 if (status != STATUS_RESOLVED) { 401 resolve(); 402 } 403 return backingArray.equals(obj); 404 } 405 406 public String toString() { 407 if (status != STATUS_RESOLVED) { 408 resolve(); 409 } 410 return backingArray.toString(); 411 } 412 413 416 public Object writeReplace() { 417 return new ArrayList(this); 418 } 419 420 } 421 | Popular Tags |