IOT-3143
[iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / db / MongoDB.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.accountserver.db;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.Set;
31
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34 import org.bson.Document;
35
36 import com.mongodb.MongoClient;
37 import com.mongodb.client.MongoCollection;
38 import com.mongodb.client.MongoCursor;
39 import com.mongodb.client.MongoDatabase;
40 import com.mongodb.client.model.IndexOptions;
41 import com.mongodb.client.result.DeleteResult;
42
43 /**
44  *
45  * This class provides a set of APIs to use MongoDB APIs.
46  *
47  */
48 public class MongoDB {
49     private final static Logger     Log             = LoggerFactory.getLogger(MongoDB.class);
50     private MongoClient             mongoClient     = null;
51     private MongoDatabase           db              = null;
52
53     /**
54      * API creating MongoClient and initializing MongoDatabase
55      *
56      * @param host
57      *            host of MongoDatabase
58      * @param dbname
59      *            database name to create MongoDatabase
60      * @throws Exception
61      */
62     public MongoDB(String host, String dbname) throws Exception {
63         mongoClient = new MongoClient(host);
64         db = mongoClient.getDatabase(dbname);
65     }
66
67     /**
68      * API for creating collection
69      *
70      * @param tableName
71      *            collection name
72      */
73     public void createTable(String tableName) {
74         if (!collectionExists(tableName))
75             db.createCollection(tableName);
76     }
77
78     private boolean collectionExists(String tableName ) {
79         return db.listCollectionNames().into(new ArrayList<>()).contains(tableName);
80     }
81
82     /**
83      * API for dropping collection
84      *
85      * @param tableName
86      *            collection name
87      */
88     public void dropTable(String tableName) {
89         if (collectionExists(tableName))
90             db.getCollection(tableName).drop();
91     }
92
93     /**
94      * API for creating index
95      *
96      * @param tableName
97      *            collection name
98      * @param keys
99      *            key fields of collection
100      */
101     public void createIndex(String tablename, ArrayList<String> keys) {
102
103         Document doc = new Document();
104
105         for (String key : keys) {
106
107             doc.append(key, 1);
108         }
109
110         IndexOptions options = new IndexOptions();
111         options.unique(true);
112
113         db.getCollection(tablename).createIndex(doc, options);
114     }
115
116     /**
117      * API for deleting collection
118      *
119      * @param tableName
120      *            collection name
121      */
122     public void deleteTable(String tableName) {
123
124         db.getCollection(tableName).drop();
125     }
126
127     /**
128      * API for getting database object
129      *
130      */
131     public MongoDatabase getMongoDatabase() {
132
133         return db;
134     }
135
136     /**
137      * API for inserting a record into DB table. the record will not be inserted
138      * if duplicated one.
139      * 
140      * @param tableName
141      *            table name to be inserted
142      * @param doc
143      *            document to be inserted
144      */
145     public Boolean insertRecord(String tableName, Document doc) {
146
147         if (tableName == null || doc == null)
148             return false;
149
150         MongoCollection<Document> collection = db.getCollection(tableName);
151
152         try {
153
154             if (collection.find(doc).first() == null) {
155
156                 collection.insertOne(doc);
157
158             } else {
159
160                 Log.warn("DB insert failed due to duplecated one.");
161                 return false;
162             }
163
164         } catch (Exception e) {
165
166             e.printStackTrace();
167             return false;
168         }
169
170         showRecord(tableName);
171
172         return true;
173     }
174
175     /**
176      * API for inserting a record into DB table. the record will be replaced if
177      * duplicated one.
178      * 
179      * @param tableName
180      *            table name to be inserted
181      * @param filter
182      *            document filter
183      * @param doc
184      *            document to be inserted
185      * @return returns true if the record is inserted and replaced successfully,
186      *         or returns false
187      */
188     public Boolean insertAndReplaceRecord(String tableName, Document filter,
189             Document doc) {
190
191         if (tableName == null || filter == null || doc == null)
192             return false;
193
194         MongoCollection<Document> collection = db.getCollection(tableName);
195
196         try {
197
198             if (collection.findOneAndReplace(filter, doc) == null) {
199
200                 collection.insertOne(doc);
201             }
202
203         } catch (Exception e) {
204
205             e.printStackTrace();
206             return false;
207         }
208
209         showRecord(tableName);
210
211         return true;
212     }
213
214     /**
215      * API for updating a record into DB table.
216      * 
217      * @param tableName
218      *            table name to be updated
219      * @param filter
220      *            document filter
221      * @param record
222      *            record to be updated
223      * @return returns true if the record is updated successfully, or returns
224      *         false
225      */
226     public Boolean updateRecord(String tableName, Document filter,
227             Document record) {
228
229         if (tableName == null || filter == null || record == null)
230             return false;
231
232         MongoCollection<Document> collection = db.getCollection(tableName);
233
234         if (collection.findOneAndReplace(filter, record) == null) {
235
236             Log.warn("DB updateX509CRL failed due to no matched record!");
237             return false;
238         }
239
240         showRecord(tableName);
241
242         return true;
243     }
244
245     /**
246      * API for deleting records from DB table.
247      * 
248      * @param tableName
249      *            table name for the record to be deleted
250      * @param record
251      *            record filter to be deleted
252      * @return returns true if the record is deleted successfully, or returns
253      *         false
254      */
255     public Boolean deleteRecord(String tableName, Document record) {
256
257         if (tableName == null || record == null)
258             return false;
259
260         MongoCollection<Document> collection = db.getCollection(tableName);
261
262         try {
263
264             DeleteResult result = collection.deleteMany(record);
265
266             if (result.getDeletedCount() == 0) {
267                 Log.warn("DB delete failed due to no mached record!");
268                 return false;
269             }
270
271         } catch (Exception e) {
272
273             e.printStackTrace();
274             return false;
275         }
276
277         showRecord(tableName);
278
279         return true;
280     }
281
282     /**
283      * API for selecting records from DB table.
284      * 
285      * @param tableName
286      *            table name for the record to be selected
287      * @param doc
288      *            document filter to be selected
289      * @return record list according to the filter document
290      */
291     public ArrayList<HashMap<String, Object>> selectRecord(String tableName,
292             Document doc) {
293
294         if (tableName == null || doc == null)
295             return new ArrayList<>();
296
297         MongoCollection<Document> collection = db.getCollection(tableName);
298         MongoCursor<Document> cursor = collection.find(doc).iterator();
299
300         ArrayList<HashMap<String, Object>> recordList = new ArrayList<HashMap<String, Object>>();
301
302         try {
303
304             while (cursor.hasNext()) {
305                 Document selectedDoc = cursor.next();
306                 recordList.add(convertDocumentToHashMap(selectedDoc));
307             }
308
309         } finally {
310
311             cursor.close();
312         }
313
314         return recordList;
315     }
316
317     private HashMap<String, Object> convertDocumentToHashMap(Document doc) {
318         HashMap<String, Object> resourceMap = new HashMap<String, Object>();
319
320         Set<Entry<String, Object>> entrySet = doc.entrySet();
321         Iterator<Entry<String, Object>> entryIter = entrySet.iterator();
322
323         while (entryIter.hasNext()) {
324
325             Map.Entry<String, Object> entry = (Map.Entry<String, Object>) entryIter
326                     .next();
327
328             String entryKey = entry.getKey();
329
330             // remove a mongoDB index
331             if (entry.getValue() != null && !entryKey.equals("_id")) {
332
333                 // if value is Array
334                 if (entry.getValue() instanceof List
335                         && !((List) entry.getValue()).isEmpty()
336                         && ((List) entry.getValue()).get(0) instanceof Document)
337
338                 {
339                     List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
340
341                     for (Document document : (List<Document>) entry
342                             .getValue()) {
343                         list.add(convertDocumentToHashMap(document));
344                     }
345                     resourceMap.put(entry.getKey(), list);
346                 } else {
347                     resourceMap.put(entry.getKey(), entry.getValue());
348                 }
349             }
350         }
351
352         return resourceMap;
353     }
354
355     private void showRecord(String tableName) {
356
357         MongoCollection<Document> collection = db.getCollection(tableName);
358         MongoCursor<Document> cursor = collection.find().iterator();
359
360         Log.info("<" + tableName + ">");
361
362         HashMap<String, Object> records = null;
363         int index = 0;
364         while (cursor.hasNext()) {
365
366             Document doc = cursor.next();
367             records = convertDocumentToHashMap(doc);
368
369             Log.info("[" + index + "] " + records.toString());
370             index++;
371         }
372
373         cursor.close();
374     }
375 }