fixed CI unit test.
[iotivity.git] / cloud / interface / src / main / java / org / iotivity / cloud / ciserver / resources / DiResource.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;
23
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.List;
28
29 import org.iotivity.cloud.base.device.CoapDevice;
30 import org.iotivity.cloud.base.device.Device;
31 import org.iotivity.cloud.base.device.IRequestChannel;
32 import org.iotivity.cloud.base.device.IResponseEventHandler;
33 import org.iotivity.cloud.base.exception.ServerException;
34 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
35 import org.iotivity.cloud.base.exception.ServerException.NotFoundException;
36 import org.iotivity.cloud.base.exception.ServerException.PreconditionFailedException;
37 import org.iotivity.cloud.base.protocols.IRequest;
38 import org.iotivity.cloud.base.protocols.IResponse;
39 import org.iotivity.cloud.base.protocols.MessageBuilder;
40 import org.iotivity.cloud.base.protocols.coap.CoapResponse;
41 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
42 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
43 import org.iotivity.cloud.base.resource.Resource;
44 import org.iotivity.cloud.ciserver.Constants;
45 import org.iotivity.cloud.ciserver.DeviceServerSystem.CoapDevicePool;
46 import org.iotivity.cloud.util.Cbor;
47
48 public class DiResource extends Resource {
49
50     private CoapDevicePool mDevicePool = null;
51
52     public DiResource(CoapDevicePool devicePool) {
53         super(Arrays.asList(Constants.REQ_DEVICE_ID));
54         mDevicePool = devicePool;
55
56         addQueryHandler(
57                 Arrays.asList(Constants.RS_INTERFACE + "="
58                         + Constants.LINK_INTERFACE),
59                 this::onLinkInterfaceRequestReceived);
60     }
61
62     private IRequestChannel getTargetDeviceChannel(IRequest request)
63             throws ServerException {
64         List<String> uriPathSegment = request.getUriPathSegments();
65
66         if (uriPathSegment.size() < 2) {
67             throw new PreconditionFailedException();
68         }
69
70         String deviceId = uriPathSegment.get(1);
71         CoapDevice targetDevice = (CoapDevice) mDevicePool
72                 .queryDevice(deviceId);
73
74         if (targetDevice == null) {
75             throw new NotFoundException();
76         }
77
78         // Do request and receive response
79         return targetDevice.getRequestChannel();
80     }
81
82     private String extractTargetUriPath(IRequest request) {
83         List<String> uriPathSegment = request.getUriPathSegments();
84
85         // Remove prefix path
86         uriPathSegment.remove(0);
87         uriPathSegment.remove(0);
88
89         StringBuilder uriPath = new StringBuilder();
90         for (String path : uriPathSegment) {
91             uriPath.append("/" + path);
92         }
93
94         return uriPath.toString();
95     }
96
97     private IResponse convertReponseUri(IResponse response, String di) {
98
99         String convertedUri = new String();
100
101         CoapResponse coapResponse = (CoapResponse) response;
102
103         if (coapResponse.getUriPath().isEmpty() == false) {
104             convertedUri = "/di/" + di + "/" + coapResponse.getUriPath();
105         }
106
107         return MessageBuilder.modifyResponse(response, convertedUri, null,
108                 null);
109     }
110
111     class LinkInterfaceHandler implements IResponseEventHandler {
112         private Cbor<List<HashMap<String, Object>>> mCbor      = new Cbor<>();
113         private String                              mTargetDI  = null;
114         private Device                              mSrcDevice = null;
115
116         public LinkInterfaceHandler(String targetDI, Device srcDevice) {
117             mTargetDI = targetDI;
118             mSrcDevice = srcDevice;
119         }
120
121         private void convertHref(List<HashMap<String, Object>> linkPayload) {
122             for (HashMap<String, Object> link : linkPayload) {
123                 link.put("href", "/di/" + mTargetDI + link.get("href"));
124             }
125         }
126
127         @Override
128         public void onResponseReceived(IResponse response) {
129             List<HashMap<String, Object>> linkPayload = null;
130             if (response.getStatus() == ResponseStatus.CONTENT) {
131                 linkPayload = mCbor.parsePayloadFromCbor(response.getPayload(),
132                         ArrayList.class);
133                 if (linkPayload == null) {
134                     throw new BadRequestException("payload is null");
135                 }
136                 convertHref(linkPayload);
137             }
138
139             mSrcDevice.sendResponse(MessageBuilder.modifyResponse(
140                     convertReponseUri(response, mTargetDI),
141                     ContentFormat.APPLICATION_CBOR, linkPayload != null
142                             ? mCbor.encodingPayloadToCbor(linkPayload) : null));
143         }
144     }
145
146     public void onLinkInterfaceRequestReceived(Device srcDevice,
147             IRequest request) throws ServerException {
148         IRequestChannel requestChannel = getTargetDeviceChannel(request);
149
150         if (requestChannel == null) {
151             throw new NotFoundException();
152         }
153
154         String deviceId = request.getUriPathSegments().get(1);
155
156         requestChannel.sendRequest(
157                 MessageBuilder.modifyRequest(request,
158                         extractTargetUriPath(request), null, null, null),
159                 new LinkInterfaceHandler(deviceId, srcDevice));
160     }
161
162     class DefaultResponseHandler implements IResponseEventHandler {
163         private String mTargetDI  = null;
164         private Device mSrcDevice = null;
165
166         public DefaultResponseHandler(String targetDI, Device srcDevice) {
167             mTargetDI = targetDI;
168             mSrcDevice = srcDevice;
169         }
170
171         @Override
172         public void onResponseReceived(IResponse response) {
173
174             mSrcDevice.sendResponse(convertReponseUri(response, mTargetDI));
175         }
176     }
177
178     // This is optional method for packet handling
179     @Override
180     public void onDefaultRequestReceived(Device srcDevice, IRequest request)
181             throws ServerException {
182         // Find proper request channel using di in URI path field.
183         IRequestChannel requestChannel = getTargetDeviceChannel(request);
184
185         if (requestChannel == null) {
186             throw new NotFoundException();
187         }
188
189         String deviceId = request.getUriPathSegments().get(1);
190
191         requestChannel.sendRequest(
192                 MessageBuilder.modifyRequest(request,
193                         extractTargetUriPath(request), null, null, null),
194                 new DefaultResponseHandler(deviceId, srcDevice));
195     }
196
197 }