19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.database;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Does a join on two cursors using the specified columns. The cursors must already
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be sorted on each of the specified columns in ascending order. This joiner only
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * supports the case where the tuple of key column values is unique.
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Typical usage:
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CursorJoiner joiner = new CursorJoiner(cursorA, keyColumnsofA, cursorB, keyColumnsofB);
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for (CursorJointer.Result joinerResult : joiner) {
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     switch (joinerResult) {
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         case LEFT:
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             // handle case where a row in cursorA is unique
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             break;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         case RIGHT:
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             // handle case where a row in cursorB is unique
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             break;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         case BOTH:
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             // handle case where a row with the same key is in both cursors
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *             break;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     }
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre>
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class CursorJoiner
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements Iterator<CursorJoiner.Result>, Iterable<CursorJoiner.Result> {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Cursor mCursorLeft;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Cursor mCursorRight;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mCompareResultIsValid;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Result mCompareResult;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int[] mColumnsLeft;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int[] mColumnsRight;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String[] mValues;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The result of a call to next().
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public enum Result {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The row currently pointed to by the left cursor is unique */
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RIGHT,
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The row currently pointed to by the right cursor is unique */
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LEFT,
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The rows pointed to by both cursors are the same */
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BOTH
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Initializes the CursorJoiner and resets the cursors to the first row. The left and right
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * column name arrays must have the same number of columns.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cursorLeft The left cursor to compare
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param columnNamesLeft The column names to compare from the left cursor
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cursorRight The right cursor to compare
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param columnNamesRight The column names to compare from the right cursor
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CursorJoiner(
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Cursor cursorLeft, String[] columnNamesLeft,
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Cursor cursorRight, String[] columnNamesRight) {
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (columnNamesLeft.length != columnNamesRight.length) {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException(
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "you must have the same number of columns on the left and right, "
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + columnNamesLeft.length + " != " + columnNamesRight.length);
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCursorLeft = cursorLeft;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCursorRight = cursorRight;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCursorLeft.moveToFirst();
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCursorRight.moveToFirst();
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCompareResultIsValid = false;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColumnsLeft = buildColumnIndiciesArray(cursorLeft, columnNamesLeft);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColumnsRight = buildColumnIndiciesArray(cursorRight, columnNamesRight);
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mValues = new String[mColumnsLeft.length * 2];
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Iterator<Result> iterator() {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Lookup the indicies of the each column name and return them in an array.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cursor the cursor that contains the columns
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param columnNames the array of names to lookup
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return an array of column indices
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int[] buildColumnIndiciesArray(Cursor cursor, String[] columnNames) {
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int[] columns = new int[columnNames.length];
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < columnNames.length; i++) {
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            columns[i] = cursor.getColumnIndexOrThrow(columnNames[i]);
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return columns;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns whether or not there are more rows to compare using next().
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if there are more rows to compare
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasNext() {
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCompareResultIsValid) {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (mCompareResult) {
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case BOTH:
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return !mCursorLeft.isLast() || !mCursorRight.isLast();
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case LEFT:
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return !mCursorLeft.isLast() || !mCursorRight.isAfterLast();
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case RIGHT:
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return !mCursorLeft.isAfterLast() || !mCursorRight.isLast();
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                default:
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new IllegalStateException("bad value for mCompareResult, "
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + mCompareResult);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return !mCursorLeft.isAfterLast() || !mCursorRight.isAfterLast();
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the comparison result of the next row from each cursor. If one cursor
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * has no more rows but the other does then subsequent calls to this will indicate that
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the remaining rows are unique.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The caller must check that hasNext() returns true before calling this.
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Once next() has been called the cursors specified in the result of the call to
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * next() are guaranteed to point to the row that was indicated. Reading values
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from the cursor that was not indicated in the call to next() will result in
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * undefined behavior.
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return LEFT, if the row pointed to by the left cursor is unique, RIGHT
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   if the row pointed to by the right cursor is unique, BOTH if the rows in both
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   cursors are the same.
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Result next() {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!hasNext()) {
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("you must only call next() when hasNext() is true");
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        incrementCursors();
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert hasNext();
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasLeft = !mCursorLeft.isAfterLast();
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasRight = !mCursorRight.isAfterLast();
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hasLeft && hasRight) {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            populateValues(mValues, mCursorLeft, mColumnsLeft, 0 /* start filling at index 0 */);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            populateValues(mValues, mCursorRight, mColumnsRight, 1 /* start filling at index 1 */);
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (compareStrings(mValues)) {
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case -1:
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCompareResult = Result.LEFT;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case 0:
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCompareResult = Result.BOTH;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case 1:
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCompareResult = Result.RIGHT;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (hasLeft) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCompareResult = Result.LEFT;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else  {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            assert hasRight;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCompareResult = Result.RIGHT;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCompareResultIsValid = true;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCompareResult;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void remove() {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw new UnsupportedOperationException("not implemented");
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Reads the strings from the cursor that are specifed in the columnIndicies
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * array and saves them in values beginning at startingIndex, skipping a slot
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for each value. If columnIndicies has length 3 and startingIndex is 1, the
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * values will be stored in slots 1, 3, and 5.
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values the String[] to populate
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cursor the cursor from which to read
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param columnIndicies the indicies of the values to read from the cursor
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startingIndex the slot in which to start storing values, and must be either 0 or 1.
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void populateValues(String[] values, Cursor cursor, int[] columnIndicies,
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int startingIndex) {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assert startingIndex == 0 || startingIndex == 1;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < columnIndicies.length; i++) {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            values[startingIndex + i*2] = cursor.getString(columnIndicies[i]);
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Increment the cursors past the rows indicated in the most recent call to next().
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This will only have an affect once per call to next().
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void incrementCursors() {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCompareResultIsValid) {
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (mCompareResult) {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case LEFT:
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCursorLeft.moveToNext();
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case RIGHT:
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCursorRight.moveToNext();
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case BOTH:
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCursorLeft.moveToNext();
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCursorRight.moveToNext();
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCompareResultIsValid = false;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Compare the values. Values contains n pairs of strings. If all the pairs of strings match
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * then returns 0. Otherwise returns the comparison result of the first non-matching pair
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of values, -1 if the first of the pair is less than the second of the pair or 1 if it
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is greater.
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param values the n pairs of values to compare
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return -1, 0, or 1 as described above.
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int compareStrings(String... values) {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((values.length % 2) != 0) {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("you must specify an even number of values");
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int index = 0; index < values.length; index+=2) {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (values[index] == null) {
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (values[index+1] == null) continue;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return -1;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (values[index+1] == null) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 1;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int comp = values[index].compareTo(values[index+1]);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (comp != 0) {
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return comp < 0 ? -1 : 1;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
266