refactoring accessor allocation

git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_opentype@315 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AFlatValueAccessor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AFlatValueAccessor.java
index fe8b656..130d597 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AFlatValueAccessor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AFlatValueAccessor.java
@@ -16,8 +16,10 @@
 package edu.uci.ics.asterix.runtime.accessors;
 
 import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.types.IAType;
 import edu.uci.ics.asterix.runtime.accessors.base.IBinaryAccessor;
 import edu.uci.ics.asterix.runtime.accessors.visitor.IBinaryAccessorVisitor;
+import edu.uci.ics.asterix.runtime.util.container.IElementFactory;
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.IValueReference;
 
 public class AFlatValueAccessor implements IBinaryAccessor {
@@ -26,6 +28,16 @@
     private int start;
     private int len;
 
+    public static IElementFactory<IBinaryAccessor, IAType> FACTORY = new IElementFactory<IBinaryAccessor, IAType>() {
+        public AFlatValueAccessor createElement(IAType type) {
+            return new AFlatValueAccessor();
+        }
+    };
+
+    private AFlatValueAccessor() {
+
+    }
+
     @Override
     public void reset(byte[] data, int start, int len) {
         this.data = data;
@@ -67,7 +79,7 @@
     }
 
     @Override
-    public <R, T> R accept(IBinaryAccessorVisitor<R, T> vistor, T tag) throws AsterixException{
+    public <R, T> R accept(IBinaryAccessorVisitor<R, T> vistor, T tag) throws AsterixException {
         return vistor.visit(this, tag);
     }
 }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AListAccessor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AListAccessor.java
index 60d6a2e..2aa4152 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AListAccessor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AListAccessor.java
@@ -1,11 +1,23 @@
 package edu.uci.ics.asterix.runtime.accessors;
 
 import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.types.IAType;
 import edu.uci.ics.asterix.runtime.accessors.base.IBinaryAccessor;
 import edu.uci.ics.asterix.runtime.accessors.visitor.IBinaryAccessorVisitor;
+import edu.uci.ics.asterix.runtime.util.container.IElementFactory;
 
 public class AListAccessor implements IBinaryAccessor {
 
+    public static IElementFactory<IBinaryAccessor, IAType> FACTORY = new IElementFactory<IBinaryAccessor, IAType>() {
+        public IBinaryAccessor createElement(IAType type) {
+            return new AListAccessor();
+        }
+    };
+
+    private AListAccessor() {
+
+    }
+
     @Override
     public byte[] getBytes() {
         // TODO Auto-generated method stub
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/ARecordAccessor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/ARecordAccessor.java
index e8e85ac..6bd798d 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/ARecordAccessor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/ARecordAccessor.java
@@ -32,14 +32,25 @@
 import edu.uci.ics.asterix.runtime.accessors.base.IBinaryAccessor;
 import edu.uci.ics.asterix.runtime.accessors.visitor.IBinaryAccessorVisitor;
 import edu.uci.ics.asterix.runtime.util.ResettableByteArrayOutputStream;
+import edu.uci.ics.asterix.runtime.util.container.IElementFactory;
 import edu.uci.ics.hyracks.api.dataflow.value.INullWriter;
 
 public class ARecordAccessor implements IBinaryAccessor {
 
+    public static IElementFactory<IBinaryAccessor, IAType> FACTORY = new IElementFactory<IBinaryAccessor, IAType>() {
+        public IBinaryAccessor createElement(IAType type) {
+            return new ARecordAccessor((ARecordType) type);
+        }
+    };
+
+    // access results: field names, field types, and field values
     private List<IBinaryAccessor> fieldNames = new ArrayList<IBinaryAccessor>();
     private List<IBinaryAccessor> fieldTypeTags = new ArrayList<IBinaryAccessor>();
     private List<IBinaryAccessor> fieldValues = new ArrayList<IBinaryAccessor>();
 
+    // accessor allocator
+    AccessorAllocator allocator = new AccessorAllocator();
+
     private byte[] typeBuffer = new byte[32768];
     private ResettableByteArrayOutputStream typeBos = new ResettableByteArrayOutputStream();
     private DataOutputStream typeDos = new DataOutputStream(typeBos);
@@ -54,14 +65,18 @@
     private int numberOfSchemaFields;
     private int offsetArrayOffset;
     private int[] fieldOffsets;
-    private int fieldCursor = -1;
     private ATypeTag typeTag;
-    private AFlatValueAccessor nullReference = new AFlatValueAccessor();
+    private IBinaryAccessor nullReference = AFlatValueAccessor.FACTORY.createElement(null);
 
     private byte[] data;
     private int start;
     private int len;
 
+    // nested open field rec type
+    // private static ARecordType nestedOpenRecType = new
+    // ARecordType("nested-open", new String[] {}, new IAType[] {},
+    // true);
+
     public ARecordAccessor(ARecordType inputType) {
         this.inputRecType = inputType;
         IAType[] fieldTypes = inputType.getFieldTypes();
@@ -79,7 +94,7 @@
                 int tagStart = typeBos.size();
                 typeDos.writeByte(ftypeTag.serialize());
                 int tagEnd = typeBos.size();
-                AFlatValueAccessor typeTagReference = new AFlatValueAccessor();
+                IBinaryAccessor typeTagReference = AFlatValueAccessor.FACTORY.createElement(null);
                 typeTagReference.reset(typeBuffer, tagStart, tagEnd - tagStart);
                 fieldTypeTags.add(typeTagReference);
 
@@ -88,7 +103,7 @@
                 typeDos.writeByte(ATypeTag.STRING.serialize());
                 typeDos.writeUTF(fieldNameStrs[i]);
                 int nameEnd = typeBos.size();
-                AFlatValueAccessor typeNameReference = new AFlatValueAccessor();
+                IBinaryAccessor typeNameReference = AFlatValueAccessor.FACTORY.createElement(null);
                 typeNameReference.reset(typeBuffer, nameStart, nameEnd - nameStart);
                 fieldNames.add(typeNameReference);
             }
@@ -109,7 +124,14 @@
     private void reset() {
         typeBos.setByteArray(typeBuffer, closedPartTypeInfoSize);
         dataBos.setByteArray(dataBuffer, 0);
-        fieldCursor = -1;
+        allocator.reset();
+
+        //clean up the returned containers
+        for (int i = fieldNames.size() - 1; i >= numberOfSchemaFields; i--)
+            fieldNames.remove(i);
+        for (int i = fieldTypeTags.size() - 1; i >= numberOfSchemaFields; i--)
+            fieldTypeTags.remove(i);
+        fieldValues.clear();
     }
 
     public void reset(byte[] b, int start, int len) {
@@ -156,14 +178,12 @@
                     offsetArrayOffset += 4;
                 }
                 for (int fieldNumber = 0; fieldNumber < numberOfSchemaFields; fieldNumber++) {
-                    next();
                     if (hasNullableFields) {
                         byte b1 = b[nullBitMapOffset + fieldNumber / 8];
                         int p = 1 << (7 - (fieldNumber % 8));
                         if ((b1 & p) == 0) {
                             // set null value (including type tag inside)
-                            nextFieldValue().reset(nullReference.getBytes(), nullReference.getStartIndex(),
-                                    nullReference.getLength());
+                            fieldValues.add(nullReference);
                             continue;
                         }
                     }
@@ -187,14 +207,15 @@
                     dataDos.writeByte(typeTag.serialize());
                     dataDos.write(b, fieldOffsets[fieldNumber], fieldValueLength);
                     int fend = dataBos.size();
-                    nextFieldValue().reset(dataBuffer, fstart, fend - fstart);
+                    IBinaryAccessor fieldValue = allocator.allocateFieldValue(fieldTypes[fieldNumber]);
+                    fieldValue.reset(dataBuffer, fstart, fend - fstart);
+                    fieldValues.add(fieldValue);
                 }
             }
             if (isExpanded) {
                 int numberOfOpenFields = AInt32SerializerDeserializer.getInt(b, openPartOffset);
                 int fieldOffset = openPartOffset + 4 + (8 * numberOfOpenFields);
                 for (int i = 0; i < numberOfOpenFields; i++) {
-                    next();
                     // set the field name (including a type tag, which is
                     // astring)
                     int fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b, fieldOffset, ATypeTag.STRING,
@@ -203,16 +224,22 @@
                     dataDos.writeByte(ATypeTag.STRING.serialize());
                     dataDos.write(b, fieldOffset, fieldValueLength);
                     int fnend = dataBos.size();
-                    nextFieldName().reset(dataBuffer, fnstart, fnend - fnstart);
+                    IBinaryAccessor fieldName = allocator.allocateFieldName();
+                    fieldName.reset(dataBuffer, fnstart, fnend - fnstart);
+                    fieldNames.add(fieldName);
                     fieldOffset += fieldValueLength;
 
                     // set the field type tag
-                    nextFieldType().reset(b, fieldOffset, 1);
+                    IBinaryAccessor fieldTypeTag = allocator.allocateFieldType();
+                    fieldTypeTag.reset(b, fieldOffset, 1);
+                    fieldTypeTags.add(fieldTypeTag);
                     typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b[fieldOffset]);
 
                     // set the field value (already including type tag)
                     fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(b, fieldOffset, typeTag, true) + 1;
-                    nextFieldValue().reset(b, fieldOffset, fieldValueLength);
+                    IBinaryAccessor fieldValueAccessor = allocator.allocateFieldName();
+                    fieldValueAccessor.reset(b, fieldOffset, fieldValueLength);
+                    fieldValues.add(fieldValueAccessor);
                     fieldOffset += fieldValueLength;
                 }
             }
@@ -221,44 +248,6 @@
         }
     }
 
-    private void next() {
-        fieldCursor++;
-    }
-
-    private IBinaryAccessor nextFieldName() {
-        if (fieldCursor < fieldNames.size()) {
-            return fieldNames.get(fieldCursor);
-        } else {
-            AFlatValueAccessor fieldNameReference = new AFlatValueAccessor();
-            fieldNames.add(fieldNameReference);
-            return fieldNameReference;
-        }
-    }
-
-    private IBinaryAccessor nextFieldType() {
-        if (fieldCursor < fieldTypeTags.size()) {
-            return fieldTypeTags.get(fieldCursor);
-        } else {
-            AFlatValueAccessor fieldTypeReference = new AFlatValueAccessor();
-            fieldTypeTags.add(fieldTypeReference);
-            return fieldTypeReference;
-        }
-    }
-
-    private IBinaryAccessor nextFieldValue() {
-        if (fieldCursor < fieldValues.size()) {
-            return fieldValues.get(fieldCursor);
-        } else {
-            AFlatValueAccessor fieldValueReference = new AFlatValueAccessor();
-            fieldValues.add(fieldValueReference);
-            return fieldValueReference;
-        }
-    }
-
-    public int getCursor() {
-        return fieldCursor;
-    }
-
     public List<IBinaryAccessor> getFieldNames() {
         return fieldNames;
     }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AccessorAllocator.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AccessorAllocator.java
new file mode 100644
index 0000000..a3fd0d7
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/AccessorAllocator.java
@@ -0,0 +1,44 @@
+package edu.uci.ics.asterix.runtime.accessors;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.runtime.accessors.base.IBinaryAccessor;
+import edu.uci.ics.asterix.runtime.util.container.IElementAllocator;
+import edu.uci.ics.asterix.runtime.util.container.ListElementAllocator;
+
+public class AccessorAllocator {
+
+    private IElementAllocator<IBinaryAccessor, IAType> flatArtifactAllocator = new ListElementAllocator<IBinaryAccessor, IAType>(
+            AFlatValueAccessor.FACTORY);
+    private IElementAllocator<IBinaryAccessor, IAType> nestedRecValueAllocator = new ListElementAllocator<IBinaryAccessor, IAType>(
+            ARecordAccessor.FACTORY);
+    private IElementAllocator<IBinaryAccessor, IAType> nestedListValueAllocator = new ListElementAllocator<IBinaryAccessor, IAType>(
+            AListAccessor.FACTORY);
+
+    public IBinaryAccessor allocateFieldName() {
+        return flatArtifactAllocator.allocate(null);
+    }
+
+    public IBinaryAccessor allocateFieldType() {
+        return flatArtifactAllocator.allocate(null);
+    }
+
+    public IBinaryAccessor allocateFieldValue(IAType type) {
+        if (type.getTypeTag().equals(ATypeTag.RECORD))
+            return nestedRecValueAllocator.allocate(type);
+        else if (type.getTypeTag().equals(ATypeTag.UNORDEREDLIST) || type.getTypeTag().equals(ATypeTag.ORDEREDLIST))
+            return nestedListValueAllocator.allocate(type);
+        else
+            return flatArtifactAllocator.allocate(null);
+    }
+
+    public IBinaryAccessor allocateNestedListValue(IAType type) {
+        return nestedListValueAllocator.allocate(type);
+    }
+
+    public void reset() {
+        flatArtifactAllocator.reset();
+        nestedRecValueAllocator.reset();
+        nestedListValueAllocator.reset();
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/cast/ACastVisitor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/cast/ACastVisitor.java
index 6e874cf..c84f28e 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/cast/ACastVisitor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/cast/ACastVisitor.java
@@ -9,20 +9,21 @@
 import edu.uci.ics.asterix.runtime.accessors.AFlatValueAccessor;
 import edu.uci.ics.asterix.runtime.accessors.AListAccessor;
 import edu.uci.ics.asterix.runtime.accessors.ARecordAccessor;
+import edu.uci.ics.asterix.runtime.accessors.base.IBinaryAccessor;
 import edu.uci.ics.asterix.runtime.accessors.visitor.IBinaryAccessorVisitor;
 import edu.uci.ics.hyracks.algebricks.common.utils.Triple;
 
-public class ACastVisitor implements IBinaryAccessorVisitor<Void, Triple<ARecordAccessor, IAType, Boolean>> {
+public class ACastVisitor implements IBinaryAccessorVisitor<Void, Triple<IBinaryAccessor, IAType, Boolean>> {
 
-    private Map<ARecordAccessor, ARecordCaster> raccessorToCaster = new HashMap<ARecordAccessor, ARecordCaster>();
+    private Map<IBinaryAccessor, ARecordCaster> raccessorToCaster = new HashMap<IBinaryAccessor, ARecordCaster>();
 
     @Override
-    public Void visit(AListAccessor accessor, Triple<ARecordAccessor, IAType, Boolean> arg) {
+    public Void visit(AListAccessor accessor, Triple<IBinaryAccessor, IAType, Boolean> arg) {
         return null;
     }
 
     @Override
-    public Void visit(ARecordAccessor accessor, Triple<ARecordAccessor, IAType, Boolean> arg) throws AsterixException {
+    public Void visit(ARecordAccessor accessor, Triple<IBinaryAccessor, IAType, Boolean> arg) throws AsterixException {
         ARecordCaster caster = raccessorToCaster.get(accessor);
         if (caster == null) {
             caster = new ARecordCaster();
@@ -37,7 +38,9 @@
     }
 
     @Override
-    public Void visit(AFlatValueAccessor accessor, Triple<ARecordAccessor, IAType, Boolean> arg) {
+    public Void visit(AFlatValueAccessor accessor, Triple<IBinaryAccessor, IAType, Boolean> arg) {
+        //set the pointer for result
+        arg.first.reset(accessor.getBytes(), accessor.getStartIndex(), accessor.getLength());
         return null;
     }
 
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/cast/ARecordCaster.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/cast/ARecordCaster.java
index e7a35bd..8073c91 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/cast/ARecordCaster.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/accessors/cast/ARecordCaster.java
@@ -58,8 +58,8 @@
     private DataOutputStream dos = new DataOutputStream(bos);
 
     private RecordBuilder recBuilder = new RecordBuilder();
-    private AFlatValueAccessor nullReference = new AFlatValueAccessor();
-    private AFlatValueAccessor nullTypeTag = new AFlatValueAccessor();
+    private IBinaryAccessor nullReference = AFlatValueAccessor.FACTORY.createElement(null);
+    private IBinaryAccessor nullTypeTag = AFlatValueAccessor.FACTORY.createElement(null);
 
     private int numInputFields = 0;
     private IBinaryComparator fieldNameComparator = PointableBinaryComparatorFactory.of(UTF8StringPointable.FACTORY)
@@ -86,12 +86,12 @@
         }
     }
 
-    public void castRecord(ARecordAccessor recordAccessor, ARecordAccessor resultAccessor, ARecordType reqType,
+    public void castRecord(ARecordAccessor recordAccessor, IBinaryAccessor resultAccessor, ARecordType reqType,
             ACastVisitor visitor) throws IOException {
         List<IBinaryAccessor> fieldNames = recordAccessor.getFieldNames();
         List<IBinaryAccessor> fieldTypeTags = recordAccessor.getFieldTypeTags();
         List<IBinaryAccessor> fieldValues = recordAccessor.getFieldValues();
-        numInputFields = recordAccessor.getCursor() + 1;
+        numInputFields = fieldNames.size();
 
         if (openFields == null || numInputFields > openFields.length) {
             openFields = new boolean[numInputFields];
@@ -147,7 +147,7 @@
             int tagStart = bos.size();
             dos.writeByte(ftypeTag.serialize());
             int tagEnd = bos.size();
-            AFlatValueAccessor typeTagPointable = new AFlatValueAccessor();
+            IBinaryAccessor typeTagPointable = AFlatValueAccessor.FACTORY.createElement(null);
             typeTagPointable.reset(buffer, tagStart, tagEnd - tagStart);
             reqFieldTypeTags.add(typeTagPointable);
 
@@ -156,7 +156,7 @@
             dos.write(ATypeTag.STRING.serialize());
             dos.writeUTF(fname);
             int nameEnd = bos.size();
-            AFlatValueAccessor typeNamePointable = new AFlatValueAccessor();
+            IBinaryAccessor typeNamePointable = AFlatValueAccessor.FACTORY.createElement(null);
             typeNamePointable.reset(buffer, nameStart, nameEnd - nameStart);
             reqFieldNames.add(typeNamePointable);
         }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/CastRecordDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/CastRecordDescriptor.java
index d193e85..c82bb9b 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/CastRecordDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/CastRecordDescriptor.java
@@ -8,6 +8,7 @@
 import edu.uci.ics.asterix.om.types.ARecordType;
 import edu.uci.ics.asterix.om.types.IAType;
 import edu.uci.ics.asterix.runtime.accessors.ARecordAccessor;
+import edu.uci.ics.asterix.runtime.accessors.base.IBinaryAccessor;
 import edu.uci.ics.asterix.runtime.accessors.cast.ACastVisitor;
 import edu.uci.ics.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -60,7 +61,7 @@
                     final ARecordAccessor recAccessor = new ARecordAccessor(inputType);
                     final ARecordAccessor resultAccessor = new ARecordAccessor(reqType);
                     final ACastVisitor castVisitor = new ACastVisitor();
-                    final Triple<ARecordAccessor, IAType, Boolean> arg = new Triple<ARecordAccessor, IAType, Boolean>(
+                    final Triple<IBinaryAccessor, IAType, Boolean> arg = new Triple<IBinaryAccessor, IAType, Boolean>(
                             resultAccessor, reqType, Boolean.FALSE);
 
                     @Override
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/IElementAllocator.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/IElementAllocator.java
new file mode 100644
index 0000000..bb98374
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/IElementAllocator.java
@@ -0,0 +1,8 @@
+package edu.uci.ics.asterix.runtime.util.container;
+
+public interface IElementAllocator<E, T> {
+
+    public E allocate(T arg);
+
+    public void reset();
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/IElementFactory.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/IElementFactory.java
new file mode 100644
index 0000000..bc1b525
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/IElementFactory.java
@@ -0,0 +1,6 @@
+package edu.uci.ics.asterix.runtime.util.container;
+
+public interface IElementFactory<E, T> {
+
+    public E createElement(T arg);
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/ListElementAllocator.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/ListElementAllocator.java
new file mode 100644
index 0000000..442f4cb
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/container/ListElementAllocator.java
@@ -0,0 +1,30 @@
+package edu.uci.ics.asterix.runtime.util.container;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ListElementAllocator<E, T> implements IElementAllocator<E, T> {
+
+    private IElementFactory<E, T> factory;
+    private List<E> pool = new ArrayList<E>();
+    private int cursor = -1;
+
+    public ListElementAllocator(IElementFactory<E, T> factory) {
+        this.factory = factory;
+    }
+
+    public E allocate(T arg) {
+        cursor++;
+        if (cursor < pool.size()) {
+            return pool.get(cursor);
+        } else {
+            E element = factory.createElement(arg);
+            pool.add(element);
+            return element;
+        }
+    }
+
+    public void reset() {
+        cursor = -1;
+    }
+}