Merge "Add hashCode()."
diff --git a/java/com/android/vcard/VCardInterpreterCollection.java b/java/com/android/vcard/VCardInterpreterCollection.java
deleted file mode 100644
index 9a50ab7..0000000
--- a/java/com/android/vcard/VCardInterpreterCollection.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed 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 com.android.vcard;
-
-import java.util.Collection;
-
-/**
- * The {@link VCardInterpreter} implementation which aggregates more than one
- * {@link VCardInterpreter} objects and make a user object treat them as one
- * {@link VCardInterpreter} object.
- * @deprecated {@link VCardParser} has native support for multiple interpreter now.
- */
-public final class VCardInterpreterCollection implements VCardInterpreter {
-    private final Collection<VCardInterpreter> mInterpreterCollection;
-
-    public VCardInterpreterCollection(Collection<VCardInterpreter> interpreterCollection) {
-        mInterpreterCollection = interpreterCollection;
-    }
-
-    public Collection<VCardInterpreter> getCollection() {
-        return mInterpreterCollection;
-    }
-
-    @Override
-    public void onVCardStarted() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.onVCardStarted();
-        }
-    }
-
-    @Override
-    public void onVCardEnded() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.onVCardEnded();
-        }
-    }
-
-    @Override
-    public void onEntryStarted() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.onEntryStarted();
-        }
-    }
-
-    @Override
-    public void onEntryEnded() {
-        for (VCardInterpreter builder : mInterpreterCollection) {
-            builder.onEntryEnded();
-        }
-    }
-
-    @Override
-    public void onPropertyCreated(VCardProperty property) {
-        for (VCardInterpreter interpreter : mInterpreterCollection) {
-            interpreter.onPropertyCreated(property);
-        }
-    }
-}
diff --git a/java/com/android/vcard/VCardParser.java b/java/com/android/vcard/VCardParser.java
index 584e5dc..2cc4932 100644
--- a/java/com/android/vcard/VCardParser.java
+++ b/java/com/android/vcard/VCardParser.java
@@ -21,24 +21,59 @@
 import java.io.InputStream;
 
 public abstract class VCardParser {
+
     /**
-     * <p>
-     * Parses the given stream and send the vCard data into {@link VCardInterpreter}.
-     * </p>.
-     * <p>
-     * Note that vCard 2.1 specification allows "CHARSET" parameter, and some career sets
-     * local encoding to it. For example, Japanese phone career uses Shift_JIS, which is
-     * formally allowed in vCard 2.1, but not allowed in vCard 3.0. In vCard 2.1,
-     * In some exreme case, it is allowed for vCard to have different charsets in one vCard.
-     * </p>
-     * <p>
-     * We recommend you use {@link VCardSourceDetector} and detect which kind of source the
-     * vCard comes from and explicitly specify a charset using the result.
-     * </p>
+     * Registers one {@link VCardInterpreter} instance, which receives events along with
+     * vCard parsing.
+     *
+     * @param interpreter
+     */
+    public abstract void addInterpreter(VCardInterpreter interpreter);
+
+    /**
+     * <p>Parses a whole InputStream as a vCard file and lets registered {@link VCardInterpreter}
+     * instances handle callbacks.</p>
+     *
+     * <p>This method reads a whole InputStream. If you just want to parse one vCard entry inside
+     * a vCard file with multiple entries, try {@link #parseOne(InputStream)}.</p>
      *
      * @param is The source to parse.
-     * @param interpreter A {@link VCardInterpreter} object which used to construct data.
      * @throws IOException, VCardException
+     */
+    public abstract void parse(InputStream is) throws IOException, VCardException;
+
+    /**
+     * <p>Parses the first vCard entry in InputStream and lets registered {@link VCardInterpreter}
+     * instances handle callbacks.</p>
+     *
+     * <p>This method finishes itself when the first entry ended.</p>
+     *
+     * <p>Note that, registered {@link VCardInterpreter} may still see multiple
+     * {@link VCardInterpreter#onEntryStarted()} / {@link VCardInterpreter#onEntryEnded()} calls
+     * even with this method.</p>
+     *
+     * <p>This happens when the first entry contains nested vCards, which is allowed in vCard 2.1.
+     * See the following example.</p>
+     *
+     * <code>
+     * BEGIN:VCARD
+     * N:a
+     * BEGIN:VCARD
+     * N:b
+     * END:VCARD
+     * END:VCARD
+     * </code>
+     *
+     * <p>With this vCard, registered interpreters will grab two
+     * {@link VCardInterpreter#onEntryStarted()} and {@link VCardInterpreter#onEntryEnded()}
+     * calls. Callers should handle the situation by themselves.</p>
+     *
+     * @param is  The source to parse.
+     * @throws IOException, VCardException
+     */
+    public abstract void parseOne(InputStream is) throws IOException, VCardException;
+
+    /**
      * @deprecated use {@link #addInterpreter(VCardInterpreter)} and
      * {@link #parse(InputStream)}
      */
@@ -49,9 +84,6 @@
         parse(is);
     }
 
-    public abstract void addInterpreter(VCardInterpreter interpreter);
-    public abstract void parse(InputStream is) throws IOException, VCardException;
-
     /**
      * <p>
      * Cancel parsing vCard. Useful when you want to stop the parse in the other threads.
diff --git a/java/com/android/vcard/VCardParserImpl_V21.java b/java/com/android/vcard/VCardParserImpl_V21.java
index 2cedff9..7a24928 100644
--- a/java/com/android/vcard/VCardParserImpl_V21.java
+++ b/java/com/android/vcard/VCardParserImpl_V21.java
@@ -31,7 +31,6 @@
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -163,26 +162,6 @@
     }
 
     /**
-     * <p>
-     * Parses the file at the given position.
-     * </p>
-     */
-    // <pre class="prettyprint">vcard_file = [wsls] vcard [wsls]</pre>
-    protected void parseVCardFile() throws IOException, VCardException {
-        while (true) {
-            synchronized (this) {
-                if (mCanceled) {
-                    Log.i(LOG_TAG, "Cancel request has come. exitting parse operation.");
-                    break;
-                }
-            }
-            if (!parseOneVCard()) {
-                break;
-            }
-        }
-    }
-
-    /**
      * @return true when a given property name is a valid property name.
      */
     protected boolean isValidPropertyName(final String propertyName) {
@@ -230,6 +209,7 @@
      *         items *CRLF
      *         "END" [ws] ":" [ws] "VCARD"
      * </code>
+     * @return False when reaching end of file.
      */
     private boolean parseOneVCard() throws IOException, VCardException {
         // reset for this entire vCard.
@@ -940,7 +920,38 @@
         for (VCardInterpreter interpreter : mInterpreterList) {
             interpreter.onVCardStarted();
         }
-        parseVCardFile();
+
+        // vcard_file = [wsls] vcard [wsls]
+        while (true) {
+            synchronized (this) {
+                if (mCanceled) {
+                    Log.i(LOG_TAG, "Cancel request has come. exitting parse operation.");
+                    break;
+                }
+            }
+            if (!parseOneVCard()) {
+                break;
+            }
+        }
+
+        for (VCardInterpreter interpreter : mInterpreterList) {
+            interpreter.onVCardEnded();
+        }
+    }
+
+    public void parseOne(InputStream is) throws IOException, VCardException {
+        if (is == null) {
+            throw new NullPointerException("InputStream must not be null.");
+        }
+
+        final InputStreamReader tmpReader = new InputStreamReader(is, mIntermediateCharset);
+        mReader = new CustomBufferedReader(tmpReader);
+
+        final long start = System.currentTimeMillis();
+        for (VCardInterpreter interpreter : mInterpreterList) {
+            interpreter.onVCardStarted();
+        }
+        parseOneVCard();
         for (VCardInterpreter interpreter : mInterpreterList) {
             interpreter.onVCardEnded();
         }
diff --git a/java/com/android/vcard/VCardParser_V21.java b/java/com/android/vcard/VCardParser_V21.java
index 3583a68..d0887af 100644
--- a/java/com/android/vcard/VCardParser_V21.java
+++ b/java/com/android/vcard/VCardParser_V21.java
@@ -109,6 +109,11 @@
     }
 
     @Override
+    public void parseOne(InputStream is) throws IOException, VCardException {
+        mVCardParserImpl.parseOne(is);
+    }
+
+    @Override
     public void cancel() {
         mVCardParserImpl.cancel();
     }
diff --git a/java/com/android/vcard/VCardParser_V30.java b/java/com/android/vcard/VCardParser_V30.java
index 905aee4..c7ae8c8 100644
--- a/java/com/android/vcard/VCardParser_V30.java
+++ b/java/com/android/vcard/VCardParser_V30.java
@@ -88,6 +88,11 @@
     }
 
     @Override
+    public void parseOne(InputStream is) throws IOException, VCardException {
+        mVCardParserImpl.parseOne(is);
+    }
+
+    @Override
     public void cancel() {
         mVCardParserImpl.cancel();
     }
diff --git a/java/com/android/vcard/VCardParser_V40.java b/java/com/android/vcard/VCardParser_V40.java
index 71c8c20..de9c2a1 100644
--- a/java/com/android/vcard/VCardParser_V40.java
+++ b/java/com/android/vcard/VCardParser_V40.java
@@ -76,6 +76,11 @@
     }
 
     @Override
+    public void parseOne(InputStream is) throws IOException, VCardException {
+        mVCardParserImpl.parseOne(is);
+    }
+
+    @Override
     public void cancel() {
         mVCardParserImpl.cancel();
     }
diff --git a/tests/src/com/android/vcard/tests/VCardInterpreterTests.java b/tests/src/com/android/vcard/tests/VCardInterpreterTests.java
deleted file mode 100644
index 3e0f0b5..0000000
--- a/tests/src/com/android/vcard/tests/VCardInterpreterTests.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed 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 com.android.vcard.tests;
-
-import com.android.vcard.VCardInterpreter;
-import com.android.vcard.VCardParser;
-import com.android.vcard.VCardParser_V21;
-import com.android.vcard.VCardProperty;
-import com.android.vcard.exception.VCardException;
-
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class VCardInterpreterTests extends AndroidTestCase {
-    private enum Order {
-        START,
-        END,
-        START_ENTRY,
-        END_ENTRY,
-        PROPERTY_CREATED,
-    }
-
-    private class MockVCardInterpreter implements VCardInterpreter {
-        private final List<Order> mHistory = new ArrayList<Order>();
-        private final List<Order> mExpectedOrder = new ArrayList<Order>();
-
-        public MockVCardInterpreter addExpectedOrder(Order order) {
-            mExpectedOrder.add(order);
-            return this;
-        }
-
-        private void inspectOrder(Order order) {
-            mHistory.add(order);
-            final Order top = mExpectedOrder.get(0);
-            assertEquals(top, order);
-            mExpectedOrder.remove(0);
-        }
-
-        public void verify() {
-            assertTrue(String.format("Remaining: " + Arrays.toString(mExpectedOrder.toArray())),
-                    mExpectedOrder.isEmpty());
-        }
-
-        @Override
-        public void onVCardStarted() {
-            inspectOrder(Order.START);
-        }
-
-        @Override
-        public void onVCardEnded() {
-            inspectOrder(Order.END);
-        }
-
-        @Override
-        public void onEntryStarted() {
-            inspectOrder(Order.START_ENTRY);
-        }
-
-        @Override
-        public void onEntryEnded() {
-            inspectOrder(Order.END_ENTRY);
-        }
-
-        @Override
-        public void onPropertyCreated(VCardProperty property) {
-            inspectOrder(Order.PROPERTY_CREATED);
-        }
-    }
-
-    public void testSimple() throws IOException, VCardException {
-        InputStream inputStream = getContext().getResources().openRawResource(R.raw.v21_simple_1);
-        VCardParser parser = new VCardParser_V21();
-        MockVCardInterpreter interpreter = new MockVCardInterpreter();
-        interpreter.addExpectedOrder(Order.START)
-                .addExpectedOrder(Order.START_ENTRY)
-                .addExpectedOrder(Order.PROPERTY_CREATED)
-                .addExpectedOrder(Order.END_ENTRY)
-                .addExpectedOrder(Order.END);
-        parser.addInterpreter(interpreter);
-        parser.parse(inputStream);
-        interpreter.verify();
-    }
-
-    public void testNest() throws IOException, VCardException {
-        InputStream inputStream = getContext().getResources().openRawResource(R.raw.v21_nest);
-        VCardParser parser = new VCardParser_V21();
-        MockVCardInterpreter interpreter = new MockVCardInterpreter();
-        interpreter.addExpectedOrder(Order.START)
-                .addExpectedOrder(Order.START_ENTRY)
-                .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
-                .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
-                .addExpectedOrder(Order.START_ENTRY)  // First nested vCard begins
-                .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
-                .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
-                .addExpectedOrder(Order.END_ENTRY)  // First nested vCard ends
-                .addExpectedOrder(Order.START_ENTRY)  // Second nested vCard begins
-                .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
-                .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
-                .addExpectedOrder(Order.END_ENTRY)  // Second nested vCard ends
-                .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
-                .addExpectedOrder(Order.END_ENTRY)
-                .addExpectedOrder(Order.END);
-        parser.addInterpreter(interpreter);
-        parser.parse(inputStream);
-        interpreter.verify();
-    }
-}
\ No newline at end of file
diff --git a/tests/src/com/android/vcard/tests/VCardParserTests.java b/tests/src/com/android/vcard/tests/VCardParserTests.java
new file mode 100644
index 0000000..9b65593
--- /dev/null
+++ b/tests/src/com/android/vcard/tests/VCardParserTests.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed 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 com.android.vcard.tests;
+
+import com.android.vcard.VCardInterpreter;
+import com.android.vcard.VCardParser;
+import com.android.vcard.VCardParser_V21;
+import com.android.vcard.VCardProperty;
+import com.android.vcard.exception.VCardException;
+
+import android.test.AndroidTestCase;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tests for basic {@link VCardParser} capability (e.g. if it calls callbacks
+ * in {@link VCardInterpreter}}.
+ */
+public class VCardParserTests extends AndroidTestCase {
+    private enum Order {
+        START,
+        END,
+        START_ENTRY,
+        END_ENTRY,
+        PROPERTY_CREATED,
+    }
+
+    private class MockVCardInterpreter implements VCardInterpreter {
+        private final List<Order> mHistory = new ArrayList<Order>();
+        private final List<Order> mExpectedOrder = new ArrayList<Order>();
+
+        public MockVCardInterpreter addExpectedOrder(Order order) {
+            mExpectedOrder.add(order);
+            return this;
+        }
+
+        private void inspectOrder(Order order) {
+            mHistory.add(order);
+            final Order top = mExpectedOrder.get(0);
+            assertEquals(top, order);
+            mExpectedOrder.remove(0);
+        }
+
+        public void verify() {
+            assertTrue(String.format("Remaining: " + Arrays.toString(mExpectedOrder.toArray())),
+                    mExpectedOrder.isEmpty());
+        }
+
+        @Override
+        public void onVCardStarted() {
+            inspectOrder(Order.START);
+        }
+
+        @Override
+        public void onVCardEnded() {
+            inspectOrder(Order.END);
+        }
+
+        @Override
+        public void onEntryStarted() {
+            inspectOrder(Order.START_ENTRY);
+        }
+
+        @Override
+        public void onEntryEnded() {
+            inspectOrder(Order.END_ENTRY);
+        }
+
+        @Override
+        public void onPropertyCreated(VCardProperty property) {
+            inspectOrder(Order.PROPERTY_CREATED);
+        }
+    }
+
+    public void testSimple() throws IOException, VCardException {
+        InputStream inputStream = getContext().getResources().openRawResource(R.raw.v21_simple_1);
+        try {
+            VCardParser parser = new VCardParser_V21();
+            MockVCardInterpreter interpreter = new MockVCardInterpreter();
+            interpreter.addExpectedOrder(Order.START)
+                    .addExpectedOrder(Order.START_ENTRY)
+                    .addExpectedOrder(Order.PROPERTY_CREATED)
+                    .addExpectedOrder(Order.END_ENTRY)
+                    .addExpectedOrder(Order.END);
+            parser.addInterpreter(interpreter);
+            parser.parse(inputStream);
+            interpreter.verify();
+        } finally {
+            inputStream.close();
+        }
+    }
+
+    public void testNest() throws IOException, VCardException {
+        InputStream inputStream = getContext().getResources().openRawResource(R.raw.v21_nest);
+        try {
+            VCardParser parser = new VCardParser_V21();
+            MockVCardInterpreter interpreter = new MockVCardInterpreter();
+            interpreter.addExpectedOrder(Order.START)
+                    .addExpectedOrder(Order.START_ENTRY)
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
+                    .addExpectedOrder(Order.START_ENTRY)  // First nested vCard begins
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
+                    .addExpectedOrder(Order.END_ENTRY)  // First nested vCard ends
+                    .addExpectedOrder(Order.START_ENTRY)  // Second nested vCard begins
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
+                    .addExpectedOrder(Order.END_ENTRY)  // Second nested vCard ends
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.END_ENTRY)
+                    .addExpectedOrder(Order.END);
+            parser.addInterpreter(interpreter);
+            parser.parse(inputStream);
+            interpreter.verify();
+        } finally {
+            inputStream.close();
+        }
+    }
+
+    /**
+     * Tests if {@link VCardParser#parse(InputStream)} parses the whole vCard file and
+     * {@link VCardParser#parseOne(InputStream)} parses just first entry of a vCard file
+     * with multiple vCard entries.
+     */
+    public void testParseOne() throws IOException, VCardException {
+        InputStream inputStream =
+                getContext().getResources().openRawResource(R.raw.v21_multiple_entry);
+        try {
+            VCardParser parser = new VCardParser_V21();
+            MockVCardInterpreter interpreter = new MockVCardInterpreter();
+            interpreter.addExpectedOrder(Order.START)
+                    .addExpectedOrder(Order.START_ENTRY)
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For SOUND
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.END_ENTRY)
+                    .addExpectedOrder(Order.START_ENTRY)
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For SOUND
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.END_ENTRY)
+                    .addExpectedOrder(Order.START_ENTRY)
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For SOUND
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.END_ENTRY)
+                    .addExpectedOrder(Order.END);
+            parser.addInterpreter(interpreter);
+            // Use parse() to check we
+            parser.parse(inputStream);
+            interpreter.verify();
+        } finally {
+            inputStream.close();
+        }
+
+        inputStream = getContext().getResources().openRawResource(R.raw.v21_multiple_entry);
+        try {
+            VCardParser parser = new VCardParser_V21();
+            MockVCardInterpreter interpreter = new MockVCardInterpreter();
+            interpreter.addExpectedOrder(Order.START)
+                    .addExpectedOrder(Order.START_ENTRY)
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For VERSION
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For N
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For SOUND
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.PROPERTY_CREATED)  // For TEL
+                    .addExpectedOrder(Order.END_ENTRY)
+                    .addExpectedOrder(Order.END);
+            parser.addInterpreter(interpreter);
+            parser.parseOne(inputStream);
+            interpreter.verify();
+        } finally {
+            inputStream.close();
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/vcard/tests/VCardTestRunner.java b/tests/src/com/android/vcard/tests/VCardTestRunner.java
index 2409339..e8ccae9 100644
--- a/tests/src/com/android/vcard/tests/VCardTestRunner.java
+++ b/tests/src/com/android/vcard/tests/VCardTestRunner.java
@@ -28,7 +28,7 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(VCardEntryTests.class);
-        suite.addTestSuite(VCardInterpreterTests.class);
+        suite.addTestSuite(VCardParserTests.class);
         suite.addTestSuite(VCardUtilsTests.class);
         suite.addTestSuite(VCardTestUtilsTests.class);
         suite.addTestSuite(VCardImporterTests.class);
diff --git a/tests/src/com/android/vcard/tests/testutils/VCardVerifier.java b/tests/src/com/android/vcard/tests/testutils/VCardVerifier.java
index e529e71..b07564c 100644
--- a/tests/src/com/android/vcard/tests/testutils/VCardVerifier.java
+++ b/tests/src/com/android/vcard/tests/testutils/VCardVerifier.java
@@ -19,7 +19,6 @@
 import com.android.vcard.VCardConfig;
 import com.android.vcard.VCardEntryConstructor;
 import com.android.vcard.VCardInterpreter;
-import com.android.vcard.VCardInterpreterCollection;
 import com.android.vcard.VCardParser;
 import com.android.vcard.VCardUtils;
 import com.android.vcard.exception.VCardException;
@@ -233,30 +232,20 @@
      * Used both from {@link #verifyForImportTest()} and from {@link #verifyForExportTest()}.
      */
     private void verifyWithInputStream(InputStream is) throws IOException {
-        final VCardInterpreter interpreter;
-        if (mContentValuesVerifier != null) {
-            final VCardEntryConstructor constructor = new VCardEntryConstructor(mVCardType);
-            constructor.addEntryHandler(mContentValuesVerifier);
-            if (mPropertyNodesVerifier != null) {
-                interpreter = new VCardInterpreterCollection(Arrays.asList(
-                        mPropertyNodesVerifier, constructor));
-            } else {
-                interpreter = constructor;
-            }
-        } else {
-            if (mPropertyNodesVerifier != null) {
-                interpreter = mPropertyNodesVerifier;
-            } else {
-                interpreter = null;
-            }
-        }
-
         try {
             // Note: we must not specify charset toward vCard parsers. This code checks whether
             // those parsers are able to encode given binary without any extra information for
             // charset.
             final VCardParser parser = VCardUtils.getAppropriateParser(mVCardType);
-            parser.parse(is, interpreter);
+            if (mContentValuesVerifier != null) {
+                final VCardEntryConstructor constructor = new VCardEntryConstructor(mVCardType);
+                constructor.addEntryHandler(mContentValuesVerifier);
+                parser.addInterpreter(constructor);
+            }
+            if (mPropertyNodesVerifier != null) {
+                parser.addInterpreter(mPropertyNodesVerifier);
+            }
+            parser.parse(is);
         } catch (VCardException e) {
             Log.e(LOG_TAG, "VCardException", e);
             AndroidTestCase.fail("Unexpected VCardException: " + e.getMessage());