7a01402346e43d62ae357666b6fd9fb0a02d0588
[iotivity.git] / cloud / resourcedirectory / src / main / java / org / iotivity / cloud / rdserver / resources / directory / RDManager.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.resources.directory;
23
24 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
25 import org.iotivity.cloud.rdserver.Constants;
26 import org.iotivity.cloud.rdserver.db.DBManager;
27 import org.iotivity.cloud.rdserver.resources.directory.rd.InsManager;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import java.util.*;
32 import java.util.stream.Collectors;
33
34 /**
35  *
36  * This class provides a set of APIs handle requests about resource information
37  *
38  */
39 public class RDManager {
40     private final static Logger                Log               = LoggerFactory.getLogger(RDManager.class);
41     private InsManager                         mInsManager       = new InsManager();
42     private PayloadManager                     mPayloadManager   = new PayloadManager();
43
44     private ArrayList<HashMap<String, Object>> mResourcePresence = new ArrayList<>();
45
46     private static final RDManager INSTANCE = new RDManager();
47
48     public static RDManager getInstance(){
49         return INSTANCE;
50     }
51
52
53     /**
54      * API for handling resource-publish process
55      *
56      * @param requestPayload
57      *            request payload
58      * @return response payload
59      */
60     public HashMap<String, Object> publishResource(
61             HashMap<String, Object> requestPayload) {
62
63         HashMap<String, Object> deviceInfo = setResourceDeviceInfo(
64                 requestPayload);
65         ArrayList<HashMap<String, Object>> links = getLinks(requestPayload);
66
67         // check ins and set ins
68         setResourceIns(deviceInfo.get(Constants.DEVICE_ID).toString(), links);
69
70         storeResource(links, deviceInfo);
71
72         return requestPayload;
73
74     }
75
76     // set di, n, lt info
77     private HashMap<String, Object> setResourceDeviceInfo(
78             HashMap<String, Object> payload) {
79         return mPayloadManager.setPayloadData(payload,
80                 mPayloadManager.pubTagKey);
81     }
82
83     private ArrayList<HashMap<String, Object>> getLinks(
84             HashMap<String, Object> requestPayload) {
85         return (ArrayList<HashMap<String, Object>>) requestPayload
86                 .get(Constants.LINKS);
87
88     }
89
90     private void storeResource(ArrayList<HashMap<String, Object>> links,
91                                HashMap<String, Object> deviceInfo) {
92
93         ArrayList<HashMap<String, Object>> resourcePresence = new ArrayList<>();
94
95         for (HashMap<String, Object> link : links) {
96             HashMap<String, Object> storeInfo = new HashMap<>();
97             HashMap<String, Object> storeLink = mPayloadManager
98                     .setPayloadData(link, mPayloadManager.pubLinkKey);
99             mPayloadManager.changePolicyTypeToStore(storeLink);
100             storeInfo.putAll(storeLink);
101             storeInfo.putAll(deviceInfo);
102             storeResourceInDB(storeInfo);
103             resourcePresence.add(storeInfo);
104         }
105         setmResourcePresence(resourcePresence);
106
107     }
108
109     private void storeResourceInDB(HashMap<String, Object> rdInfo) {
110         HashMap<String, Object> condition = new HashMap<>();
111         condition.put(Constants.DEVICE_ID, rdInfo.get(Constants.DEVICE_ID));
112         condition.put(Constants.INS, rdInfo.get(Constants.INS));
113         if (checkResourceExist(condition).isEmpty()) {
114             DBManager.getInstance().insertRecord(Constants.RD_TABLE, rdInfo);
115             // set resource presence
116             rdInfo.put(Constants.TRIGGER, Constants.RES_CREATE);
117         } else {
118             DBManager.getInstance().insertAndReplaceRecord(Constants.RD_TABLE,
119                     rdInfo);
120             rdInfo.put(Constants.TRIGGER, Constants.RES_CHANGE);
121         }
122
123     }
124
125     private void setResourceIns(String di,
126                                 ArrayList<HashMap<String, Object>> links) {
127
128         for (HashMap<String, Object> link : links) {
129             String href = link.get(Constants.HREF).toString();
130             int ins = (int) link.get(Constants.INS);
131             int newIns = checkResourceIns(di, href, ins);
132             if (newIns == -1) {
133                 throw new BadRequestException("resource ins is not correct");
134             }
135             link.put(Constants.INS, newIns);
136         }
137     }
138
139     private int checkResourceIns(String di, String href, int ins) {
140         int storedIns = mInsManager.getIns(di, href);
141         if (ins == 0) {
142             if (storedIns == -1) {
143                 // create ins
144                 ins = mInsManager.createIns(di);
145             } else {
146                 ins = storedIns;
147             }
148         } else {
149             if (ins != storedIns) {
150                 ins = -1;
151             }
152         }
153         return ins;
154     }
155
156     /**
157      * API for handling resource-delete process
158      *
159      * @param di
160      *            device id
161      * @param insList
162      *            unique id of resource
163      */
164     public void deleteResource(String di, List<String> insList) {
165
166         HashMap<String, Object> condition = new HashMap<>();
167         condition.put(Constants.DEVICE_ID, di);
168
169         ArrayList<HashMap<String, Object>> foundRecord = new ArrayList<>();
170
171         if (insList == null) {
172             foundRecord = checkResourceExist(condition);
173             DBManager.getInstance().deleteRecord(Constants.RD_TABLE, condition);
174         } else {
175             for (String ins : insList) {
176                 condition.put(Constants.INS, Integer.parseInt(ins));
177                 if (!checkResourceExist(condition).isEmpty()) {
178                     foundRecord.add(checkResourceExist(condition).get(0));
179                     DBManager.getInstance().deleteRecord(Constants.RD_TABLE,
180                             condition);
181                 }
182             }
183         }
184
185         if (!foundRecord.isEmpty()) {
186             // set resource presence
187             for (HashMap<String, Object> record : foundRecord) {
188                 record.put(Constants.TRIGGER, Constants.RES_DELETE);
189             }
190             setmResourcePresence(foundRecord);
191         }
192     }
193
194     private ArrayList<HashMap<String, Object>> checkResourceExist(
195             HashMap<String, Object> condition) {
196         ArrayList<HashMap<String, Object>> records = DBManager.getInstance()
197                 .selectRecord(Constants.RD_TABLE, condition);
198
199         return records;
200     }
201
202     /**
203      * API for handling resource-discover process
204      *
205      * @param diList
206      *            list of device id
207      * @param rtList
208      *            list of resource type
209      * @param ifList
210      *            list of resource interface
211      * @return response payload
212      */
213     public ArrayList<Object> discoverResource(List<String> diList,
214                                               List<String> rtList, List<String> ifList) {
215
216         ArrayList<Object> response = new ArrayList<>();
217
218         if (diList == null) {
219             return response;
220         }
221
222         final List<String> diFiltered = filterDeviceByStatus(diList);
223         if(diFiltered == null || diFiltered.size() == 0){
224             return response;
225         }
226         final HashMap<String,Object> conditions = new HashMap<>();
227         conditions.put("di",buildInQuery(diFiltered));
228
229         if(rtList != null && rtList.size() > 0){
230             conditions.put("rt",buildInQuery(rtList));
231         }
232
233         if(ifList != null && ifList.size() > 0){
234             conditions.put("if",buildInQuery(rtList));
235         }
236
237         readResource(conditions,response);
238
239         Log.debug("discovery payload : " + response);
240
241         return response;
242     }
243
244     private void readResource(
245             HashMap<String, Object> condition, ArrayList<Object> response) {
246
247         ArrayList<HashMap<String, Object>> records = DBManager.getInstance()
248                 .selectRecord(Constants.RD_TABLE, condition);
249         if (!records.isEmpty()) {
250             response.add(makeDiscoverResponseSegment(records));
251         }
252     }
253
254     private List<String> filterDeviceByStatus(final List<String> diList){
255
256         final HashMap<String,Object> query = new HashMap<>();
257         if(diList != null && diList.size() > 0){
258             query.put("di",buildInQuery(diList));
259         }
260         query.put("state",Constants.PRESENCE_ON);
261         ArrayList<HashMap<String, Object>> records = DBManager.getInstance()
262                 .selectRecord(Constants.PRESENCE_TABLE, query);
263         return records.stream().map(record -> (String)record.get("di")).collect(Collectors.toList());
264     }
265
266     private HashMap<String, Object> makeDiscoverResponseSegment(
267             ArrayList<HashMap<String, Object>> records) {
268
269         HashMap<String, Object> responseSegment = new HashMap<>();
270
271         // make Tags
272         HashMap<String, Object> discoverTag = mPayloadManager
273                 .setPayloadData(records.get(0), mPayloadManager.discoverTagKey);
274         responseSegment.putAll(discoverTag);
275
276         ArrayList<Object> links = new ArrayList<>();
277         // make links
278         for (HashMap<String, Object> record : records) {
279             HashMap<String, Object> link = mPayloadManager
280                     .setPayloadData(record, mPayloadManager.discoverLinkKey);
281             mPayloadManager.changePolicyTypeToDiscover(link);
282             links.add(link);
283         }
284         responseSegment.put(Constants.LINKS, links);
285
286         return responseSegment;
287
288     }
289
290     private void setmResourcePresence(
291             ArrayList<HashMap<String, Object>> resourcePresence) {
292         this.mResourcePresence = resourcePresence;
293     }
294
295     /**
296      * API for getting resource information to notify
297      *
298      * @return resource information
299      */
300     public ArrayList<HashMap<String, Object>> getmResourcePresence() {
301         return mResourcePresence;
302     }
303
304
305     private <T extends Object> HashMap<String,Object> buildInQuery(final Collection<T> items){
306         final HashMap<String,Object> query = new HashMap<>();
307         query.put("$in",items);
308         return query;
309     }
310
311 }