public E get(int index) { synchronized (elements) { Object o = elements.get(index); if (helper.unresolvedSuspect(o)) { // read this page int pageStart = pageIndex(index) * pageSize; resolveInterval(pageStart, pageStart + pageSize); return (E) elements.get(index); } else { return (E) o; } } }
/** @since 3.0 */ void checkPageResultConsistency(List<?> objects, List<?> ids) { if (objects.size() < ids.size()) { // find missing ids StringBuilder buffer = new StringBuilder(); buffer.append("Some ObjectIds are missing from the database. "); buffer.append("Expected ").append(ids.size()).append(", fetched ").append(objects.size()); boolean first = true; for (Object id : ids) { boolean found = false; for (Object object : objects) { if (helper.replacesObject(object, id)) { found = true; break; } } if (!found) { if (first) { first = false; } else { buffer.append(", "); } buffer.append(id.toString()); } } throw new CayenneRuntimeException(buffer.toString()); } else if (objects.size() > ids.size()) { throw new CayenneRuntimeException( "Expected " + ids.size() + " objects, retrieved " + objects.size()); } }
public int lastIndexOf(Object o) { return helper.lastIndexOfObject(o); }
/** @see java.util.List#indexOf(Object) */ public int indexOf(Object o) { return helper.indexOfObject(o); }
/** * Resolves a sublist of objects starting at <code>fromIndex</code> up to but not including <code> * toIndex</code>. Internally performs bound checking and trims indexes accordingly. */ protected void resolveInterval(int fromIndex, int toIndex) { if (fromIndex >= toIndex) { return; } synchronized (elements) { if (elements.size() == 0) { return; } // perform bound checking if (fromIndex < 0) { fromIndex = 0; } if (toIndex > elements.size()) { toIndex = elements.size(); } List<Expression> quals = new ArrayList<>(pageSize); List<Object> ids = new ArrayList<>(pageSize); for (int i = fromIndex; i < toIndex; i++) { Object object = elements.get(i); if (helper.unresolvedSuspect(object)) { quals.add(buildIdQualifier(object)); ids.add(object); } } int qualsSize = quals.size(); if (qualsSize == 0) { return; } // fetch the range of objects in fetchSize chunks boolean fetchesDataRows = internalQuery.isFetchingDataRows(); List<Object> objects = new ArrayList<>(qualsSize); int fetchSize = maxFetchSize > 0 ? maxFetchSize : Integer.MAX_VALUE; int fetchEnd = Math.min(qualsSize, fetchSize); int fetchBegin = 0; while (fetchBegin < qualsSize) { SelectQuery<Object> query = new SelectQuery<>( rootEntity, ExpressionFactory.joinExp(Expression.OR, quals.subList(fetchBegin, fetchEnd))); query.setFetchingDataRows(fetchesDataRows); if (!query.isFetchingDataRows()) { query.setPrefetchTree(internalQuery.getPrefetchTree()); } objects.addAll(dataContext.performQuery(query)); fetchBegin = fetchEnd; fetchEnd += Math.min(fetchSize, qualsSize - fetchEnd); } // sanity check - database data may have changed checkPageResultConsistency(objects, ids); // replace ids in the list with objects Iterator it = objects.iterator(); while (it.hasNext()) { helper.updateWithResolvedObjectInRange(it.next(), fromIndex, toIndex); } unfetchedObjects -= objects.size(); } }