SyncedFolderProvider.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /**
  2. * Nextcloud Android client application
  3. *
  4. * Copyright (C) 2016 Andy Scherzinger
  5. * Copyright (C) 2016 Nextcloud.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  9. * License as published by the Free Software Foundation; either
  10. * version 3 of the License, or any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public
  18. * License along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. package com.owncloud.android.datamodel;
  21. import android.content.ContentResolver;
  22. import android.content.ContentValues;
  23. import android.database.Cursor;
  24. import android.net.Uri;
  25. import android.support.annotation.NonNull;
  26. import com.owncloud.android.db.ProviderMeta;
  27. import com.owncloud.android.lib.common.utils.Log_OC;
  28. import java.util.Observable;
  29. /**
  30. * Database provider for handling the persistence aspects of synced folders.
  31. */
  32. public class SyncedFolderProvider extends Observable {
  33. static private final String TAG = SyncedFolderProvider.class.getSimpleName();
  34. private ContentResolver mContentResolver;
  35. /**
  36. * constructor.
  37. *
  38. * @param contentResolver the ContentResolver to work with.
  39. */
  40. public SyncedFolderProvider(ContentResolver contentResolver) {
  41. if (contentResolver == null) {
  42. throw new IllegalArgumentException("Cannot create an instance with a NULL contentResolver");
  43. }
  44. mContentResolver = contentResolver;
  45. }
  46. /**
  47. * Stores an media folder sync object in database.
  48. *
  49. * @param syncedFolder synced folder to store
  50. * @return upload id, -1 if the insert process fails.
  51. */
  52. public long storeFolderSync(SyncedFolder syncedFolder) {
  53. Log_OC.v(TAG, "Inserting " + syncedFolder.getLocalPath() + " with enabled=" + syncedFolder.isEnabled());
  54. ContentValues cv = createContentValuesFromSyncedFolder(syncedFolder);
  55. Uri result = mContentResolver.insert(ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS, cv);
  56. if (result != null) {
  57. notifyFolderSyncObservers();
  58. return Long.parseLong(result.getPathSegments().get(1));
  59. } else {
  60. Log_OC.e(TAG, "Failed to insert item " + syncedFolder.getLocalPath() + " into folder sync db.");
  61. return -1;
  62. }
  63. }
  64. /**
  65. * get all synced folder entries.
  66. *
  67. * @return all synced folder entries, empty if none have been found
  68. */
  69. public SyncedFolder[] getSyncedFolders() {
  70. Cursor cursor = mContentResolver.query(
  71. ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
  72. null,
  73. "1=1",
  74. null,
  75. null
  76. );
  77. if (cursor != null) {
  78. SyncedFolder[] list = new SyncedFolder[cursor.getCount()];
  79. if (cursor.moveToFirst()) {
  80. do {
  81. SyncedFolder syncedFolder = createSyncedFolderFromCursor(cursor);
  82. if (syncedFolder == null) {
  83. Log_OC.e(TAG, "SyncedFolder could not be created from cursor");
  84. } else {
  85. list[cursor.getPosition()] = syncedFolder;
  86. }
  87. } while (cursor.moveToNext());
  88. }
  89. cursor.close();
  90. return list;
  91. } else {
  92. Log_OC.e(TAG, "DB error creating read all cursor for synced folders.");
  93. }
  94. return new SyncedFolder[0];
  95. }
  96. /**
  97. * Update upload status of file uniquely referenced by id.
  98. *
  99. * @param id folder sync id.
  100. * @param enabled new status.
  101. * @return the number of rows updated.
  102. */
  103. public int updateFolderSyncEnabled(long id, Boolean enabled) {
  104. Log_OC.v(TAG, "Storing sync folder id" + id + " with enabled=" + enabled);
  105. int result = 0;
  106. Cursor cursor = mContentResolver.query(
  107. ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
  108. null,
  109. ProviderMeta.ProviderTableMeta._ID + "=?",
  110. new String[]{String.valueOf(id)},
  111. null
  112. );
  113. if (cursor != null && cursor.getCount() == 1) {
  114. while (cursor.moveToNext()) {
  115. // read sync folder object and update
  116. SyncedFolder syncedFolder = createSyncedFolderFromCursor(cursor);
  117. syncedFolder.setEnabled(enabled);
  118. // update sync folder object in db
  119. result = updateSyncFolder(syncedFolder);
  120. cursor.close();
  121. }
  122. } else {
  123. if (cursor == null) {
  124. Log_OC.e(TAG, "Sync folder db cursor for ID=" + id + " in NULL.");
  125. } else {
  126. Log_OC.e(TAG, cursor.getCount() + " items for id=" + id + " available in sync folder database. " +
  127. "Expected 1. Failed to update sync folder db.");
  128. }
  129. }
  130. return result;
  131. }
  132. /**
  133. * find a synced folder by local path.
  134. *
  135. * @param localPath the local path of the local folder
  136. * @return the synced folder if found, else null
  137. */
  138. public SyncedFolder findByLocalPath(String localPath) {
  139. SyncedFolder result = null;
  140. Cursor cursor = mContentResolver.query(
  141. ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
  142. null,
  143. ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH + "==" + localPath,
  144. null,
  145. null
  146. );
  147. if (cursor != null && cursor.getCount() == 1) {
  148. result = createSyncedFolderFromCursor(cursor);
  149. cursor.close();
  150. } else {
  151. if (cursor == null) {
  152. Log_OC.e(TAG, "Sync folder db cursor for local path=" + localPath + " in NULL.");
  153. } else {
  154. Log_OC.e(TAG, cursor.getCount() + " items for local path=" + localPath
  155. + " available in sync folder db. Expected 1. Failed to update sync folder db.");
  156. }
  157. }
  158. return result;
  159. }
  160. /**
  161. * update given synced folder.
  162. *
  163. * @param syncedFolder the synced folder to be updated.
  164. * @return the number of rows updated.
  165. */
  166. private int updateSyncFolder(SyncedFolder syncedFolder) {
  167. Log_OC.v(TAG, "Updating " + syncedFolder.getLocalPath() + " with enabled=" + syncedFolder.isEnabled());
  168. ContentValues cv = createContentValuesFromSyncedFolder(syncedFolder);
  169. int result = mContentResolver.update(
  170. ProviderMeta.ProviderTableMeta.CONTENT_URI_UPLOADS,
  171. cv,
  172. ProviderMeta.ProviderTableMeta._ID + "=?",
  173. new String[]{String.valueOf(syncedFolder.getId())}
  174. );
  175. if (result > 0) {
  176. notifyFolderSyncObservers();
  177. }
  178. return result;
  179. }
  180. /**
  181. * maps a cursor into a SyncedFolder object.
  182. *
  183. * @param cursor the cursor
  184. * @return the mapped SyncedFolder, null if cursor is null
  185. */
  186. private SyncedFolder createSyncedFolderFromCursor(Cursor cursor) {
  187. SyncedFolder syncedFolder = null;
  188. if (cursor != null) {
  189. long id = cursor.getLong(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta._ID));
  190. String localPath = cursor.getString(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH));
  191. String remotePath = cursor.getString(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_REMOTE_PATH));
  192. Boolean wifiOnly = cursor.getInt(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_WIFI_ONLY)) == 1;
  193. Boolean chargingOnly = cursor.getInt(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY)) == 1;
  194. Boolean subfolderByDate = cursor.getInt(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE)) == 1;
  195. String accountName = cursor.getString(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT));
  196. Integer uploadAction = cursor.getInt(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION));
  197. Boolean enabled = cursor.getInt(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED)) == 1;
  198. syncedFolder = new SyncedFolder(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate,
  199. accountName, uploadAction, enabled);
  200. }
  201. return syncedFolder;
  202. }
  203. /**
  204. * create ContentValues object based on given SyncedFolder.
  205. *
  206. * @param syncedFolder the synced folder
  207. * @return the corresponding ContentValues object
  208. */
  209. @NonNull
  210. private ContentValues createContentValuesFromSyncedFolder(SyncedFolder syncedFolder) {
  211. ContentValues cv = new ContentValues();
  212. cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH, syncedFolder.getLocalPath());
  213. cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_REMOTE_PATH, syncedFolder.getRemotePath());
  214. cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_WIFI_ONLY, syncedFolder.getWifiOnly());
  215. cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY, syncedFolder.getChargingOnly());
  216. cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED, syncedFolder.isEnabled());
  217. cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE, syncedFolder.getSubfolderByDate());
  218. cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT, syncedFolder.getAccount());
  219. cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION, syncedFolder.getUploadAction());
  220. return cv;
  221. }
  222. /**
  223. * Inform all observers about data change.
  224. */
  225. private void notifyFolderSyncObservers() {
  226. Log_OC.d(TAG, "notifying folder sync data observers");
  227. setChanged();
  228. notifyObservers();
  229. }
  230. }