IOT-3143
[iotivity.git] / cloud / interface / src / main / java / org / iotivity / cloud / ciserver / resources / proxy / rd / ResourceDirectory.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.ciserver.resources.proxy.rd;
23
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27
28 import org.iotivity.cloud.base.connector.ConnectorPool;
29 import org.iotivity.cloud.base.device.Device;
30 import org.iotivity.cloud.base.device.IRequestChannel;
31 import org.iotivity.cloud.base.device.IResponseEventHandler;
32 import org.iotivity.cloud.base.exception.ClientException;
33 import org.iotivity.cloud.base.exception.ServerException;
34 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
35 import org.iotivity.cloud.base.protocols.IRequest;
36 import org.iotivity.cloud.base.protocols.IResponse;
37 import org.iotivity.cloud.base.protocols.MessageBuilder;
38 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
39 import org.iotivity.cloud.base.protocols.enums.RequestMethod;
40 import org.iotivity.cloud.base.resource.Resource;
41 import org.iotivity.cloud.ciserver.Constants;
42 import org.iotivity.cloud.util.Cbor;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  *
47  * This class provides a set of APIs to send requests about publish resource to
48  * resource directory
49  *
50  */
51
52 public class ResourceDirectory extends Resource {
53     private Cbor<HashMap<String, Object>> mCbor     = new Cbor<>();
54     private final static org.slf4j.Logger Log       = LoggerFactory.getLogger(ResourceDirectory.class);
55
56     public ResourceDirectory() {
57         super(Arrays.asList(Constants.PREFIX_OIC, Constants.RD_URI));
58     }
59
60     @Override
61     public void onDefaultRequestReceived(Device srcDevice, IRequest request)
62             throws ServerException {
63         switch (request.getMethod()) {
64             case POST:
65                 HashMap<String, Object> payloadData = mCbor
66                         .parsePayloadFromCbor(request.getPayload(),
67                                 HashMap.class);
68                 StringBuffer query = new StringBuffer();
69                 query.append("op=add;");
70                 query.append(Constants.USER_ID + "=" + srcDevice.getUserId());
71
72                 StringBuffer uriPath = new StringBuffer();
73                 uriPath.append(Constants.PREFIX_OIC + "/");
74                 uriPath.append(Constants.ACL_URI + "/");
75                 uriPath.append(Constants.GROUP_URI + "/");
76                 uriPath.append(srcDevice.getUserId());
77
78                 String di = payloadData.get(Constants.REQ_DEVICE_ID).toString();
79                 HashMap<String, Object> requestPayload = new HashMap<>();
80
81                 requestPayload.put(Constants.REQ_GROUP_DEVICES,
82                         Arrays.asList(di));
83                 IRequest requestToAS = MessageBuilder.createRequest(
84                         RequestMethod.POST, uriPath.toString(),
85                         query.toString(), ContentFormat.APPLICATION_CBOR,
86                         mCbor.encodingPayloadToCbor(requestPayload));
87
88                 IRequestChannel resourceDirectoryConnection = ConnectorPool.getConnection("rd");
89                 ConnectorPool.getConnection("account").sendRequest(requestToAS,
90                         new AccountReceiveHandler(resourceDirectoryConnection, request, srcDevice));
91                 break;
92
93             case DELETE:
94                 ConnectorPool.getConnection("rd").sendRequest(request, srcDevice);
95                 break;
96
97             default:
98                 throw new BadRequestException(
99                         request.getMethod() + " request type is not support");
100         }
101     }
102
103     class AccountReceiveHandler implements IResponseEventHandler {
104         private IRequestChannel resourceDirectoryConnection;
105         private Device   mSrcDevice;
106         private IRequest mRequest;
107
108         public AccountReceiveHandler(IRequestChannel resourceDirectoryConnection, IRequest request, Device srcDevice) {
109             this.resourceDirectoryConnection = resourceDirectoryConnection;
110             mSrcDevice = srcDevice;
111             mRequest = request;
112         }
113
114         @Override
115         public void onResponseReceived(IResponse response)
116                 throws ClientException {
117
118             switch (response.getStatus()) {
119                 case CHANGED:
120                     byte[] convertedPayload = convertPublishHref(mRequest,
121                             mSrcDevice);
122
123                     mRequest = MessageBuilder.modifyRequest(mRequest, null,
124                             null, ContentFormat.APPLICATION_CBOR,
125                             convertedPayload);
126
127                     resourceDirectoryConnection.sendRequest(mRequest,
128                             new PublishResponseHandler(mSrcDevice));
129                     break;
130
131                 default:
132                     mSrcDevice.sendResponse(response);
133             }
134         }
135
136         @SuppressWarnings("unchecked")
137         private byte[] convertPublishHref(IRequest request, Device device) {
138
139             Cbor<HashMap<String, Object>> cbor = new Cbor<>();
140             HashMap<String, Object> payload = cbor
141                     .parsePayloadFromCbor(request.getPayload(), HashMap.class);
142
143             ArrayList<HashMap<String, Object>> links = (ArrayList<HashMap<String, Object>>) payload
144                     .get(Constants.REQ_LINKS);
145
146             for (HashMap<String, Object> link : links) {
147
148                 String href = (String) link.get(Constants.REQ_HREF);
149                 href = Constants.ROUTE_FULL_URI + "/" + device.getDeviceId()
150                         + href;
151
152                 link.put(Constants.REQ_HREF, href);
153             }
154
155             payload.put(Constants.REQ_LINKS, links);
156
157             return cbor.encodingPayloadToCbor(payload);
158         }
159     }
160
161     // handles response to convert href in response payload into original href
162     // when resource published or updated
163     class PublishResponseHandler implements IResponseEventHandler {
164
165         private Device mSrcDevice;
166
167         public PublishResponseHandler(Device srcDevice) {
168             mSrcDevice = srcDevice;
169         }
170
171         @Override
172         public void onResponseReceived(IResponse response)
173                 throws ClientException {
174
175             switch (response.getStatus()) {
176                 case CHANGED:
177                     response = MessageBuilder.modifyResponse(response,
178                             ContentFormat.APPLICATION_CBOR,
179                             convertResponseHref(response));
180
181                 default:
182                     mSrcDevice.sendResponse(response);
183             }
184         }
185
186         @SuppressWarnings("unchecked")
187         private byte[] convertResponseHref(IResponse response) {
188
189             Cbor<HashMap<String, Object>> cbor = new Cbor<>();
190             HashMap<String, Object> payload = cbor
191                     .parsePayloadFromCbor(response.getPayload(), HashMap.class);
192
193             ArrayList<HashMap<String, Object>> links = (ArrayList<HashMap<String, Object>>) payload
194                     .get(Constants.REQ_LINKS);
195
196             for (HashMap<String, Object> link : links) {
197
198                 String href = (String) link.get(Constants.REQ_HREF);
199
200                 // remove prefix
201                 ArrayList<String> hrefSegments = new ArrayList<>(
202                         Arrays.asList(href.split("/")));
203
204                 ArrayList<String> RouteResourceSegment = new ArrayList<>(
205                         Arrays.asList(Constants.ROUTE_FULL_URI.split("/")));
206
207                 for (String path : RouteResourceSegment) {
208                     hrefSegments.remove(path);
209                 }
210                 hrefSegments.remove(0);
211
212                 StringBuilder newHref = new StringBuilder();
213                 for (String path : hrefSegments) {
214                     newHref.append("/" + path);
215                 }
216
217                 link.put(Constants.REQ_HREF, newHref.toString());
218             }
219
220             payload.put(Constants.REQ_LINKS, links);
221
222             return cbor.encodingPayloadToCbor(payload);
223         }
224     }
225
226 }