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 public 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 
MergeCursor(Cursor[] cursors)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
getCount()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
onMove(int oldPosition, int newPosition)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     @Override
getString(int column)96     public String getString(int column)
97     {
98         return mCursor.getString(column);
99     }
100 
101     @Override
getShort(int column)102     public short getShort(int column)
103     {
104         return mCursor.getShort(column);
105     }
106 
107     @Override
getInt(int column)108     public int getInt(int column)
109     {
110         return mCursor.getInt(column);
111     }
112 
113     @Override
getLong(int column)114     public long getLong(int column)
115     {
116         return mCursor.getLong(column);
117     }
118 
119     @Override
getFloat(int column)120     public float getFloat(int column)
121     {
122         return mCursor.getFloat(column);
123     }
124 
125     @Override
getDouble(int column)126     public double getDouble(int column)
127     {
128         return mCursor.getDouble(column);
129     }
130 
131     @Override
getType(int column)132     public int getType(int column) {
133         return mCursor.getType(column);
134     }
135 
136     @Override
isNull(int column)137     public boolean isNull(int column)
138     {
139         return mCursor.isNull(column);
140     }
141 
142     @Override
getBlob(int column)143     public byte[] getBlob(int column)
144     {
145         return mCursor.getBlob(column);
146     }
147 
148     @Override
getColumnNames()149     public String[] getColumnNames()
150     {
151         if (mCursor != null) {
152             return mCursor.getColumnNames();
153         } else {
154             return new String[0];
155         }
156     }
157 
158     @Override
deactivate()159     public void deactivate()
160     {
161         int length = mCursors.length;
162         for (int i = 0 ; i < length ; i++) {
163             if (mCursors[i] != null) {
164                 mCursors[i].deactivate();
165             }
166         }
167         super.deactivate();
168     }
169 
170     @Override
close()171     public void close() {
172         int length = mCursors.length;
173         for (int i = 0 ; i < length ; i++) {
174             if (mCursors[i] == null) continue;
175             mCursors[i].close();
176         }
177         super.close();
178     }
179 
180     @Override
registerContentObserver(ContentObserver observer)181     public void registerContentObserver(ContentObserver observer) {
182         int length = mCursors.length;
183         for (int i = 0 ; i < length ; i++) {
184             if (mCursors[i] != null) {
185                 mCursors[i].registerContentObserver(observer);
186             }
187         }
188     }
189     @Override
unregisterContentObserver(ContentObserver observer)190     public void unregisterContentObserver(ContentObserver observer) {
191         int length = mCursors.length;
192         for (int i = 0 ; i < length ; i++) {
193             if (mCursors[i] != null) {
194                 mCursors[i].unregisterContentObserver(observer);
195             }
196         }
197     }
198 
199     @Override
registerDataSetObserver(DataSetObserver observer)200     public void registerDataSetObserver(DataSetObserver observer) {
201         int length = mCursors.length;
202         for (int i = 0 ; i < length ; i++) {
203             if (mCursors[i] != null) {
204                 mCursors[i].registerDataSetObserver(observer);
205             }
206         }
207     }
208 
209     @Override
unregisterDataSetObserver(DataSetObserver observer)210     public void unregisterDataSetObserver(DataSetObserver observer) {
211         int length = mCursors.length;
212         for (int i = 0 ; i < length ; i++) {
213             if (mCursors[i] != null) {
214                 mCursors[i].unregisterDataSetObserver(observer);
215             }
216         }
217     }
218 
219     @Override
requery()220     public boolean requery()
221     {
222         int length = mCursors.length;
223         for (int i = 0 ; i < length ; i++) {
224             if (mCursors[i] == null) {
225                 continue;
226             }
227 
228             if (mCursors[i].requery() == false) {
229                 return false;
230             }
231         }
232 
233         return true;
234     }
235 
236     private Cursor mCursor; // updated in onMove
237     private Cursor[] mCursors;
238 }
239