1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 package org.mozilla.gecko.sync.repositories.android;
6 
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.List;
12 import java.util.Map;
13 
14 import org.json.simple.JSONArray;
15 
16 import org.mozilla.gecko.sync.CommandProcessor.Command;
17 import org.mozilla.gecko.sync.repositories.NullCursorException;
18 import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
19 import org.mozilla.gecko.sync.setup.Constants;
20 
21 import android.content.Context;
22 import android.database.Cursor;
23 
24 public class ClientsDatabaseAccessor {
25 
26   public static final String LOG_TAG = "ClientsDatabaseAccessor";
27 
28   private ClientsDatabase db;
29 
30   // Need this so we can properly stub out the class for testing.
ClientsDatabaseAccessor()31   public ClientsDatabaseAccessor() {}
32 
ClientsDatabaseAccessor(Context context)33   public ClientsDatabaseAccessor(Context context) {
34     db = new ClientsDatabase(context);
35   }
36 
store(ClientRecord record)37   public void store(ClientRecord record) {
38     db.store(getProfileId(), record);
39   }
40 
store(Collection<ClientRecord> records)41   public void store(Collection<ClientRecord> records) {
42     for (ClientRecord record : records) {
43       this.store(record);
44     }
45   }
46 
store(String accountGUID, Command command)47   public void store(String accountGUID, Command command) throws NullCursorException {
48     db.store(accountGUID, command.commandType, command.args.toJSONString());
49   }
50 
fetchClient(String accountGUID)51   public ClientRecord fetchClient(String accountGUID) throws NullCursorException {
52     final Cursor cur = db.fetchClientsCursor(accountGUID, getProfileId());
53     try {
54       if (!cur.moveToFirst()) {
55         return null;
56       }
57       return recordFromCursor(cur);
58     } finally {
59       cur.close();
60     }
61   }
62 
fetchAllClients()63   public Map<String, ClientRecord> fetchAllClients() throws NullCursorException {
64     final HashMap<String, ClientRecord> map = new HashMap<String, ClientRecord>();
65     final Cursor cur = db.fetchAllClients();
66     try {
67       if (!cur.moveToFirst()) {
68         return Collections.unmodifiableMap(map);
69       }
70 
71       while (!cur.isAfterLast()) {
72         ClientRecord clientRecord = recordFromCursor(cur);
73         map.put(clientRecord.guid, clientRecord);
74         cur.moveToNext();
75       }
76       return Collections.unmodifiableMap(map);
77     } finally {
78       cur.close();
79     }
80   }
81 
fetchAllCommands()82   public List<Command> fetchAllCommands() throws NullCursorException {
83     final List<Command> commands = new ArrayList<Command>();
84     final Cursor cur = db.fetchAllCommands();
85     try {
86       if (!cur.moveToFirst()) {
87         return Collections.unmodifiableList(commands);
88       }
89 
90       while (!cur.isAfterLast()) {
91         Command command = commandFromCursor(cur);
92         commands.add(command);
93         cur.moveToNext();
94       }
95       return Collections.unmodifiableList(commands);
96     } finally {
97       cur.close();
98     }
99   }
100 
fetchCommandsForClient(String accountGUID)101   public List<Command> fetchCommandsForClient(String accountGUID) throws NullCursorException {
102     final List<Command> commands = new ArrayList<Command>();
103     final Cursor cur = db.fetchCommandsForClient(accountGUID);
104     try {
105       if (!cur.moveToFirst()) {
106         return Collections.unmodifiableList(commands);
107       }
108 
109       while(!cur.isAfterLast()) {
110         Command command = commandFromCursor(cur);
111         commands.add(command);
112         cur.moveToNext();
113       }
114       return Collections.unmodifiableList(commands);
115     } finally {
116       cur.close();
117     }
118   }
119 
recordFromCursor(Cursor cur)120   protected static ClientRecord recordFromCursor(Cursor cur) {
121     final String accountGUID = RepoUtils.getStringFromCursor(cur, ClientsDatabase.COL_ACCOUNT_GUID);
122     final String clientName = RepoUtils.getStringFromCursor(cur, ClientsDatabase.COL_NAME);
123     final String clientType = RepoUtils.getStringFromCursor(cur, ClientsDatabase.COL_TYPE);
124 
125     final ClientRecord record = new ClientRecord(accountGUID);
126     record.name = clientName;
127     record.type = clientType;
128 
129     // Optional fields. These will either be null or strings.
130     record.formfactor = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_FORMFACTOR);
131     record.os = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_OS);
132     record.device = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_DEVICE);
133     record.appPackage = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_APP_PACKAGE);
134     record.application = RepoUtils.optStringFromCursor(cur, ClientsDatabase.COL_APPLICATION);
135 
136     return record;
137   }
138 
commandFromCursor(Cursor cur)139   protected static Command commandFromCursor(Cursor cur) {
140     String commandType = RepoUtils.getStringFromCursor(cur, ClientsDatabase.COL_COMMAND);
141     JSONArray commandArgs = RepoUtils.getJSONArrayFromCursor(cur, ClientsDatabase.COL_ARGS);
142     return new Command(commandType, commandArgs);
143   }
144 
clientsCount()145   public int clientsCount() {
146     try {
147       final Cursor cur = db.fetchAllClients();
148       try {
149         return cur.getCount();
150       } finally {
151         cur.close();
152       }
153     } catch (NullCursorException e) {
154       return 0;
155     }
156 
157   }
158 
getProfileId()159   private String getProfileId() {
160     return Constants.DEFAULT_PROFILE;
161   }
162 
wipeDB()163   public void wipeDB() {
164     db.wipeDB();
165   }
166 
wipeClientsTable()167   public void wipeClientsTable() {
168     db.wipeClientsTable();
169   }
170 
wipeCommandsTable()171   public void wipeCommandsTable() {
172     db.wipeCommandsTable();
173   }
174 
close()175   public void close() {
176     db.close();
177   }
178 }
179