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 import android.compat.annotation.UnsupportedAppUsage;
20 import android.os.Build;
21 
22 /**
23  * A base class for Cursors that store their data in {@link CursorWindow}s.
24  * <p>
25  * The cursor owns the cursor window it uses.  When the cursor is closed,
26  * its window is also closed.  Likewise, when the window used by the cursor is
27  * changed, its old window is closed.  This policy of strict ownership ensures
28  * that cursor windows are not leaked.
29  * </p><p>
30  * Subclasses are responsible for filling the cursor window with data during
31  * {@link #onMove(int, int)}, allocating a new cursor window if necessary.
32  * During {@link #requery()}, the existing cursor window should be cleared and
33  * filled with new data.
34  * </p><p>
35  * If the contents of the cursor change or become invalid, the old window must be closed
36  * (because it is owned by the cursor) and set to null.
37  * </p>
38  */
39 public abstract class AbstractWindowedCursor extends AbstractCursor {
40     /**
41      * The cursor window owned by this cursor.
42      */
43     protected CursorWindow mWindow;
44 
45     @Override
getBlob(int columnIndex)46     public byte[] getBlob(int columnIndex) {
47         checkPosition();
48         return mWindow.getBlob(mPos, columnIndex);
49     }
50 
51     @Override
getString(int columnIndex)52     public String getString(int columnIndex) {
53         checkPosition();
54         return mWindow.getString(mPos, columnIndex);
55     }
56 
57     @Override
copyStringToBuffer(int columnIndex, CharArrayBuffer buffer)58     public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
59         checkPosition();
60         mWindow.copyStringToBuffer(mPos, columnIndex, buffer);
61     }
62 
63     @Override
getShort(int columnIndex)64     public short getShort(int columnIndex) {
65         checkPosition();
66         return mWindow.getShort(mPos, columnIndex);
67     }
68 
69     @Override
getInt(int columnIndex)70     public int getInt(int columnIndex) {
71         checkPosition();
72         return mWindow.getInt(mPos, columnIndex);
73     }
74 
75     @Override
getLong(int columnIndex)76     public long getLong(int columnIndex) {
77         checkPosition();
78         return mWindow.getLong(mPos, columnIndex);
79     }
80 
81     @Override
getFloat(int columnIndex)82     public float getFloat(int columnIndex) {
83         checkPosition();
84         return mWindow.getFloat(mPos, columnIndex);
85     }
86 
87     @Override
getDouble(int columnIndex)88     public double getDouble(int columnIndex) {
89         checkPosition();
90         return mWindow.getDouble(mPos, columnIndex);
91     }
92 
93     @Override
isNull(int columnIndex)94     public boolean isNull(int columnIndex) {
95         checkPosition();
96         return mWindow.getType(mPos, columnIndex) == Cursor.FIELD_TYPE_NULL;
97     }
98 
99     /**
100      * @deprecated Use {@link #getType}
101      */
102     @Deprecated
isBlob(int columnIndex)103     public boolean isBlob(int columnIndex) {
104         return getType(columnIndex) == Cursor.FIELD_TYPE_BLOB;
105     }
106 
107     /**
108      * @deprecated Use {@link #getType}
109      */
110     @Deprecated
isString(int columnIndex)111     public boolean isString(int columnIndex) {
112         return getType(columnIndex) == Cursor.FIELD_TYPE_STRING;
113     }
114 
115     /**
116      * @deprecated Use {@link #getType}
117      */
118     @Deprecated
isLong(int columnIndex)119     public boolean isLong(int columnIndex) {
120         return getType(columnIndex) == Cursor.FIELD_TYPE_INTEGER;
121     }
122 
123     /**
124      * @deprecated Use {@link #getType}
125      */
126     @Deprecated
isFloat(int columnIndex)127     public boolean isFloat(int columnIndex) {
128         return getType(columnIndex) == Cursor.FIELD_TYPE_FLOAT;
129     }
130 
131     @Override
getType(int columnIndex)132     public int getType(int columnIndex) {
133         checkPosition();
134         return mWindow.getType(mPos, columnIndex);
135     }
136 
137     @Override
checkPosition()138     protected void checkPosition() {
139         super.checkPosition();
140 
141         if (mWindow == null) {
142             throw new StaleDataException("Attempting to access a closed CursorWindow." +
143                     "Most probable cause: cursor is deactivated prior to calling this method.");
144         }
145     }
146 
147     @Override
getWindow()148     public CursorWindow getWindow() {
149         return mWindow;
150     }
151 
152     /**
153      * Sets a new cursor window for the cursor to use.
154      * <p>
155      * The cursor takes ownership of the provided cursor window; the cursor window
156      * will be closed when the cursor is closed or when the cursor adopts a new
157      * cursor window.
158      * </p><p>
159      * If the cursor previously had a cursor window, then it is closed when the
160      * new cursor window is assigned.
161      * </p>
162      *
163      * @param window The new cursor window, typically a remote cursor window.
164      */
setWindow(CursorWindow window)165     public void setWindow(CursorWindow window) {
166         if (window != mWindow) {
167             closeWindow();
168             mWindow = window;
169         }
170     }
171 
172     /**
173      * Returns true if the cursor has an associated cursor window.
174      *
175      * @return True if the cursor has an associated cursor window.
176      */
hasWindow()177     public boolean hasWindow() {
178         return mWindow != null;
179     }
180 
181     /**
182      * Closes the cursor window and sets {@link #mWindow} to null.
183      * @hide
184      */
185     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
closeWindow()186     protected void closeWindow() {
187         if (mWindow != null) {
188             mWindow.close();
189             mWindow = null;
190         }
191     }
192 
193     /**
194      * If there is a window, clear it.
195      * Otherwise, creates a new window.
196      *
197      * @param name The window name.
198      * @hide
199      */
200     @UnsupportedAppUsage
clearOrCreateWindow(String name)201     protected void clearOrCreateWindow(String name) {
202         if (mWindow == null) {
203             mWindow = new CursorWindow(name);
204         } else {
205             mWindow.clear();
206         }
207     }
208 
209     /** @hide */
210     @Override
211     @UnsupportedAppUsage
onDeactivateOrClose()212     protected void onDeactivateOrClose() {
213         super.onDeactivateOrClose();
214         closeWindow();
215     }
216 }
217