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 base class for Cursors that store their data in {@link CursorWindow}s.
21 */
22public abstract class AbstractWindowedCursor extends AbstractCursor
23{
24    @Override
25    public byte[] getBlob(int columnIndex)
26    {
27        checkPosition();
28
29        synchronized(mUpdatedRows) {
30            if (isFieldUpdated(columnIndex)) {
31                return (byte[])getUpdatedField(columnIndex);
32            }
33        }
34
35        return mWindow.getBlob(mPos, columnIndex);
36    }
37
38    @Override
39    public String getString(int columnIndex)
40    {
41        checkPosition();
42
43        synchronized(mUpdatedRows) {
44            if (isFieldUpdated(columnIndex)) {
45                return (String)getUpdatedField(columnIndex);
46            }
47        }
48
49        return mWindow.getString(mPos, columnIndex);
50    }
51
52    @Override
53    public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer)
54    {
55        checkPosition();
56
57        synchronized(mUpdatedRows) {
58            if (isFieldUpdated(columnIndex)) {
59                super.copyStringToBuffer(columnIndex, buffer);
60            }
61        }
62
63        mWindow.copyStringToBuffer(mPos, columnIndex, buffer);
64    }
65
66    @Override
67    public short getShort(int columnIndex)
68    {
69        checkPosition();
70
71        synchronized(mUpdatedRows) {
72            if (isFieldUpdated(columnIndex)) {
73                Number value = (Number)getUpdatedField(columnIndex);
74                return value.shortValue();
75            }
76        }
77
78        return mWindow.getShort(mPos, columnIndex);
79    }
80
81    @Override
82    public int getInt(int columnIndex)
83    {
84        checkPosition();
85
86        synchronized(mUpdatedRows) {
87            if (isFieldUpdated(columnIndex)) {
88                Number value = (Number)getUpdatedField(columnIndex);
89                return value.intValue();
90            }
91        }
92
93        return mWindow.getInt(mPos, columnIndex);
94    }
95
96    @Override
97    public long getLong(int columnIndex)
98    {
99        checkPosition();
100
101        synchronized(mUpdatedRows) {
102            if (isFieldUpdated(columnIndex)) {
103                Number value = (Number)getUpdatedField(columnIndex);
104                return value.longValue();
105            }
106        }
107
108        return mWindow.getLong(mPos, columnIndex);
109    }
110
111    @Override
112    public float getFloat(int columnIndex)
113    {
114        checkPosition();
115
116        synchronized(mUpdatedRows) {
117            if (isFieldUpdated(columnIndex)) {
118                Number value = (Number)getUpdatedField(columnIndex);
119                return value.floatValue();
120            }
121        }
122
123        return mWindow.getFloat(mPos, columnIndex);
124    }
125
126    @Override
127    public double getDouble(int columnIndex)
128    {
129        checkPosition();
130
131        synchronized(mUpdatedRows) {
132            if (isFieldUpdated(columnIndex)) {
133                Number value = (Number)getUpdatedField(columnIndex);
134                return value.doubleValue();
135            }
136        }
137
138        return mWindow.getDouble(mPos, columnIndex);
139    }
140
141    @Override
142    public boolean isNull(int columnIndex)
143    {
144        checkPosition();
145
146        synchronized(mUpdatedRows) {
147            if (isFieldUpdated(columnIndex)) {
148                return getUpdatedField(columnIndex) == null;
149            }
150        }
151
152        return mWindow.isNull(mPos, columnIndex);
153    }
154
155    public boolean isBlob(int columnIndex)
156    {
157        checkPosition();
158
159        synchronized(mUpdatedRows) {
160            if (isFieldUpdated(columnIndex)) {
161                Object object = getUpdatedField(columnIndex);
162                return object == null || object instanceof byte[];
163            }
164        }
165
166        return mWindow.isBlob(mPos, columnIndex);
167    }
168
169    public boolean isString(int columnIndex)
170    {
171        checkPosition();
172
173        synchronized(mUpdatedRows) {
174            if (isFieldUpdated(columnIndex)) {
175                Object object = getUpdatedField(columnIndex);
176                return object == null || object instanceof String;
177            }
178        }
179
180        return mWindow.isString(mPos, columnIndex);
181    }
182
183    public boolean isLong(int columnIndex)
184    {
185        checkPosition();
186
187        synchronized(mUpdatedRows) {
188            if (isFieldUpdated(columnIndex)) {
189                Object object = getUpdatedField(columnIndex);
190                return object != null && (object instanceof Integer || object instanceof Long);
191            }
192        }
193
194        return mWindow.isLong(mPos, columnIndex);
195    }
196
197    public boolean isFloat(int columnIndex)
198    {
199        checkPosition();
200
201        synchronized(mUpdatedRows) {
202            if (isFieldUpdated(columnIndex)) {
203                Object object = getUpdatedField(columnIndex);
204                return object != null && (object instanceof Float || object instanceof Double);
205            }
206        }
207
208        return mWindow.isFloat(mPos, columnIndex);
209    }
210
211    @Override
212    protected void checkPosition()
213    {
214        super.checkPosition();
215
216        if (mWindow == null) {
217            throw new StaleDataException("Access closed cursor");
218        }
219    }
220
221    @Override
222    public CursorWindow getWindow() {
223        return mWindow;
224    }
225
226    /**
227     * Set a new cursor window to cursor, usually set a remote cursor window
228     * @param window cursor window
229     */
230    public void setWindow(CursorWindow window) {
231        if (mWindow != null) {
232            mWindow.close();
233        }
234        mWindow = window;
235    }
236
237    public boolean hasWindow() {
238        return mWindow != null;
239    }
240
241    /**
242     * This needs be updated in {@link #onMove} by subclasses, and
243     * needs to be set to NULL when the contents of the cursor change.
244     */
245    protected CursorWindow mWindow;
246}
247