1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.database; 18 19 /** 20 * A convenience class that lets you present an array of Cursors as a single linear Cursor. 21 * The schema of the cursors presented is entirely up to the creator of the MergeCursor, and 22 * may be different if that is desired. Calls to getColumns, getColumnIndex, etc will return the 23 * value for the row that the MergeCursor is currently pointing at. 24 */ 25 @android.ravenwood.annotation.RavenwoodKeepWholeClass 26 public class MergeCursor extends AbstractCursor 27 { 28 private DataSetObserver mObserver = new DataSetObserver() { 29 30 @Override 31 public void onChanged() { 32 // Reset our position so the optimizations in move-related code 33 // don't screw us over 34 mPos = -1; 35 } 36 37 @Override 38 public void onInvalidated() { 39 mPos = -1; 40 } 41 }; 42 MergeCursor(Cursor[] cursors)43 public MergeCursor(Cursor[] cursors) 44 { 45 mCursors = cursors; 46 mCursor = cursors[0]; 47 48 for (int i = 0; i < mCursors.length; i++) { 49 if (mCursors[i] == null) continue; 50 51 mCursors[i].registerDataSetObserver(mObserver); 52 } 53 } 54 55 @Override getCount()56 public int getCount() 57 { 58 int count = 0; 59 int length = mCursors.length; 60 for (int i = 0 ; i < length ; i++) { 61 if (mCursors[i] != null) { 62 count += mCursors[i].getCount(); 63 } 64 } 65 return count; 66 } 67 68 @Override onMove(int oldPosition, int newPosition)69 public boolean onMove(int oldPosition, int newPosition) 70 { 71 /* Find the right cursor */ 72 mCursor = null; 73 int cursorStartPos = 0; 74 int length = mCursors.length; 75 for (int i = 0 ; i < length; i++) { 76 if (mCursors[i] == null) { 77 continue; 78 } 79 80 if (newPosition < (cursorStartPos + mCursors[i].getCount())) { 81 mCursor = mCursors[i]; 82 break; 83 } 84 85 cursorStartPos += mCursors[i].getCount(); 86 } 87 88 /* Move it to the right position */ 89 if (mCursor != null) { 90 boolean ret = mCursor.moveToPosition(newPosition - cursorStartPos); 91 return ret; 92 } 93 return false; 94 } 95 96 @Override getString(int column)97 public String getString(int column) 98 { 99 return mCursor.getString(column); 100 } 101 102 @Override getShort(int column)103 public short getShort(int column) 104 { 105 return mCursor.getShort(column); 106 } 107 108 @Override getInt(int column)109 public int getInt(int column) 110 { 111 return mCursor.getInt(column); 112 } 113 114 @Override getLong(int column)115 public long getLong(int column) 116 { 117 return mCursor.getLong(column); 118 } 119 120 @Override getFloat(int column)121 public float getFloat(int column) 122 { 123 return mCursor.getFloat(column); 124 } 125 126 @Override getDouble(int column)127 public double getDouble(int column) 128 { 129 return mCursor.getDouble(column); 130 } 131 132 @Override getType(int column)133 public int getType(int column) { 134 return mCursor.getType(column); 135 } 136 137 @Override isNull(int column)138 public boolean isNull(int column) 139 { 140 return mCursor.isNull(column); 141 } 142 143 @Override getBlob(int column)144 public byte[] getBlob(int column) 145 { 146 return mCursor.getBlob(column); 147 } 148 149 @Override getColumnNames()150 public String[] getColumnNames() 151 { 152 if (mCursor != null) { 153 return mCursor.getColumnNames(); 154 } else { 155 return new String[0]; 156 } 157 } 158 159 @Override deactivate()160 public void deactivate() 161 { 162 int length = mCursors.length; 163 for (int i = 0 ; i < length ; i++) { 164 if (mCursors[i] != null) { 165 mCursors[i].deactivate(); 166 } 167 } 168 super.deactivate(); 169 } 170 171 @Override close()172 public void close() { 173 int length = mCursors.length; 174 for (int i = 0 ; i < length ; i++) { 175 if (mCursors[i] == null) continue; 176 mCursors[i].close(); 177 } 178 super.close(); 179 } 180 181 @Override registerContentObserver(ContentObserver observer)182 public void registerContentObserver(ContentObserver observer) { 183 int length = mCursors.length; 184 for (int i = 0 ; i < length ; i++) { 185 if (mCursors[i] != null) { 186 mCursors[i].registerContentObserver(observer); 187 } 188 } 189 } 190 @Override unregisterContentObserver(ContentObserver observer)191 public void unregisterContentObserver(ContentObserver observer) { 192 int length = mCursors.length; 193 for (int i = 0 ; i < length ; i++) { 194 if (mCursors[i] != null) { 195 mCursors[i].unregisterContentObserver(observer); 196 } 197 } 198 } 199 200 @Override registerDataSetObserver(DataSetObserver observer)201 public void registerDataSetObserver(DataSetObserver observer) { 202 int length = mCursors.length; 203 for (int i = 0 ; i < length ; i++) { 204 if (mCursors[i] != null) { 205 mCursors[i].registerDataSetObserver(observer); 206 } 207 } 208 } 209 210 @Override unregisterDataSetObserver(DataSetObserver observer)211 public void unregisterDataSetObserver(DataSetObserver observer) { 212 int length = mCursors.length; 213 for (int i = 0 ; i < length ; i++) { 214 if (mCursors[i] != null) { 215 mCursors[i].unregisterDataSetObserver(observer); 216 } 217 } 218 } 219 220 @Override requery()221 public boolean requery() 222 { 223 int length = mCursors.length; 224 for (int i = 0 ; i < length ; i++) { 225 if (mCursors[i] == null) { 226 continue; 227 } 228 229 if (mCursors[i].requery() == false) { 230 return false; 231 } 232 } 233 234 return true; 235 } 236 237 private Cursor mCursor; // updated in onMove 238 private Cursor[] mCursors; 239 } 240