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 17package android.database; 18 19/** 20 * A convience 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 */ 25public class MergeCursor extends AbstractCursor 26{ 27 private DataSetObserver mObserver = new DataSetObserver() { 28 29 @Override 30 public void onChanged() { 31 // Reset our position so the optimizations in move-related code 32 // don't screw us over 33 mPos = -1; 34 } 35 36 @Override 37 public void onInvalidated() { 38 mPos = -1; 39 } 40 }; 41 42 public MergeCursor(Cursor[] cursors) 43 { 44 mCursors = cursors; 45 mCursor = cursors[0]; 46 47 for (int i = 0; i < mCursors.length; i++) { 48 if (mCursors[i] == null) continue; 49 50 mCursors[i].registerDataSetObserver(mObserver); 51 } 52 } 53 54 @Override 55 public int getCount() 56 { 57 int count = 0; 58 int length = mCursors.length; 59 for (int i = 0 ; i < length ; i++) { 60 if (mCursors[i] != null) { 61 count += mCursors[i].getCount(); 62 } 63 } 64 return count; 65 } 66 67 @Override 68 public boolean onMove(int oldPosition, int newPosition) 69 { 70 /* Find the right cursor */ 71 mCursor = null; 72 int cursorStartPos = 0; 73 int length = mCursors.length; 74 for (int i = 0 ; i < length; i++) { 75 if (mCursors[i] == null) { 76 continue; 77 } 78 79 if (newPosition < (cursorStartPos + mCursors[i].getCount())) { 80 mCursor = mCursors[i]; 81 break; 82 } 83 84 cursorStartPos += mCursors[i].getCount(); 85 } 86 87 /* Move it to the right position */ 88 if (mCursor != null) { 89 boolean ret = mCursor.moveToPosition(newPosition - cursorStartPos); 90 return ret; 91 } 92 return false; 93 } 94 95 /** 96 * @hide 97 * @deprecated 98 */ 99 @Override 100 public boolean deleteRow() 101 { 102 return mCursor.deleteRow(); 103 } 104 105 /** 106 * @hide 107 * @deprecated 108 */ 109 @Override 110 public boolean commitUpdates() { 111 int length = mCursors.length; 112 for (int i = 0 ; i < length ; i++) { 113 if (mCursors[i] != null) { 114 mCursors[i].commitUpdates(); 115 } 116 } 117 onChange(true); 118 return true; 119 } 120 121 @Override 122 public String getString(int column) 123 { 124 return mCursor.getString(column); 125 } 126 127 @Override 128 public short getShort(int column) 129 { 130 return mCursor.getShort(column); 131 } 132 133 @Override 134 public int getInt(int column) 135 { 136 return mCursor.getInt(column); 137 } 138 139 @Override 140 public long getLong(int column) 141 { 142 return mCursor.getLong(column); 143 } 144 145 @Override 146 public float getFloat(int column) 147 { 148 return mCursor.getFloat(column); 149 } 150 151 @Override 152 public double getDouble(int column) 153 { 154 return mCursor.getDouble(column); 155 } 156 157 @Override 158 public boolean isNull(int column) 159 { 160 return mCursor.isNull(column); 161 } 162 163 @Override 164 public byte[] getBlob(int column) 165 { 166 return mCursor.getBlob(column); 167 } 168 169 @Override 170 public String[] getColumnNames() 171 { 172 if (mCursor != null) { 173 return mCursor.getColumnNames(); 174 } else { 175 return new String[0]; 176 } 177 } 178 179 @Override 180 public void deactivate() 181 { 182 int length = mCursors.length; 183 for (int i = 0 ; i < length ; i++) { 184 if (mCursors[i] != null) { 185 mCursors[i].deactivate(); 186 } 187 } 188 super.deactivate(); 189 } 190 191 @Override 192 public void close() { 193 int length = mCursors.length; 194 for (int i = 0 ; i < length ; i++) { 195 if (mCursors[i] == null) continue; 196 mCursors[i].close(); 197 } 198 super.close(); 199 } 200 201 @Override 202 public void registerContentObserver(ContentObserver observer) { 203 int length = mCursors.length; 204 for (int i = 0 ; i < length ; i++) { 205 if (mCursors[i] != null) { 206 mCursors[i].registerContentObserver(observer); 207 } 208 } 209 } 210 @Override 211 public void unregisterContentObserver(ContentObserver observer) { 212 int length = mCursors.length; 213 for (int i = 0 ; i < length ; i++) { 214 if (mCursors[i] != null) { 215 mCursors[i].unregisterContentObserver(observer); 216 } 217 } 218 } 219 220 @Override 221 public void registerDataSetObserver(DataSetObserver observer) { 222 int length = mCursors.length; 223 for (int i = 0 ; i < length ; i++) { 224 if (mCursors[i] != null) { 225 mCursors[i].registerDataSetObserver(observer); 226 } 227 } 228 } 229 230 @Override 231 public void unregisterDataSetObserver(DataSetObserver observer) { 232 int length = mCursors.length; 233 for (int i = 0 ; i < length ; i++) { 234 if (mCursors[i] != null) { 235 mCursors[i].unregisterDataSetObserver(observer); 236 } 237 } 238 } 239 240 @Override 241 public boolean requery() 242 { 243 int length = mCursors.length; 244 for (int i = 0 ; i < length ; i++) { 245 if (mCursors[i] == null) { 246 continue; 247 } 248 249 if (mCursors[i].requery() == false) { 250 return false; 251 } 252 } 253 254 return true; 255 } 256 257 private Cursor mCursor; // updated in onMove 258 private Cursor[] mCursors; 259} 260