1 /*
2  * Copyright (C) 2013 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 com.android.documentsui.roots;
18 
19 import android.database.AbstractCursor;
20 import android.database.ContentObserver;
21 import android.database.Cursor;
22 import android.os.Bundle;
23 import android.util.Log;
24 
25 import static com.android.documentsui.base.SharedMinimal.VERBOSE;
26 
27 import com.android.documentsui.base.UserId;
28 
29 /**
30  * Cursor wrapper that adds columns to identify which root a document came from.
31  */
32 public class RootCursorWrapper extends AbstractCursor {
33     private final UserId mUserId;
34     private final String mAuthority;
35     private final String mRootId;
36 
37     private final Cursor mCursor;
38     private final int mCount;
39 
40     private final String[] mColumnNames;
41 
42     private final int mAuthorityIndex;
43     private final int mRootIdIndex;
44     private final int mUserIdIndex;
45 
46     public static final String COLUMN_USER_ID = "android:userId";
47     public static final String COLUMN_AUTHORITY = "android:authority";
48     public static final String COLUMN_ROOT_ID = "android:rootId";
49     private static final String TAG = "RootCursorWrapper";
50 
RootCursorWrapper(UserId userId, String authority, String rootId, Cursor cursor, int maxCount)51     public RootCursorWrapper(UserId userId, String authority, String rootId, Cursor cursor,
52             int maxCount) {
53         mUserId = userId;
54         mAuthority = authority;
55         mRootId = rootId;
56         mCursor = cursor;
57 
58         final int count = cursor.getCount();
59         if (maxCount > 0 && count > maxCount) {
60             mCount = maxCount;
61         } else {
62             mCount = count;
63         }
64 
65         if (cursor.getColumnIndex(COLUMN_USER_ID) != -1
66                 || cursor.getColumnIndex(COLUMN_AUTHORITY) != -1
67                 || cursor.getColumnIndex(COLUMN_ROOT_ID) != -1) {
68             throw new IllegalArgumentException("Cursor contains internal columns!");
69         }
70         final String[] before = cursor.getColumnNames();
71         // Create a new columnNames and copy the existing one to it.
72         // Add the internal column names to the end of the array.
73         mColumnNames = new String[before.length + 3];
74         System.arraycopy(before, 0, mColumnNames, 0, before.length);
75         mAuthorityIndex = before.length;
76         mRootIdIndex = before.length + 1;
77         mUserIdIndex = before.length + 2;
78         mColumnNames[mAuthorityIndex] = COLUMN_AUTHORITY;
79         mColumnNames[mRootIdIndex] = COLUMN_ROOT_ID;
80         mColumnNames[mUserIdIndex] = COLUMN_USER_ID;
81     }
82 
83     @Override
getExtras()84     public Bundle getExtras() {
85         Bundle extras = mCursor.getExtras();
86 
87         if (extras == null) {
88             if (VERBOSE) Log.v(TAG, "Cursor for root " + mRootId + " does not have any extras.");
89             return Bundle.EMPTY;
90         }
91 
92         return extras;
93     }
94 
95     @Override
close()96     public void close() {
97         super.close();
98         mCursor.close();
99     }
100 
101     @Override
onMove(int oldPosition, int newPosition)102     public boolean onMove(int oldPosition, int newPosition) {
103         return mCursor.moveToPosition(newPosition);
104     }
105 
106     @Override
getColumnNames()107     public String[] getColumnNames() {
108         return mColumnNames;
109     }
110 
111     @Override
getCount()112     public int getCount() {
113         return mCount;
114     }
115 
116     @Override
getDouble(int column)117     public double getDouble(int column) {
118         return mCursor.getDouble(column);
119     }
120 
121     @Override
getFloat(int column)122     public float getFloat(int column) {
123         return mCursor.getFloat(column);
124     }
125 
126     @Override
getInt(int column)127     public int getInt(int column) {
128         if (column == mUserIdIndex) {
129             return mUserId.getIdentifier();
130         } else {
131             return mCursor.getInt(column);
132         }
133     }
134 
135     @Override
getLong(int column)136     public long getLong(int column) {
137         return mCursor.getLong(column);
138     }
139 
140     @Override
getShort(int column)141     public short getShort(int column) {
142         return mCursor.getShort(column);
143     }
144 
145     @Override
getString(int column)146     public String getString(int column) {
147         if (column == mAuthorityIndex) {
148             return mAuthority;
149         } else if (column == mRootIdIndex) {
150             return mRootId;
151         } else {
152             return mCursor.getString(column);
153         }
154     }
155 
156     @Override
getType(int column)157     public int getType(int column) {
158         return mCursor.getType(column);
159     }
160 
161     @Override
isNull(int column)162     public boolean isNull(int column) {
163         return mCursor.isNull(column);
164     }
165 
166     @Override
registerContentObserver(ContentObserver observer)167     public void registerContentObserver(ContentObserver observer) {
168         mCursor.registerContentObserver(observer);
169     }
170 
171     @Override
unregisterContentObserver(ContentObserver observer)172     public void unregisterContentObserver(ContentObserver observer) {
173         mCursor.unregisterContentObserver(observer);
174     }
175 }
176