You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2013/05/24 19:31:14 UTC

svn commit: r1486125 [2/3] - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src: main/java/org/apache/cayenne/ main/java/org/apache/cayenne/access/ main/java/org/apache/cayenne/access/jdbc/ main/java/org/apache/cayenne/access/util/ test/ja...

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java Fri May 24 17:31:14 2013
@@ -30,7 +30,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.cayenne.CayenneException;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectContext;
@@ -62,8 +61,9 @@ import org.apache.cayenne.util.Util;
 import org.apache.commons.collections.Transformer;
 
 /**
- * Performs query routing and execution. During execution phase intercepts callbacks to
- * the OperationObserver, remapping results to the original pre-routed queries.
+ * Performs query routing and execution. During execution phase intercepts
+ * callbacks to the OperationObserver, remapping results to the original
+ * pre-routed queries.
  * 
  * @since 1.2
  */
@@ -90,10 +90,8 @@ class DataDomainQueryAction implements Q
      */
     DataDomainQueryAction(ObjectContext context, DataDomain domain, Query query) {
         if (context != null && !(context instanceof DataContext)) {
-            throw new IllegalArgumentException(
-                    "DataDomain can only work with DataContext. "
-                            + "Unsupported context type: "
-                            + context);
+            throw new IllegalArgumentException("DataDomain can only work with DataContext. "
+                    + "Unsupported context type: " + context);
         }
 
         this.domain = domain;
@@ -148,8 +146,10 @@ class DataDomainQueryAction implements Q
             ObjectIdQuery oidQuery = (ObjectIdQuery) query;
             ObjectId oid = oidQuery.getObjectId();
 
-            // special handling of temp ids... Return an empty list immediately so that
-            // upstream code could throw FaultFailureException, etc. Don't attempt to
+            // special handling of temp ids... Return an empty list immediately
+            // so that
+            // upstream code could throw FaultFailureException, etc. Don't
+            // attempt to
             // translate and run the query. See for instance CAY-1651
             if (oid.isTemporary() && !oid.isReplacementIdAttached()) {
                 response = new ListResponse();
@@ -168,12 +168,10 @@ class DataDomainQueryAction implements Q
                 if (oidQuery.isFetchAllowed()) {
 
                     runQueryInTransaction();
-                }
-                else {
+                } else {
                     response = new ListResponse();
                 }
-            }
-            else {
+            } else {
                 response = new ListResponse(row);
             }
 
@@ -192,26 +190,23 @@ class DataDomainQueryAction implements Q
                 return !DONE;
             }
 
-            ObjRelationship relationship = relationshipQuery.getRelationship(domain
-                    .getEntityResolver());
+            ObjRelationship relationship = relationshipQuery.getRelationship(domain.getEntityResolver());
 
             // check if we can derive target PK from FK...
             if (relationship.isSourceIndependentFromTargetChange()) {
                 return !DONE;
             }
-            
+
             // we can assume that there is one and only one DbRelationship as
             // we previously checked that "!isSourceIndependentFromTargetChange"
             DbRelationship dbRelationship = relationship.getDbRelationships().get(0);
-            
+
             // FK pointing to a unique field that is a 'fake' PK (CAY-1755)...
             // It is not sufficient to generate target ObjectId.
             DbEntity targetEntity = (DbEntity) dbRelationship.getTargetEntity();
-            if (dbRelationship.getJoins().size() < targetEntity
-                    .getPrimaryKeys().size()) {
+            if (dbRelationship.getJoins().size() < targetEntity.getPrimaryKeys().size()) {
                 return !DONE;
             }
-            
 
             if (cache == null) {
                 return !DONE;
@@ -222,10 +217,7 @@ class DataDomainQueryAction implements Q
                 return !DONE;
             }
 
-
-            ObjectId targetId = sourceRow.createTargetObjectId(
-                    relationship.getTargetEntityName(),
-                    dbRelationship);
+            ObjectId targetId = sourceRow.createTargetObjectId(relationship.getTargetEntityName(), dbRelationship);
 
             // null id means that FK is null...
             if (targetId == null) {
@@ -240,14 +232,15 @@ class DataDomainQueryAction implements Q
                 return DONE;
             }
 
-            // check whether a non-null FK is enough to assume non-null target, and if so,
+            // check whether a non-null FK is enough to assume non-null target,
+            // and if so,
             // create a fault
-            if (context != null
-                    && relationship.isSourceDefiningTargetPrecenseAndType(domain
-                            .getEntityResolver())) {
+            if (context != null && relationship.isSourceDefiningTargetPrecenseAndType(domain.getEntityResolver())) {
 
-                // prevent passing partial snapshots to ObjectResolver per CAY-724.
-                // Create a hollow object right here and skip object conversion downstream
+                // prevent passing partial snapshots to ObjectResolver per
+                // CAY-724.
+                // Create a hollow object right here and skip object conversion
+                // downstream
                 this.noObjectConversion = true;
                 Object object = context.findOrCreateObject(targetId);
 
@@ -281,8 +274,7 @@ class DataDomainQueryAction implements Q
                 return DONE;
             }
 
-            Collection<Persistent> objects = (Collection<Persistent>) refreshQuery
-                    .getObjects();
+            Collection<Persistent> objects = (Collection<Persistent>) refreshQuery.getObjects();
             if (objects != null && !objects.isEmpty()) {
 
                 Collection<ObjectId> ids = new ArrayList<ObjectId>(objects.size());
@@ -292,12 +284,8 @@ class DataDomainQueryAction implements Q
 
                 if (domain.getSharedSnapshotCache() != null) {
                     // send an event for removed snapshots
-                    domain.getSharedSnapshotCache().processSnapshotChanges(
-                            context.getObjectStore(),
-                            Collections.EMPTY_MAP,
-                            Collections.EMPTY_LIST,
-                            ids,
-                            Collections.EMPTY_LIST);
+                    domain.getSharedSnapshotCache().processSnapshotChanges(context.getObjectStore(),
+                            Collections.EMPTY_MAP, Collections.EMPTY_LIST, ids, Collections.EMPTY_LIST);
                 }
 
                 GenericResponse response = new GenericResponse();
@@ -306,14 +294,13 @@ class DataDomainQueryAction implements Q
                 return DONE;
             }
 
-            // 3. refresh query - this shouldn't normally happen as child datacontext
+            // 3. refresh query - this shouldn't normally happen as child
+            // datacontext
             // usually does a cascading refresh
             if (refreshQuery.getQuery() != null) {
                 Query cachedQuery = refreshQuery.getQuery();
 
-                String cacheKey = cachedQuery
-                        .getMetaData(context.getEntityResolver())
-                        .getCacheKey();
+                String cacheKey = cachedQuery.getMetaData(context.getEntityResolver()).getCacheKey();
                 context.getQueryCache().remove(cacheKey);
 
                 this.response = domain.onQuery(context, cachedQuery);
@@ -321,8 +308,7 @@ class DataDomainQueryAction implements Q
             }
 
             // 4. refresh groups...
-            if (refreshQuery.getGroupKeys() != null
-                    && refreshQuery.getGroupKeys().length > 0) {
+            if (refreshQuery.getGroupKeys() != null && refreshQuery.getGroupKeys().length > 0) {
 
                 String[] groups = refreshQuery.getGroupKeys();
                 for (String group : groups) {
@@ -349,8 +335,7 @@ class DataDomainQueryAction implements Q
         }
 
         boolean cache = QueryCacheStrategy.SHARED_CACHE == metadata.getCacheStrategy();
-        boolean cacheOrCacheRefresh = cache
-                || QueryCacheStrategy.SHARED_CACHE_REFRESH == metadata.getCacheStrategy();
+        boolean cacheOrCacheRefresh = cache || QueryCacheStrategy.SHARED_CACHE_REFRESH == metadata.getCacheStrategy();
 
         if (!cacheOrCacheRefresh) {
             return !DONE;
@@ -362,19 +347,19 @@ class DataDomainQueryAction implements Q
         if (cache) {
             List cachedResults = queryCache.get(metadata, factory);
 
-            // response may already be initialized by the factory above ... it is null if
+            // response may already be initialized by the factory above ... it
+            // is null if
             // there was a preexisting cache entry
             if (response == null) {
                 response = new ListResponse(cachedResults);
             }
 
             if (cachedResults instanceof ListWithPrefetches) {
-                this.prefetchResultsByPath = ((ListWithPrefetches) cachedResults)
-                        .getPrefetchResultsByPath();
+                this.prefetchResultsByPath = ((ListWithPrefetches) cachedResults).getPrefetchResultsByPath();
             }
-        }
-        else {
-            // on cache-refresh request, fetch without blocking and fill the cache
+        } else {
+            // on cache-refresh request, fetch without blocking and fill the
+            // cache
             queryCache.put(metadata, (List) factory.createObject());
         }
 
@@ -390,7 +375,8 @@ class DataDomainQueryAction implements Q
                 List list = response.firstList();
                 if (list != null) {
 
-                    // make an immutable list to make sure callers don't mess it up
+                    // make an immutable list to make sure callers don't mess it
+                    // up
                     list = Collections.unmodifiableList(list);
 
                     // include prefetches in the cached result
@@ -425,18 +411,18 @@ class DataDomainQueryAction implements Q
         this.queriesByNode = null;
         this.queriesByExecutedQueries = null;
 
-        // whether this is null or not will driver further decisions on how to process
+        // whether this is null or not will driver further decisions on how to
+        // process
         // prefetched rows
-        this.prefetchResultsByPath = metadata.getPrefetchTree() != null
-                && !metadata.isFetchingDataRows() ? new HashMap() : null;
+        this.prefetchResultsByPath = metadata.getPrefetchTree() != null && !metadata.isFetchingDataRows() ? new HashMap()
+                : null;
 
         // categorize queries by node and by "executable" query...
         query.route(this, domain.getEntityResolver(), null);
 
         // run categorized queries
         if (queriesByNode != null) {
-            for (Map.Entry<QueryEngine, Collection<Query>> entry : queriesByNode
-                    .entrySet()) {
+            for (Map.Entry<QueryEngine, Collection<Query>> entry : queriesByNode.entrySet()) {
                 QueryEngine nextNode = entry.getKey();
                 Collection<Query> nodeQueries = entry.getValue();
                 nextNode.performQueries(nodeQueries, this);
@@ -456,18 +442,15 @@ class DataDomainQueryAction implements Q
                 List<Object> rsMapping = metadata.getResultSetMapping();
                 if (rsMapping == null) {
                     converter = new SingleObjectConversionStrategy();
-                }
-                else {
+                } else {
 
                     if (rsMapping.size() == 1) {
                         if (rsMapping.get(0) instanceof EntityResultSegment) {
                             converter = new SingleObjectConversionStrategy();
-                        }
-                        else {
+                        } else {
                             converter = new SingleScalarConversionStrategy();
                         }
-                    }
-                    else {
+                    } else {
                         converter = new MixedConversionStrategy();
                     }
                 }
@@ -482,8 +465,7 @@ class DataDomainQueryAction implements Q
         Collection<Query> queries = null;
         if (queriesByNode == null) {
             queriesByNode = new HashMap<QueryEngine, Collection<Query>>();
-        }
-        else {
+        } else {
             queries = queriesByNode.get(engine);
         }
 
@@ -494,7 +476,8 @@ class DataDomainQueryAction implements Q
 
         queries.add(query);
 
-        // handle case when routing resulted in an "executable" query different from the
+        // handle case when routing resulted in an "executable" query different
+        // from the
         // original query.
         if (substitutedQuery != null && substitutedQuery != query) {
 
@@ -534,8 +517,7 @@ class DataDomainQueryAction implements Q
         if (prefetchResultsByPath != null && query instanceof PrefetchSelectQuery) {
             PrefetchSelectQuery prefetchQuery = (PrefetchSelectQuery) query;
             prefetchResultsByPath.put(prefetchQuery.getPrefetchPath(), dataRows);
-        }
-        else {
+        } else {
             fullResponse.addResultList(dataRows);
         }
     }
@@ -548,19 +530,8 @@ class DataDomainQueryAction implements Q
         if (keysIterator != null) {
             try {
                 nextRows(query, keysIterator.allRows());
-            }
-            catch (CayenneException ex) {
-                // don't throw here....
-                nextQueryException(query, ex);
-            }
-            finally {
-                try {
-                    keysIterator.close();
-                }
-                catch (CayenneException e) {
-                    // don't throw here....
-                    nextQueryException(query, e);
-                }
+            } finally {
+                keysIterator.close();
             }
         }
     }
@@ -581,26 +552,16 @@ class DataDomainQueryAction implements Q
 
         abstract void convert(List<T> mainRows);
 
-        protected PrefetchProcessorNode toResultsTree(
-                ClassDescriptor descriptor,
-                PrefetchTreeNode prefetchTree,
+        protected PrefetchProcessorNode toResultsTree(ClassDescriptor descriptor, PrefetchTreeNode prefetchTree,
                 List<DataRow> normalizedRows) {
 
             // take a shortcut when no prefetches exist...
             if (prefetchTree == null) {
-                return new ObjectResolver(
-                        context,
-                        descriptor,
-                        metadata.isRefreshingObjects())
+                return new ObjectResolver(context, descriptor, metadata.isRefreshingObjects())
                         .synchronizedRootResultNodeFromDataRows(normalizedRows);
-            }
-            else {
-                HierarchicalObjectResolver resolver = new HierarchicalObjectResolver(
-                        context,
-                        metadata);
-                return resolver.synchronizedRootResultNodeFromDataRows(
-                        prefetchTree,
-                        normalizedRows,
+            } else {
+                HierarchicalObjectResolver resolver = new HierarchicalObjectResolver(context, metadata);
+                return resolver.synchronizedRootResultNodeFromDataRows(prefetchTree, normalizedRows,
                         prefetchResultsByPath);
             }
         }
@@ -608,24 +569,18 @@ class DataDomainQueryAction implements Q
         protected void updateResponse(List sourceObjects, List targetObjects) {
             if (response instanceof GenericResponse) {
                 ((GenericResponse) response).replaceResult(sourceObjects, targetObjects);
-            }
-            else if (response instanceof ListResponse) {
+            } else if (response instanceof ListResponse) {
                 response = new ListResponse(targetObjects);
-            }
-            else {
+            } else {
                 throw new IllegalStateException("Unknown response object: " + response);
             }
         }
 
-        protected void performPostLoadCallbacks(
-                PrefetchProcessorNode node,
-                LifecycleCallbackRegistry callbackRegistry) {
+        protected void performPostLoadCallbacks(PrefetchProcessorNode node, LifecycleCallbackRegistry callbackRegistry) {
 
             if (node.hasChildren()) {
                 for (PrefetchTreeNode child : node.getChildren()) {
-                    performPostLoadCallbacks(
-                            (PrefetchProcessorNode) child,
-                            callbackRegistry);
+                    performPostLoadCallbacks((PrefetchProcessorNode) child, callbackRegistry);
                 }
             }
 
@@ -646,14 +601,10 @@ class DataDomainQueryAction implements Q
 
             PrefetchProcessorNode node = toResultsTree(descriptor, prefetchTree, mainRows);
             List<Persistent> objects = node.getObjects();
-            updateResponse(mainRows, objects != null
-                    ? objects
-                    : new ArrayList<Persistent>(1));
+            updateResponse(mainRows, objects != null ? objects : new ArrayList<Persistent>(1));
 
             // apply POST_LOAD callback
-            LifecycleCallbackRegistry callbackRegistry = context
-                    .getEntityResolver()
-                    .getCallbackRegistry();
+            LifecycleCallbackRegistry callbackRegistry = context.getEntityResolver().getCallbackRegistry();
 
             if (!callbackRegistry.isEmpty(LifecycleEvent.POST_LOAD)) {
                 performPostLoadCallbacks(node, callbackRegistry);
@@ -671,11 +622,8 @@ class DataDomainQueryAction implements Q
 
     class MixedConversionStrategy extends ObjectConversionStrategy<Object[]> {
 
-        protected PrefetchProcessorNode toResultsTree(
-                ClassDescriptor descriptor,
-                PrefetchTreeNode prefetchTree,
-                List<Object[]> rows,
-                int position) {
+        protected PrefetchProcessorNode toResultsTree(ClassDescriptor descriptor, PrefetchTreeNode prefetchTree,
+                List<Object[]> rows, int position) {
 
             int len = rows.size();
             List<DataRow> rowsColumn = new ArrayList<DataRow>(len);
@@ -690,8 +638,7 @@ class DataDomainQueryAction implements Q
                         if (prefetchTreeNode == null) {
                             prefetchTreeNode = new PrefetchTreeNode();
                         }
-                        PrefetchTreeNode addPath = prefetchTreeNode.addPath(prefetch
-                                .getPath());
+                        PrefetchTreeNode addPath = prefetchTreeNode.addPath(prefetch.getPath());
                         addPath.setSemantics(PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);
                         addPath.setPhantom(false);
                     }
@@ -700,22 +647,12 @@ class DataDomainQueryAction implements Q
             }
 
             if (prefetchTree == null) {
-                return new ObjectResolver(
-                        context,
-                        descriptor,
-                        metadata.isRefreshingObjects())
+                return new ObjectResolver(context, descriptor, metadata.isRefreshingObjects())
                         .synchronizedRootResultNodeFromDataRows(rowsColumn);
-            }
-            else {
-                HierarchicalObjectResolver resolver = new HierarchicalObjectResolver(
-                        context,
-                        metadata,
-                        descriptor,
+            } else {
+                HierarchicalObjectResolver resolver = new HierarchicalObjectResolver(context, metadata, descriptor,
                         true);
-                return resolver.synchronizedRootResultNodeFromDataRows(
-                        prefetchTree,
-                        rowsColumn,
-                        prefetchResultsByPath);
+                return resolver.synchronizedRootResultNodeFromDataRows(prefetchTree, rowsColumn, prefetchResultsByPath);
             }
         }
 
@@ -727,20 +664,16 @@ class DataDomainQueryAction implements Q
             List<Object> rsMapping = metadata.getResultSetMapping();
             int width = rsMapping.size();
 
-            // no conversions needed for scalar positions; reuse Object[]'s to fill them
+            // no conversions needed for scalar positions; reuse Object[]'s to
+            // fill them
             // with resolved objects
-            List<PrefetchProcessorNode> segmentNodes = new ArrayList<PrefetchProcessorNode>(
-                    width);
+            List<PrefetchProcessorNode> segmentNodes = new ArrayList<PrefetchProcessorNode>(width);
             for (int i = 0; i < width; i++) {
 
                 if (rsMapping.get(i) instanceof EntityResultSegment) {
-                    EntityResultSegment entitySegment = (EntityResultSegment) rsMapping
-                            .get(i);
-                    PrefetchProcessorNode nextResult = toResultsTree(
-                            entitySegment.getClassDescriptor(),
-                            metadata.getPrefetchTree(),
-                            mainRows,
-                            i);
+                    EntityResultSegment entitySegment = (EntityResultSegment) rsMapping.get(i);
+                    PrefetchProcessorNode nextResult = toResultsTree(entitySegment.getClassDescriptor(),
+                            metadata.getPrefetchTree(), mainRows, i);
 
                     segmentNodes.add(nextResult);
 
@@ -761,9 +694,7 @@ class DataDomainQueryAction implements Q
             }
 
             // invoke callbacks now that all objects are resolved...
-            LifecycleCallbackRegistry callbackRegistry = context
-                    .getEntityResolver()
-                    .getCallbackRegistry();
+            LifecycleCallbackRegistry callbackRegistry = context.getEntityResolver().getCallbackRegistry();
 
             if (!callbackRegistry.isEmpty(LifecycleEvent.POST_LOAD)) {
                 for (PrefetchProcessorNode node : segmentNodes) {

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataPort.java Fri May 24 17:31:14 2013
@@ -39,19 +39,20 @@ import org.apache.cayenne.query.SQLTempl
 import org.apache.cayenne.query.SelectQuery;
 
 /**
- * An engine to port data between two DataNodes. These nodes can potentially connect to
- * databases from different vendors. The only assumption is that all of the DbEntities
- * (tables) being ported are present in both source and destination databases and are
- * adequately described by Cayenne mapping.
+ * An engine to port data between two DataNodes. These nodes can potentially
+ * connect to databases from different vendors. The only assumption is that all
+ * of the DbEntities (tables) being ported are present in both source and
+ * destination databases and are adequately described by Cayenne mapping.
  * <p>
- * DataPort implements a Cayenne-based algorithm to read data from source DataNode and
- * write to destination DataNode. It uses DataPortDelegate interface to externalize
- * various things, such as determining what entities to port (include/exclude from port
- * based on some criteria), logging the progress of port operation, qualifying the
- * queries, etc.
+ * DataPort implements a Cayenne-based algorithm to read data from source
+ * DataNode and write to destination DataNode. It uses DataPortDelegate
+ * interface to externalize various things, such as determining what entities to
+ * port (include/exclude from port based on some criteria), logging the progress
+ * of port operation, qualifying the queries, etc.
  * </p>
  * 
- * @since 1.2: Prior to 1.2 DataPort classes were a part of cayenne-examples package.
+ * @since 1.2: Prior to 1.2 DataPort classes were a part of cayenne-examples
+ *        package.
  * @deprecated since 3.2
  */
 @Deprecated
@@ -78,9 +79,9 @@ public class DataPort {
     }
 
     /**
-     * Runs DataPort. The instance must be fully configured by the time this method is
-     * invoked, having its delegate, source and destinatio nodes, and a list of entities
-     * set up.
+     * Runs DataPort. The instance must be fully configured by the time this
+     * method is invoked, having its delegate, source and destinatio nodes, and
+     * a list of entities set up.
      */
     public void execute() throws CayenneException {
         // sanity check
@@ -92,11 +93,11 @@ public class DataPort {
             throw new CayenneException("Can't port data, destination node is null.");
         }
 
-        // the simple equality check may actually detect problems with misconfigred nodes
+        // the simple equality check may actually detect problems with
+        // misconfigred nodes
         // it is not as dumb as it may look at first
         if (sourceNode == destinationNode) {
-            throw new CayenneException(
-                    "Can't port data, source and target nodes are the same.");
+            throw new CayenneException("Can't port data, source and target nodes are the same.");
         }
 
         if (entities == null || entities.isEmpty()) {
@@ -145,8 +146,7 @@ public class DataPort {
         while (it.hasNext()) {
             DbEntity entity = (DbEntity) it.next();
 
-            Query query = new SQLTemplate(entity, "DELETE FROM "
-                    + entity.getFullyQualifiedName());
+            Query query = new SQLTemplate(entity, "DELETE FROM " + entity.getFullyQualifiedName());
 
             // notify delegate that delete is about to happen
             if (delegate != null) {
@@ -201,10 +201,7 @@ public class DataPort {
             select.setFetchingDataRows(true);
 
             // delegate is allowed to substitute query
-            Query query = (delegate != null) ? delegate.willPortEntity(
-                    this,
-                    entity,
-                    select) : select;
+            Query query = (delegate != null) ? delegate.willPortEntity(this, entity, select) : select;
 
             sourceNode.performQueries(Collections.singletonList(query), observer);
             ResultIterator result = observer.getResultIterator();
@@ -217,19 +214,17 @@ public class DataPort {
                 // and not run out of memory.
                 int currentRow = 0;
 
-                // even if we don't use intermediate batch commits, we still need to
+                // even if we don't use intermediate batch commits, we still
+                // need to
                 // estimate batch insert size
                 int batchSize = insertBatchSize > 0 ? insertBatchSize : INSERT_BATCH_SIZE;
 
                 while (result.hasNextRow()) {
-                    if (insertBatchSize > 0
-                            && currentRow > 0
-                            && currentRow % insertBatchSize == 0) {
-                        // end of the batch detected... commit and start a new insert
+                    if (insertBatchSize > 0 && currentRow > 0 && currentRow % insertBatchSize == 0) {
+                        // end of the batch detected... commit and start a new
+                        // insert
                         // query
-                        destinationNode.performQueries(
-                                Collections.singletonList((Query) insert),
-                                insertObserver);
+                        destinationNode.performQueries(Collections.singletonList((Query) insert), insertObserver);
                         insert = new InsertBatchQuery(entity, batchSize);
                         insertObserver.clear();
                     }
@@ -242,22 +237,16 @@ public class DataPort {
 
                 // commit remaining batch if needed
                 if (insert.size() > 0) {
-                    destinationNode.performQueries(
-                            Collections.singletonList((Query) insert),
-                            insertObserver);
+                    destinationNode.performQueries(Collections.singletonList((Query) insert), insertObserver);
                 }
 
                 if (delegate != null) {
                     delegate.didPortEntity(this, entity, currentRow);
                 }
-            }
-            finally {
-                try {
-                    // don't forget to close ResultIterator
-                    result.close();
-                }
-                catch (CayenneException ex) {
-                }
+            } finally {
+
+                // don't forget to close ResultIterator
+                result.close();
             }
         }
     }
@@ -275,8 +264,8 @@ public class DataPort {
     }
 
     /**
-     * Sets the initial list of entities to process. This list can be later modified by
-     * the delegate.
+     * Sets the initial list of entities to process. This list can be later
+     * modified by the delegate.
      */
     public void setEntities(Collection entities) {
         this.entities = entities;
@@ -308,16 +297,16 @@ public class DataPort {
     }
 
     /**
-     * Returns true if a DataPort was configured to delete all data from the destination
-     * tables.
+     * Returns true if a DataPort was configured to delete all data from the
+     * destination tables.
      */
     public boolean isCleaningDestination() {
         return cleaningDestination;
     }
 
     /**
-     * Defines whether DataPort should delete all data from destination tables before
-     * doing the port.
+     * Defines whether DataPort should delete all data from destination tables
+     * before doing the port.
      */
     public void setCleaningDestination(boolean cleaningDestination) {
         this.cleaningDestination = cleaningDestination;
@@ -328,9 +317,10 @@ public class DataPort {
     }
 
     /**
-     * Sets a parameter used for tuning insert batches. If set to a value greater than
-     * zero, DataPort will commit every N rows. If set to value less or equal to zero,
-     * DataPort will commit only once at the end of the insert.
+     * Sets a parameter used for tuning insert batches. If set to a value
+     * greater than zero, DataPort will commit every N rows. If set to value
+     * less or equal to zero, DataPort will commit only once at the end of the
+     * insert.
      */
     public void setInsertBatchSize(int insertBatchSize) {
         this.insertBatchSize = insertBatchSize;

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultIterator.java Fri May 24 17:31:14 2013
@@ -21,49 +21,52 @@ package org.apache.cayenne.access;
 
 import java.util.List;
 
-import org.apache.cayenne.CayenneException;
-
 /**
- * Defines API of an iterator over the records returned as a result of SelectQuery
- * execution. Usually a ResultIterator is supported by an open java.sql.ResultSet,
- * therefore most of the methods would throw checked exceptions. ResultIterators must be
- * explicitly closed when the user is done working with them.
+ * Defines API of an iterator over the records returned as a result of
+ * SelectQuery execution. Usually a ResultIterator is supported by an open
+ * java.sql.ResultSet, therefore most of the methods would throw checked
+ * exceptions. ResultIterators must be explicitly closed when the user is done
+ * working with them.
  * <p>
- * Result "rows", depending on the query, may be represented as scalar values, DataRows,
- * or Object[] arrays containing a mix of scalars and DataRows.
+ * Result "rows", depending on the query, may be represented as scalar values,
+ * DataRows, or Object[] arrays containing a mix of scalars and DataRows.
  */
-public interface ResultIterator {
+public interface ResultIterator<T> extends Iterable<T> {
 
     /**
      * Returns all yet unread rows from ResultSet without closing it.
      * 
      * @since 3.0
      */
-    List<?> allRows() throws CayenneException;
+    List<T> allRows();
 
     /**
-     * Returns true if there is at least one more record that can be read from the
-     * iterator.
+     * Returns true if there is at least one more record that can be read from
+     * the iterator.
      */
-    boolean hasNextRow() throws CayenneException;
+    boolean hasNextRow();
 
     /**
-     * Returns the next result row that is, depending on the query, may be a scalar value,
-     * a DataRow, or an Object[] array containing a mix of scalars and DataRows.
+     * Returns the next result row that is, depending on the query, may be a
+     * scalar value, a DataRow, or an Object[] array containing a mix of scalars
+     * and DataRows.
      * 
      * @since 3.0
      */
-    Object nextRow() throws CayenneException;
+    T nextRow();
 
     /**
+     * Goes past current row. If the row is not needed, this may save some time
+     * on data conversion.
+     * 
      * @since 3.0
      */
-    void skipRow() throws CayenneException;
+    void skipRow();
 
     /**
-     * Closes ResultIterator and associated ResultSet. This method must be called
-     * explicitly when the user is finished processing the records. Otherwise unused
-     * database resources will not be released properly.
+     * Closes ResultIterator and associated ResultSet. This method must be
+     * called explicitly when the user is finished processing the records.
+     * Otherwise unused database resources will not be released properly.
      */
-    void close() throws CayenneException;
+    void close();
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/TransactionResultIteratorDecorator.java Fri May 24 17:31:14 2013
@@ -20,44 +20,47 @@
 package org.apache.cayenne.access;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
-import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 
 /**
- * Decorates ResultIterator to close active transaction when the iterator is closed.
+ * Decorates ResultIterator to close active transaction when the iterator is
+ * closed.
  * 
  * @since 1.2
  */
-final class TransactionResultIteratorDecorator implements ResultIterator {
+final class TransactionResultIteratorDecorator<T> implements ResultIterator<T> {
 
-    private ResultIterator result;
+    private ResultIterator<T> result;
     private Transaction tx;
 
-    public TransactionResultIteratorDecorator(ResultIterator result, Transaction tx) {
+    public TransactionResultIteratorDecorator(ResultIterator<T> result, Transaction tx) {
         this.result = result;
         this.tx = tx;
     }
 
+    public Iterator<T> iterator() {
+        return result.iterator();
+    }
+
     /**
      * Closes the result and commits the transaction.
      */
-    public void close() throws CayenneException {
+    public void close() {
 
         try {
             result.close();
             tx.commit();
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             try {
                 tx.rollback();
-            }
-            catch (Exception rollbackEx) {
+            } catch (Exception rollbackEx) {
             }
 
-            throw new CayenneException(e);
-        }
-        finally {
+            throw new CayenneRuntimeException(e);
+        } finally {
             if (Transaction.getThreadTransaction() == tx) {
                 Transaction.bindThreadTransaction(null);
             }
@@ -67,8 +70,8 @@ final class TransactionResultIteratorDec
     /**
      * @since 3.0
      */
-    public List<?> allRows() throws CayenneException {
-        List<Object> list = new ArrayList<Object>();
+    public List<T> allRows() {
+        List<T> list = new ArrayList<T>();
 
         while (hasNextRow()) {
             list.add(nextRow());
@@ -77,21 +80,21 @@ final class TransactionResultIteratorDec
         return list;
     }
 
-    public boolean hasNextRow() throws CayenneException {
+    public boolean hasNextRow() {
         return result.hasNextRow();
     }
 
     /**
      * @since 3.0
      */
-    public Object nextRow() throws CayenneException {
+    public T nextRow() {
         return result.nextRow();
     }
 
     /**
      * @since 3.0
      */
-    public void skipRow() throws CayenneException {
+    public void skipRow() {
         result.skipRow();
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseRowReader.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseRowReader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseRowReader.java Fri May 24 17:31:14 2013
@@ -20,7 +20,6 @@ package org.apache.cayenne.access.jdbc;
 
 import java.sql.ResultSet;
 
-import org.apache.cayenne.CayenneException;
 import org.apache.cayenne.access.types.ExtendedType;
 import org.apache.cayenne.map.ObjEntity;
 import org.apache.cayenne.query.QueryMetadata;
@@ -55,7 +54,7 @@ abstract class BaseRowReader<T> implemen
         }
     }
 
-    public abstract T readRow(ResultSet resultSet) throws CayenneException;
+    public abstract T readRow(ResultSet resultSet);
 
     public void setPostProcessor(DataRowPostProcessor postProcessor) {
         this.postProcessor = postProcessor;

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BaseSQLAction.java Fri May 24 17:31:14 2013
@@ -23,7 +23,6 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.List;
 
-import org.apache.cayenne.CayenneException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.OperationObserver;
 import org.apache.cayenne.dba.JdbcAdapter;
@@ -58,58 +57,41 @@ public abstract class BaseSQLAction impl
     /**
      * Helper method to process a ResultSet.
      */
-    protected void readResultSet(
-            ResultSet resultSet,
-            RowDescriptor descriptor,
-            Query query,
-            OperationObserver delegate) throws SQLException, Exception {
+    protected void readResultSet(ResultSet resultSet, RowDescriptor descriptor, Query query, OperationObserver delegate)
+            throws SQLException, Exception {
 
         long t1 = System.currentTimeMillis();
 
         QueryMetadata metadata = query.getMetaData(getEntityResolver());
 
-        JDBCResultIterator resultReader = new JDBCResultIterator(
-                null,
-                null,
-                resultSet,
-                descriptor,
+        JDBCResultIterator<DataRow> resultReader = new JDBCResultIterator<DataRow>(null, null, resultSet, descriptor,
                 metadata);
 
-        LimitResultIterator it = new LimitResultIterator(
-                resultReader,
-                getInMemoryOffset(metadata.getFetchOffset()),
-                metadata.getFetchLimit());
+        LimitResultIterator<DataRow> it = new LimitResultIterator<DataRow>(resultReader,
+                getInMemoryOffset(metadata.getFetchOffset()), metadata.getFetchLimit());
 
         if (!delegate.isIteratedResult()) {
-            List<DataRow> resultRows = (List<DataRow>) it.allRows();
+            List<DataRow> resultRows = it.allRows();
             adapter.getJdbcEventLogger().logSelectCount(resultRows.size(), System.currentTimeMillis() - t1);
 
             delegate.nextRows(query, resultRows);
-        }
-        else {
+        } else {
             try {
                 resultReader.setClosingConnection(true);
                 delegate.nextRows(query, it);
-            }
-            catch (Exception ex) {
-
-                try {
-                    it.close();
-                }
-                catch (CayenneException cex) {
-                    // ignore...
-                }
-
+            } catch (Exception ex) {
+                it.close();
                 throw ex;
             }
         }
     }
 
     /**
-     * Returns a value of the offset that will be used to rewind the ResultSet within the
-     * SQL action before reading the result rows. The default implementation returns
-     * 'queryOffset' argument. If the adapter supports setting offset at the SQL level,
-     * this method must be overridden to return zero to suppress manual offset.
+     * Returns a value of the offset that will be used to rewind the ResultSet
+     * within the SQL action before reading the result rows. The default
+     * implementation returns 'queryOffset' argument. If the adapter supports
+     * setting offset at the SQL level, this method must be overridden to return
+     * zero to suppress manual offset.
      * 
      * @since 3.0
      */

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CollectionResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CollectionResultIterator.java?rev=1486125&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CollectionResultIterator.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CollectionResultIterator.java Fri May 24 17:31:14 2013
@@ -0,0 +1,81 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access.jdbc;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cayenne.access.ResultIterator;
+
+/**
+ * A ResultIterator over a collection of objects.
+ * 
+ * @since 3.2
+ */
+public class CollectionResultIterator<T> implements ResultIterator<T> {
+
+    protected Iterator<T> iterator;
+
+    public CollectionResultIterator(Collection<T> c) {
+        this.iterator = c.iterator();
+    }
+
+    public Iterator<T> iterator() {
+        checkIterator();
+        return iterator;
+    }
+
+    public List<T> allRows() {
+
+        List<T> list = new ArrayList<T>();
+        for (T t : this) {
+            list.add(t);
+        }
+
+        return list;
+    }
+
+    public boolean hasNextRow() {
+        checkIterator();
+        return iterator.hasNext();
+    }
+
+    public T nextRow() {
+        checkIterator();
+        return iterator.next();
+    }
+
+    public void skipRow() {
+        checkIterator();
+        iterator.next();
+    }
+
+    public void close() {
+        iterator = null;
+    }
+
+    protected void checkIterator() {
+        if (iterator == null) {
+            throw new IllegalStateException("Iterator is closed");
+        }
+    }
+
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/CompoundRowReader.java Fri May 24 17:31:14 2013
@@ -20,8 +20,6 @@ package org.apache.cayenne.access.jdbc;
 
 import java.sql.ResultSet;
 
-import org.apache.cayenne.CayenneException;
-
 /**
  * A row reader for complex result sets resolved as object arrays.
  * 
@@ -39,7 +37,7 @@ class CompoundRowReader implements RowRe
         this.readers[pos] = reader;
     }
 
-    public Object[] readRow(ResultSet resultSet) throws CayenneException {
+    public Object[] readRow(ResultSet resultSet) {
 
         int width = readers.length;
         Object[] row = new Object[width];

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DistinctResultIterator.java Fri May 24 17:31:14 2013
@@ -21,28 +21,30 @@ package org.apache.cayenne.access.jdbc;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
-import org.apache.cayenne.CayenneException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.ResultIterator;
 import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.DbEntity;
 
 /**
- * A ResultIterator that does in-memory filtering of rows to return only distinct rows.
- * Distinct comparison is done by comparing ObjectIds created from each row. Internally
- * DistinctResultIterator wraps another ResultIterator that provides the actual rows.
+ * A ResultIterator that does in-memory filtering of rows to return only
+ * distinct rows. Distinct comparison is done by comparing ObjectIds created
+ * from each row. Internally DistinctResultIterator wraps another ResultIterator
+ * that provides the actual rows.
  * 
  * @since 3.0
  */
-public class DistinctResultIterator implements ResultIterator {
+public class DistinctResultIterator<T> implements ResultIterator<T> {
 
-    protected ResultIterator wrappedIterator;
+    protected ResultIterator<T> delegate;
     protected Set<Map<String, Object>> fetchedIds;
-    protected Object nextDataRow;
+    protected DataRow nextDataRow;
     protected DbEntity defaultEntity;
     protected boolean compareFullRows;
 
@@ -50,19 +52,19 @@ public class DistinctResultIterator impl
      * Creates new DistinctResultIterator wrapping another ResultIterator.
      * 
      * @param wrappedIterator
-     * @param defaultEntity an entity needed to build ObjectIds for distinct comparison.
+     * @param defaultEntity
+     *            an entity needed to build ObjectIds for distinct comparison.
      */
-    public DistinctResultIterator(ResultIterator wrappedIterator, DbEntity defaultEntity,
-            boolean compareFullRows) throws CayenneException {
-        if (wrappedIterator == null) {
-            throw new CayenneException("Null wrapped iterator.");
+    public DistinctResultIterator(ResultIterator<T> delegate, DbEntity defaultEntity, boolean compareFullRows) {
+        if (delegate == null) {
+            throw new NullPointerException("Null wrapped iterator.");
         }
 
         if (defaultEntity == null) {
-            throw new CayenneException("Null defaultEntity.");
+            throw new NullPointerException("Null defaultEntity.");
         }
 
-        this.wrappedIterator = wrappedIterator;
+        this.delegate = delegate;
         this.defaultEntity = defaultEntity;
         this.fetchedIds = new HashSet<Map<String, Object>>();
         this.compareFullRows = compareFullRows;
@@ -71,17 +73,24 @@ public class DistinctResultIterator impl
     }
 
     /**
+     * @since 3.2
+     */
+    public Iterator<T> iterator() {
+        return new ResultIteratorIterator<T>(this);
+    }
+
+    /**
      * CLoses underlying ResultIterator.
      */
-    public void close() throws CayenneException {
-        wrappedIterator.close();
+    public void close() {
+        delegate.close();
     }
 
     /**
      * @since 3.0
      */
-    public List<?> allRows() throws CayenneException {
-        List<Object> list = new ArrayList<Object>();
+    public List<T> allRows() {
+        List<T> list = new ArrayList<T>();
 
         while (this.hasNextRow()) {
             list.add(nextRow());
@@ -89,17 +98,18 @@ public class DistinctResultIterator impl
         return list;
     }
 
-    public boolean hasNextRow() throws CayenneException {
+    public boolean hasNextRow() {
         return nextDataRow != null;
     }
 
-    public Object nextRow() throws CayenneException {
+    public T nextRow() {
         if (!hasNextRow()) {
-            throw new CayenneException(
-                    "An attempt to read uninitialized row or past the end of the iterator.");
+            throw new NoSuchElementException("An attempt to read uninitialized row or past the end of the iterator.");
         }
 
-        Object row = nextDataRow;
+        // TODO: 
+        @SuppressWarnings("unchecked")
+        T row = (T) nextDataRow;
         checkNextRow();
         return row;
     }
@@ -107,30 +117,28 @@ public class DistinctResultIterator impl
     /**
      * @since 3.0
      */
-    public void skipRow() throws CayenneException {
+    public void skipRow() {
         if (!hasNextRow()) {
-            throw new CayenneException(
-                    "An attempt to read uninitialized row or past the end of the iterator.");
+            throw new NoSuchElementException("An attempt to read uninitialized row or past the end of the iterator.");
         }
 
         checkNextRow();
     }
 
-    void checkNextRow() throws CayenneException {
+    void checkNextRow() {
 
         if (this.compareFullRows) {
             checkNextUniqueRow();
-        }
-        else {
+        } else {
             checkNextRowWithUniqueId();
         }
     }
 
-    void checkNextUniqueRow() throws CayenneException {
+    void checkNextUniqueRow() {
 
         nextDataRow = null;
-        while (wrappedIterator.hasNextRow()) {
-            DataRow next = (DataRow) wrappedIterator.nextRow();
+        while (delegate.hasNextRow()) {
+            DataRow next = (DataRow) delegate.nextRow();
 
             if (fetchedIds.add(next)) {
                 this.nextDataRow = next;
@@ -139,11 +147,11 @@ public class DistinctResultIterator impl
         }
     }
 
-    void checkNextRowWithUniqueId() throws CayenneException {
+    void checkNextRowWithUniqueId() {
 
         nextDataRow = null;
-        while (wrappedIterator.hasNextRow()) {
-            DataRow next = (DataRow) wrappedIterator.nextRow();
+        while (delegate.hasNextRow()) {
+            DataRow next = (DataRow) delegate.nextRow();
 
             // create id map...
             // TODO: this can be optimized by creating an array with id keys

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/EntityRowReader.java Fri May 24 17:31:14 2013
@@ -20,7 +20,7 @@ package org.apache.cayenne.access.jdbc;
 
 import java.sql.ResultSet;
 
-import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.access.types.ExtendedType;
 import org.apache.cayenne.query.EntityResultSegment;
@@ -62,17 +62,17 @@ class EntityRowReader implements RowRead
             this.converters[i] = converters[startIndex + i];
             types[i] = columns[startIndex + i].getJdbcType();
 
-            // query translator may change the order of fields compare to the entity
+            // query translator may change the order of fields compare to the
+            // entity
             // result, so figure out DataRow labels by doing reverse lookup of
             // RowDescriptor labels...
             if (columns[startIndex + i].getDataRowKey().contains(".")) {
-                // if the dataRowKey contains ".", it is prefetched column and we can use
+                // if the dataRowKey contains ".", it is prefetched column and
+                // we can use
                 // it instead of search the name by alias
                 labels[i] = columns[startIndex + i].getDataRowKey();
-            }
-            else {
-                labels[i] = segmentMetadata.getColumnPath(columns[startIndex + i]
-                        .getDataRowKey());
+            } else {
+                labels[i] = segmentMetadata.getColumnPath(columns[startIndex + i].getDataRowKey());
             }
         }
     }
@@ -81,7 +81,7 @@ class EntityRowReader implements RowRead
         this.postProcessor = postProcessor;
     }
 
-    public DataRow readRow(ResultSet resultSet) throws CayenneException {
+    public DataRow readRow(ResultSet resultSet) {
 
         try {
             DataRow row = new DataRow(mapCapacity);
@@ -90,23 +90,18 @@ class EntityRowReader implements RowRead
             for (int i = 0; i < len; i++) {
 
                 // note: jdbc column indexes start from 1, not 0 as in arrays
-                Object val = converters[i].materializeObject(resultSet, startIndex
-                        + i
-                        + 1, types[i]);
+                Object val = converters[i].materializeObject(resultSet, startIndex + i + 1, types[i]);
                 row.put(labels[i], val);
             }
 
             postprocessRow(resultSet, row);
 
             return row;
-        }
-        catch (CayenneException cex) {
+        } catch (CayenneRuntimeException cex) {
             // rethrow unmodified
             throw cex;
-        }
-        catch (Exception otherex) {
-            throw new CayenneException("Exception materializing id column.", Util
-                    .unwindException(otherex));
+        } catch (Exception otherex) {
+            throw new CayenneRuntimeException("Exception materializing id column.", Util.unwindException(otherex));
         }
     }
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/FullRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/FullRowReader.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/FullRowReader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/FullRowReader.java Fri May 24 17:31:14 2013
@@ -20,7 +20,7 @@ package org.apache.cayenne.access.jdbc;
 
 import java.sql.ResultSet;
 
-import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.query.QueryMetadata;
 import org.apache.cayenne.util.Util;
@@ -38,7 +38,7 @@ class FullRowReader extends BaseRowReade
     }
 
     @Override
-    public DataRow readRow(ResultSet resultSet) throws CayenneException {
+    public DataRow readRow(ResultSet resultSet) {
         try {
             DataRow dataRow = new DataRow(mapCapacity);
 
@@ -46,7 +46,8 @@ class FullRowReader extends BaseRowReade
 
             // process result row columns,
             for (int i = 0; i < resultWidth; i++) {
-                // note: jdbc column indexes start from 1, not 0 unlike everywhere else
+                // note: jdbc column indexes start from 1, not 0 unlike
+                // everywhere else
                 Object val = converters[i].materializeObject(resultSet, i + 1, types[i]);
                 dataRow.put(labels[i], val);
             }
@@ -54,14 +55,11 @@ class FullRowReader extends BaseRowReade
             postprocessRow(resultSet, dataRow);
 
             return dataRow;
-        }
-        catch (CayenneException cex) {
+        } catch (CayenneRuntimeException cex) {
             // rethrow unmodified
             throw cex;
-        }
-        catch (Exception otherex) {
-            throw new CayenneException("Exception materializing column.", Util
-                    .unwindException(otherex));
+        } catch (Exception otherex) {
+            throw new CayenneRuntimeException("Exception materializing column.", Util.unwindException(otherex));
         }
     }
 

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/IdRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/IdRowReader.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/IdRowReader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/IdRowReader.java Fri May 24 17:31:14 2013
@@ -20,7 +20,6 @@ package org.apache.cayenne.access.jdbc;
 
 import java.sql.ResultSet;
 
-import org.apache.cayenne.CayenneException;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.map.DbAttribute;
@@ -31,7 +30,7 @@ import org.apache.cayenne.util.Util;
 /**
  * @since 3.0
  */
-class IdRowReader extends BaseRowReader<Object> {
+class IdRowReader<T> extends BaseRowReader<T> {
 
     protected int[] pkIndices;
 
@@ -47,8 +46,7 @@ class IdRowReader extends BaseRowReader<
 
         // sanity check
         if (len == 0) {
-            throw new CayenneRuntimeException("Root DBEntity has no PK defined: "
-                    + dbEntity);
+            throw new CayenneRuntimeException("Root DBEntity has no PK defined: " + dbEntity);
         }
 
         int[] pk = new int[len];
@@ -64,42 +62,38 @@ class IdRowReader extends BaseRowReader<
     }
 
     @Override
-    public Object readRow(ResultSet resultSet) throws CayenneException {
+    public T readRow(ResultSet resultSet) {
         try {
             if (pkIndices.length == 1) {
                 return readSingleId(resultSet);
-            }
-            else {
+            } else {
                 return readIdMap(resultSet);
             }
-        }
-        catch (CayenneException cex) {
+        } catch (CayenneRuntimeException cex) {
             // rethrow unmodified
             throw cex;
-        }
-        catch (Exception otherex) {
-            throw new CayenneException("Exception materializing id column.", Util
-                    .unwindException(otherex));
+        } catch (Exception otherex) {
+            throw new CayenneRuntimeException("Exception materializing id column.", Util.unwindException(otherex));
         }
     }
 
-    private Object readSingleId(ResultSet resultSet) throws Exception {
+    private T readSingleId(ResultSet resultSet) throws Exception {
 
         // dereference column index
         int index = pkIndices[0];
 
         // note: jdbc column indexes start from 1, not 0 as in arrays
-        Object val = converters[index].materializeObject(
-                resultSet,
-                index + 1,
-                types[index]);
+        @SuppressWarnings("unchecked")
+        T val = (T) converters[index].materializeObject(resultSet, index + 1, types[index]);
 
-        // note that postProcessor overrides are not applied. ID mapping must be the
+        // note that postProcessor overrides are not applied. ID mapping must be
+        // the
         // same across inheritance hierarchy, so overrides do not make sense.
         return val;
     }
 
-    private Object readIdMap(ResultSet resultSet) throws Exception {
+    @SuppressWarnings("unchecked")
+    private T readIdMap(ResultSet resultSet) throws Exception {
 
         DataRow idRow = new DataRow(2);
         idRow.setEntityName(entityName);
@@ -111,10 +105,7 @@ class IdRowReader extends BaseRowReader<
             int index = pkIndices[i];
 
             // note: jdbc column indexes start from 1, not 0 as in arrays
-            Object val = converters[index].materializeObject(
-                    resultSet,
-                    index + 1,
-                    types[index]);
+            Object val = converters[index].materializeObject(resultSet, index + 1, types[index]);
             idRow.put(labels[index], val);
         }
 
@@ -122,6 +113,6 @@ class IdRowReader extends BaseRowReader<
             postProcessor.postprocessRow(resultSet, idRow);
         }
 
-        return idRow;
+        return (T) idRow;
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/JDBCResultIterator.java Fri May 24 17:31:14 2013
@@ -24,7 +24,9 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 import org.apache.cayenne.CayenneException;
 import org.apache.cayenne.CayenneRuntimeException;
@@ -38,7 +40,7 @@ import org.apache.cayenne.query.ScalarRe
  * 
  * @since 1.2
  */
-public class JDBCResultIterator implements ResultIterator {
+public class JDBCResultIterator<T> implements ResultIterator<T> {
 
     // Connection information
     protected Connection connection;
@@ -55,16 +57,15 @@ public class JDBCResultIterator implemen
 
     protected boolean nextRow;
 
-    private RowReader<?> rowReader;
+    private RowReader<T> rowReader;
 
     /**
      * Creates new JDBCResultIterator that reads from provided ResultSet.
      * 
      * @since 3.0
      */
-    public JDBCResultIterator(Connection connection, Statement statement,
-            ResultSet resultSet, RowDescriptor descriptor, QueryMetadata queryMetadata)
-            throws CayenneException {
+    public JDBCResultIterator(Connection connection, Statement statement, ResultSet resultSet,
+            RowDescriptor descriptor, QueryMetadata queryMetadata) throws CayenneException {
 
         this.connection = connection;
         this.statement = statement;
@@ -80,11 +81,17 @@ public class JDBCResultIterator implemen
     }
 
     /**
+     * @since 3.2
+     */
+    public Iterator<T> iterator() {
+        return new ResultIteratorIterator<T>(this);
+    }
+
+    /**
      * RowReader factory method.
      */
-    private RowReader<?> createRowReader(
-            RowDescriptor descriptor,
-            QueryMetadata queryMetadata) {
+    @SuppressWarnings("unchecked")
+    private RowReader<T> createRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
 
         List<Object> rsMapping = queryMetadata.getResultSetMapping();
         if (rsMapping != null) {
@@ -92,83 +99,64 @@ public class JDBCResultIterator implemen
             int resultWidth = rsMapping.size();
             if (resultWidth == 0) {
                 throw new CayenneRuntimeException("Empty result descriptor");
-            }
-            else if (resultWidth == 1) {
+            } else if (resultWidth == 1) {
 
                 Object segment = rsMapping.get(0);
 
                 if (segment instanceof EntityResultSegment) {
-                    return createEntityRowReader(
-                            descriptor,
-                            (EntityResultSegment) segment);
+                    return createEntityRowReader(descriptor, (EntityResultSegment) segment);
+                } else {
+                    return new ScalarRowReader<T>(descriptor, (ScalarResultSegment) segment);
                 }
-                else {
-                    return new ScalarRowReader(descriptor, (ScalarResultSegment) segment);
-                }
-            }
-            else {
+            } else {
                 CompoundRowReader reader = new CompoundRowReader(resultWidth);
 
                 for (int i = 0; i < resultWidth; i++) {
                     Object segment = rsMapping.get(i);
 
                     if (segment instanceof EntityResultSegment) {
-                        reader.addRowReader(i, createEntityRowReader(
-                                descriptor,
-                                (EntityResultSegment) segment));
-                    }
-                    else {
-                        reader.addRowReader(i, new ScalarRowReader(
-                                descriptor,
-                                (ScalarResultSegment) segment));
+                        reader.addRowReader(i, createEntityRowReader(descriptor, (EntityResultSegment) segment));
+                    } else {
+                        reader.addRowReader(i, new ScalarRowReader<Object>(descriptor, (ScalarResultSegment) segment));
                     }
                 }
 
-                return reader;
+                return (RowReader<T>) reader;
             }
-        }
-        else {
+        } else {
             return createFullRowReader(descriptor, queryMetadata);
         }
     }
 
-    private RowReader<?> createEntityRowReader(
-            RowDescriptor descriptor,
-            EntityResultSegment resultMetadata) {
+    @SuppressWarnings("unchecked")
+    private RowReader<T> createEntityRowReader(RowDescriptor descriptor, EntityResultSegment resultMetadata) {
 
         if (queryMetadata.getPageSize() > 0) {
-            return new IdRowReader(descriptor, queryMetadata);
-        }
-        else if (resultMetadata.getClassDescriptor() != null
-                && resultMetadata.getClassDescriptor().hasSubclasses()) {
-            return new InheritanceAwareEntityRowReader(descriptor, resultMetadata);
-        }
-        else {
-            return new EntityRowReader(descriptor, resultMetadata);
+            return new IdRowReader<T>(descriptor, queryMetadata);
+        } else if (resultMetadata.getClassDescriptor() != null && resultMetadata.getClassDescriptor().hasSubclasses()) {
+            return (RowReader<T>) new InheritanceAwareEntityRowReader(descriptor, resultMetadata);
+        } else {
+            return (RowReader<T>) new EntityRowReader(descriptor, resultMetadata);
         }
     }
 
-    private RowReader<?> createFullRowReader(
-            RowDescriptor descriptor,
-            QueryMetadata queryMetadata) {
+    @SuppressWarnings("unchecked")
+    private RowReader<T> createFullRowReader(RowDescriptor descriptor, QueryMetadata queryMetadata) {
 
         if (queryMetadata.getPageSize() > 0) {
-            return new IdRowReader(descriptor, queryMetadata);
-        }
-        else if (queryMetadata.getClassDescriptor() != null
-                && queryMetadata.getClassDescriptor().hasSubclasses()) {
-            return new InheritanceAwareRowReader(descriptor, queryMetadata);
-        }
-        else {
-            return new FullRowReader(descriptor, queryMetadata);
+            return new IdRowReader<T>(descriptor, queryMetadata);
+        } else if (queryMetadata.getClassDescriptor() != null && queryMetadata.getClassDescriptor().hasSubclasses()) {
+            return (RowReader<T>) new InheritanceAwareRowReader(descriptor, queryMetadata);
+        } else {
+            return (RowReader<T>) new FullRowReader(descriptor, queryMetadata);
         }
     }
 
     /**
      * @since 3.0
      */
-    public List<?> allRows() throws CayenneException {
-        List<Object> list = new ArrayList<Object>();
+    public List<T> allRows() {
+        List<T> list = new ArrayList<T>();
 
         while (hasNextRow()) {
             list.add(nextRow());
@@ -178,8 +166,8 @@ public class JDBCResultIterator implemen
     }
 
     /**
-     * Returns true if there is at least one more record that can be read from the
-     * iterator.
+     * Returns true if there is at least one more record that can be read from
+     * the iterator.
      */
     public boolean hasNextRow() {
         return nextRow;
@@ -188,13 +176,12 @@ public class JDBCResultIterator implemen
     /**
      * @since 3.0
      */
-    public Object nextRow() throws CayenneException {
+    public T nextRow() {
         if (!hasNextRow()) {
-            throw new CayenneException(
-                    "An attempt to read uninitialized row or past the end of the iterator.");
+            throw new NoSuchElementException("An attempt to read uninitialized row or past the end of the iterator.");
         }
 
-        Object row = rowReader.readRow(resultSet);
+        T row = rowReader.readRow(resultSet);
         checkNextRow();
         return row;
     }
@@ -202,20 +189,19 @@ public class JDBCResultIterator implemen
     /**
      * @since 3.0
      */
-    public void skipRow() throws CayenneException {
+    public void skipRow() {
         if (!hasNextRow()) {
-            throw new CayenneException(
-                    "An attempt to read uninitialized row or past the end of the iterator.");
+            throw new NoSuchElementException("An attempt to read uninitialized row or past the end of the iterator.");
         }
         checkNextRow();
     }
 
     /**
-     * Closes ResultIterator and associated ResultSet. This method must be called
-     * explicitly when the user is finished processing the records. Otherwise unused
-     * database resources will not be released properly.
+     * Closes ResultIterator and associated ResultSet. This method must be
+     * called explicitly when the user is finished processing the records.
+     * Otherwise unused database resources will not be released properly.
      */
-    public void close() throws CayenneException {
+    public void close() throws NoSuchElementException {
         if (!closed) {
             nextRow = false;
 
@@ -223,22 +209,22 @@ public class JDBCResultIterator implemen
 
             try {
                 resultSet.close();
-            }
-            catch (SQLException e1) {
+            } catch (SQLException e1) {
                 errors.append("Error closing ResultSet.");
             }
 
             if (statement != null) {
                 try {
                     statement.close();
-                }
-                catch (SQLException e2) {
+                } catch (SQLException e2) {
                     errors.append("Error closing PreparedStatement.");
                 }
             }
 
-            // TODO: andrus, 5/8/2006 - closing connection within JDBCResultIterator is
-            // obsolete as this is bound to transaction closing in DataContext. Deprecate
+            // TODO: andrus, 5/8/2006 - closing connection within
+            // JDBCResultIterator is
+            // obsolete as this is bound to transaction closing in DataContext.
+            // Deprecate
             // this after 1.2
 
             // close connection, if this object was explicitly configured to be
@@ -246,15 +232,13 @@ public class JDBCResultIterator implemen
             if (connection != null && isClosingConnection()) {
                 try {
                     connection.close();
-                }
-                catch (SQLException e3) {
+                } catch (SQLException e3) {
                     errors.append("Error closing Connection.");
                 }
             }
 
             if (errors.length() > 0) {
-                throw new CayenneException("Error closing ResultIterator: "
-                        + errors.toString());
+                throw new CayenneRuntimeException("Error closing ResultIterator: " + errors.toString());
             }
 
             closed = true;
@@ -262,25 +246,24 @@ public class JDBCResultIterator implemen
     }
 
     /**
-     * Moves internal ResultSet cursor position down one row. Checks if the next row is
-     * available.
+     * Moves internal ResultSet cursor position down one row. Checks if the next
+     * row is available.
      */
-    protected void checkNextRow() throws CayenneException {
+    protected void checkNextRow() {
         nextRow = false;
         try {
             if (resultSet.next()) {
                 nextRow = true;
             }
-        }
-        catch (SQLException e) {
-            throw new CayenneException("Error rewinding ResultSet", e);
+        } catch (SQLException e) {
+            throw new CayenneRuntimeException("Error rewinding ResultSet", e);
         }
     }
 
     /**
      * Returns <code>true</code> if this iterator is responsible for closing its
-     * connection, otherwise a user of the iterator must close the connection after
-     * closing the iterator.
+     * connection, otherwise a user of the iterator must close the connection
+     * after closing the iterator.
      */
     public boolean isClosingConnection() {
         return closingConnection;
@@ -297,7 +280,8 @@ public class JDBCResultIterator implemen
         return rowDescriptor;
     }
 
-    // TODO: andrus 11/27/2008 refactor the postprocessor hack into a special row reader.
+    // TODO: andrus 11/27/2008 refactor the postprocessor hack into a special
+    // row reader.
     void setPostProcessor(DataRowPostProcessor postProcessor) {
 
         if (rowReader != null) {

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/LimitResultIterator.java Fri May 24 17:31:14 2013
@@ -19,18 +19,19 @@
 package org.apache.cayenne.access.jdbc;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.NoSuchElementException;
 
-import org.apache.cayenne.CayenneException;
 import org.apache.cayenne.access.ResultIterator;
 
 /**
  * @since 3.0
  */
-public class LimitResultIterator implements ResultIterator {
+public class LimitResultIterator<T> implements ResultIterator<T> {
 
-    protected ResultIterator wrappedIterator;
+    protected ResultIterator<T> delegate;
     protected Map<String, Object> nextDataObjectIds;
 
     protected int fetchLimit;
@@ -39,13 +40,12 @@ public class LimitResultIterator impleme
 
     protected boolean nextRow;
 
-    public LimitResultIterator(ResultIterator wrappedIterator, int offset, int fetchLimit)
-            throws CayenneException {
+    public LimitResultIterator(ResultIterator<T> delegate, int offset, int fetchLimit) {
 
-        if (wrappedIterator == null) {
-            throw new CayenneException("Null wrapped iterator.");
+        if (delegate == null) {
+            throw new NullPointerException("Null delegate iterator.");
         }
-        this.wrappedIterator = wrappedIterator;
+        this.delegate = delegate;
         this.offset = offset;
         this.fetchLimit = fetchLimit;
 
@@ -54,54 +54,59 @@ public class LimitResultIterator impleme
 
     }
 
-    private void checkOffset() throws CayenneException {
-        for (int i = 0; i < offset && wrappedIterator.hasNextRow(); i++) {
-            wrappedIterator.nextRow();
+    /**
+     * @since 3.2
+     */
+    public Iterator<T> iterator() {
+        return new ResultIteratorIterator<T>(this);
+    }
+
+    private void checkOffset() {
+        for (int i = 0; i < offset && delegate.hasNextRow(); i++) {
+            delegate.nextRow();
         }
     }
 
-    private void checkNextRow() throws CayenneException {
+    private void checkNextRow() {
         nextRow = false;
 
-        if ((fetchLimit <= 0 || fetchedSoFar < fetchLimit)
-                && this.wrappedIterator.hasNextRow()) {
+        if ((fetchLimit <= 0 || fetchedSoFar < fetchLimit) && this.delegate.hasNextRow()) {
             nextRow = true;
             fetchedSoFar++;
         }
     }
 
-    public void close() throws CayenneException {
-        wrappedIterator.close();
+    public void close() {
+        delegate.close();
     }
 
     /**
      * @since 3.0
      */
-    public List<?> allRows() throws CayenneException {
+    public List<T> allRows() {
 
-        List<Object> list = new ArrayList<Object>();
+        List<T> list = new ArrayList<T>();
 
-        while (this.hasNextRow()) {
-            list.add(this.nextRow());
+        while (hasNextRow()) {
+            list.add(nextRow());
         }
 
         return list;
     }
 
-    public boolean hasNextRow() throws CayenneException {
+    public boolean hasNextRow() {
         return nextRow;
     }
 
     /**
      * @since 3.0
      */
-    public Object nextRow() throws CayenneException {
+    public T nextRow() {
         if (!hasNextRow()) {
-            throw new CayenneException(
-                    "An attempt to read uninitialized row or past the end of the iterator.");
+            throw new NoSuchElementException("An attempt to read uninitialized row or past the end of the iterator.");
         }
 
-        Object row = wrappedIterator.nextRow();
+        T row = delegate.nextRow();
         checkNextRow();
         return row;
     }
@@ -109,7 +114,7 @@ public class LimitResultIterator impleme
     /**
      * @since 3.0
      */
-    public void skipRow() throws CayenneException {
-        wrappedIterator.skipRow();
+    public void skipRow() {
+        delegate.skipRow();
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/RowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/RowReader.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/RowReader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/RowReader.java Fri May 24 17:31:14 2013
@@ -20,8 +20,6 @@ package org.apache.cayenne.access.jdbc;
 
 import java.sql.ResultSet;
 
-import org.apache.cayenne.CayenneException;
-
 /**
  * A strategy class that encapsulates an algorithm for converting a single ResultSet row
  * into a DataRow.
@@ -33,7 +31,7 @@ interface RowReader<T> {
     /**
      * Extracts a DataRow from the ResultSet at its current position.
      */
-    T readRow(ResultSet resultSet) throws CayenneException;
+    T readRow(ResultSet resultSet);
 
     // TODO: andrus 11/27/2008 refactor the postprocessor hack into a special row reader.
     void setPostProcessor(DataRowPostProcessor postProcessor);

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java?rev=1486125&r1=1486124&r2=1486125&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/ScalarRowReader.java Fri May 24 17:31:14 2013
@@ -20,7 +20,7 @@ package org.apache.cayenne.access.jdbc;
 
 import java.sql.ResultSet;
 
-import org.apache.cayenne.CayenneException;
+import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.access.types.ExtendedType;
 import org.apache.cayenne.query.ScalarResultSegment;
 import org.apache.cayenne.util.Util;
@@ -28,7 +28,7 @@ import org.apache.cayenne.util.Util;
 /**
  * @since 3.0
  */
-class ScalarRowReader implements RowReader<Object> {
+class ScalarRowReader<T> implements RowReader<T> {
 
     private ExtendedType converter;
     private int index;
@@ -42,17 +42,15 @@ class ScalarRowReader implements RowRead
         this.index = scalarIndex + 1;
     }
 
-    public Object readRow(ResultSet resultSet) throws CayenneException {
+    @SuppressWarnings("unchecked")
+    public T readRow(ResultSet resultSet) {
         try {
-            return converter.materializeObject(resultSet, index, type);
-        }
-        catch (CayenneException cex) {
+            return (T) converter.materializeObject(resultSet, index, type);
+        } catch (CayenneRuntimeException cex) {
             // rethrow unmodified
             throw cex;
-        }
-        catch (Exception otherex) {
-            throw new CayenneException("Exception materializing column.", Util
-                    .unwindException(otherex));
+        } catch (Exception otherex) {
+            throw new CayenneRuntimeException("Exception materializing column.", Util.unwindException(otherex));
         }
     }