IOT-3143
[iotivity.git] / cloud / resourcedirectory / src / main / java / org / iotivity / cloud / rdserver / db / DBManager.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.rdserver.db;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.Set;
30
31 import org.bson.Document;
32 import org.iotivity.cloud.base.exception.ServerException.InternalServerErrorException;
33 import org.iotivity.cloud.rdserver.Constants;
34
35 /**
36  *
37  * This class provides a set of APIs to access a DataBase.
38  *
39  */
40 public class DBManager {
41
42     private static DBManager                   mDBManager;
43     private MongoDB                            mMongoDB   = null;
44     private HashMap<String, ArrayList<String>> mKeyField  = new HashMap<>();
45
46     private DBManager(String dbHost) {
47         createDatabase(dbHost);
48         createTables();
49         createIndexes();
50     }
51
52     /**
53      * API to return DBManager object
54      * 
55      * @return DBManager DBManager object
56      */
57     public static DBManager getInstance() {
58         if (mDBManager == null)
59             mDBManager = new DBManager("127.0.0.1");
60         return mDBManager;
61     }
62
63     /**
64      * API to create DBManager instance with specific host
65      *
66      * @return created DB manager
67      */
68     public static DBManager createInstance(String dbHost) {
69         if (mDBManager == null)
70             mDBManager = new DBManager(dbHost);
71         return mDBManager;
72     }
73
74     private void createDatabase(String dbHost) {
75         try {
76             mMongoDB = new MongoDB(dbHost, Constants.RD_DB_NAME);
77         } catch (Exception e) {
78             e.printStackTrace();
79             throw new InternalServerErrorException("Database create failed!");
80         }
81     }
82
83     private void createTables() {
84         mMongoDB.createTable(Constants.RD_TABLE);
85
86         // TODO cannot be drop in case of component scaling
87         mMongoDB.dropTable(Constants.PRESENCE_TABLE);
88         mMongoDB.createTable(Constants.PRESENCE_TABLE);
89     }
90
91     private void createIndexes() {
92
93         ArrayList<String> keys = new ArrayList<>();
94         keys.add(Constants.DEVICE_ID);
95         keys.add(Constants.INS);
96
97         mMongoDB.createIndex(Constants.RD_TABLE, keys);
98         mKeyField.put(Constants.RD_TABLE, keys);
99
100         keys = new ArrayList<>();
101         keys.add(Constants.DEVICE_ID);
102
103         mMongoDB.createIndex(Constants.PRESENCE_TABLE, keys);
104         mKeyField.put(Constants.PRESENCE_TABLE, keys);
105
106     }
107
108     /**
109      * API for inserting a record into DB table. the record will not be inserted
110      * if duplicated one.
111      * 
112      * @param tableName
113      *            table name to be inserted
114      * @param insert
115      *            record to be inserted
116      */
117     public void insertRecord(String tableName, HashMap<String, Object> insert) {
118
119         if (!_insertRecord(tableName, insert))
120             throw new InternalServerErrorException(
121                     "Database record insert failed");
122     }
123
124     /**
125      * API for inserting a record into DB table. the record will be replaced if
126      * duplicated one.
127      * 
128      * @param tableName
129      *            table name to be inserted or replaced
130      * @param replace
131      *            record to be inserted
132      */
133     public void insertAndReplaceRecord(String tableName,
134             HashMap<String, Object> replace) {
135
136         if (!_insertAndReplaceRecord(tableName, replace))
137             throw new InternalServerErrorException(
138                     "Database record insert failed");
139     }
140
141     /**
142      * API for selecting records from DB table.
143      * 
144      * @param tableName
145      *            table name to be selected
146      * @param condition
147      *            condition record to be selected
148      * @return selected records
149      */
150     public ArrayList<HashMap<String, Object>> selectRecord(String tableName,
151             HashMap<String, Object> condition) {
152
153         return _selectRecord(tableName, condition);
154     }
155
156     /**
157      * API for selecting records to primary key from DB table
158      * 
159      * @param tableName
160      *            table name to be selected
161      * 
162      * @param condition
163      *            condition record to be selected
164      * @return selected record
165      */
166
167     public HashMap<String, Object> selectOneRecord(String tableName,
168             HashMap<String, Object> condition) {
169
170         ArrayList<HashMap<String, Object>> records = _selectRecord(tableName,
171                 condition);
172
173         if (records != null && records.size() > 1) {
174             throw new InternalServerErrorException(
175                     "Database record select failed");
176         }
177
178         if (records.isEmpty()) {
179             return new HashMap<String, Object>();
180         } else {
181             return records.get(0);
182         }
183
184     }
185
186     /**
187      * API for deleting records from DB table.
188      * 
189      * @param tableName
190      *            table name to be deleted
191      * @param condition
192      *            condition record to be deleted
193      */
194     public void deleteRecord(String tableName,
195             HashMap<String, Object> condition) {
196
197         if (!_deleteRecord(tableName, condition))
198             throw new InternalServerErrorException(
199                     "Database record delete failed");
200     }
201
202     /**
203      * API for updating a record into DB table.
204      * 
205      * @param tableName
206      *            table name to be updated
207      * @param replace
208      *            record to be updated
209      */
210     public void updateRecord(String tableName,
211             HashMap<String, Object> replace) {
212
213         if (!_updateRecord(tableName, replace))
214             throw new InternalServerErrorException(
215                     "Database record update failed");
216
217     }
218
219     private Boolean _insertRecord(String tableName,
220             HashMap<String, Object> record) {
221
222         Document doc = createDocument(record);
223
224         return mMongoDB.insertRecord(tableName, doc);
225     }
226
227     private Boolean _insertAndReplaceRecord(String tableName,
228             HashMap<String, Object> record) {
229
230         Document doc = createDocument(record);
231         Document filter = getKeyFilter(tableName, record);
232
233         return mMongoDB.insertAndReplaceRecord(tableName, filter, doc);
234     }
235
236     private Boolean _deleteRecord(String tableName,
237             HashMap<String, Object> condition) {
238
239         Document doc = createDocument(condition);
240
241         return mMongoDB.deleteRecord(tableName, doc);
242     }
243
244     private Boolean _updateRecord(String tableName,
245             HashMap<String, Object> record) {
246
247         Document replace = createDocument(record);
248         Document filter = getKeyFilter(tableName, record);
249
250         return mMongoDB.updateRecord(tableName, filter, replace);
251     }
252
253     private ArrayList<HashMap<String, Object>> _selectRecord(String tableName,
254             HashMap<String, Object> record) {
255
256         Document doc = createDocument(record);
257
258         return mMongoDB.selectRecord(tableName, doc);
259     }
260
261     private Document getKeyFilter(String tableName,
262             HashMap<String, Object> record) {
263
264         Document filterDoc = new Document();
265
266         ArrayList<String> keys = mKeyField.get(tableName);
267
268         for (String key : keys) {
269
270             Object value = record.get(key);
271             filterDoc.append(key, value);
272         }
273
274         return filterDoc;
275     }
276
277     private Document createDocument(HashMap<String, Object> record) {
278
279         Document doc = new Document();
280         Set<Entry<String, Object>> resEntrySet = record.entrySet();
281         Iterator<Entry<String, Object>> entryIter = resEntrySet.iterator();
282
283         while (entryIter.hasNext()) {
284             Map.Entry<String, Object> entry = (Map.Entry<String, Object>) entryIter
285                     .next();
286             doc.append(entry.getKey().toString(), entry.getValue());
287         }
288
289         return doc;
290     }
291
292 }