blob: 038d38e3d3f0fea56cba78b9e9047d7ccd1cc05a [file] [log] [blame]
Constantin Ziesche687f8882020-10-02 16:17:44 +02001/*******************************************************************************
2* Copyright (c) 2020 Robert Bosch GmbH
3* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
4*
5* This program and the accompanying materials are made available under the
6* terms of the Eclipse Public License 2.0 which is available at
7* http://www.eclipse.org/legal/epl-2.0
8*
9* SPDX-License-Identifier: EPL-2.0
10*******************************************************************************/
11using System.Collections.Generic;
12using Microsoft.AspNetCore.Mvc;
13using BaSyx.Models.Core.AssetAdministrationShell.Generics;
14using BaSyx.Utils.ResultHandling;
15using BaSyx.API.Components;
16using BaSyx.Models.Core.AssetAdministrationShell.Implementations;
17using BaSyx.Models.Communication;
Constantin Ziescheeb74d642020-11-04 17:57:12 +010018using System.Web;
Constantin Ziesche687f8882020-10-02 16:17:44 +020019
20namespace BaSyx.API.Http.Controllers
21{
22 /// <summary>
23 /// The Submodel Repository Controller
24 /// </summary>
25 public class SubmodelRepositoryController : Controller
26 {
27 private readonly ISubmodelRepositoryServiceProvider serviceProvider;
28
29 /// <summary>
30 /// The constructor for the Submodel Repository Controller
31 /// </summary>
32 /// <param name="submodelRepositoryServiceProvider"></param>
33 public SubmodelRepositoryController(ISubmodelRepositoryServiceProvider submodelRepositoryServiceProvider)
34 {
35 serviceProvider = submodelRepositoryServiceProvider;
36 }
37
38 /// <summary>
39 /// Retrieves all Submodels from the Submodel repository
40 /// </summary>
41 /// <returns></returns>
42 /// <response code="200">Returns a list of found Submodels</response>
43 [HttpGet("submodels", Name = "GetAllSubmodelsFromRepo")]
44 [Produces("application/json")]
45 [ProducesResponseType(typeof(List<Submodel>), 200)]
46 public IActionResult GetAllSubmodelsFromRepo()
47 {
48 var result = serviceProvider.RetrieveSubmodels();
49 return result.CreateActionResult(CrudOperation.Retrieve);
50 }
51 /// <summary>
52 /// Retrieves a specific Submodel from the Submodel repository
53 /// </summary>
54 /// <param name="submodelId">The Submodel's unique id</param>
55 /// <returns></returns>
56 /// <response code="200">Returns the requested Submodel</response>
57 /// <response code="404">No Submodel found</response>
58 [HttpGet("submodels/{submodelId}")]
59 [HttpGet("submodels/{submodelId}/submodel", Name = "RetrieveSubmodelFromRepoById")]
60 [Produces("application/json")]
61 [ProducesResponseType(typeof(Submodel), 200)]
62 public IActionResult RetrieveSubmodelFromRepoById(string submodelId)
63 {
64 if (string.IsNullOrEmpty(submodelId))
65 return ResultHandling.NullResult(nameof(submodelId));
66
Constantin Ziescheeb74d642020-11-04 17:57:12 +010067 submodelId = HttpUtility.UrlDecode(submodelId);
68
Constantin Ziesche687f8882020-10-02 16:17:44 +020069 var result = serviceProvider.RetrieveSubmodel(submodelId);
70 return result.CreateActionResult(CrudOperation.Retrieve);
71 }
72
73 /// <summary>
74 /// Creates or updates a Submodel at the Submodel repository
75 /// </summary>
76 /// <param name="submodelId">The Submodel's unique id</param>
77 /// <param name="submodel">The Submodel object</param>
78 /// <returns></returns>
79 /// <response code="201">Submodel created / updated successfully</response>
80 /// <response code="400">Bad Request</response>
81 [HttpPut("submodels/{submodelId}", Name = "PutSubmodelToRepo")]
82 [Produces("application/json")]
83 [Consumes("application/json")]
84 [ProducesResponseType(typeof(Submodel), 201)]
85 public IActionResult PutSubmodelToRepo(string submodelId, [FromBody] ISubmodel submodel)
86 {
87 if (string.IsNullOrEmpty(submodelId))
88 return ResultHandling.NullResult(nameof(submodelId));
89 if (submodel == null)
90 return ResultHandling.NullResult(nameof(submodel));
91
Constantin Ziescheeb74d642020-11-04 17:57:12 +010092 submodelId = HttpUtility.UrlDecode(submodelId);
93
94 if (submodelId != submodel.Identification.Id)
95 {
96 Result badRequestResult = new Result(false,
97 new Message(MessageType.Error, $"Passed path parameter {submodelId} does not equal the Submodel's Id {submodel.Identification.Id}", "400"));
98
99 return badRequestResult.CreateActionResult(CrudOperation.Create, "submodels/" + submodelId);
100 }
101
Constantin Ziesche687f8882020-10-02 16:17:44 +0200102 var result = serviceProvider.CreateSubmodel(submodel);
103 return result.CreateActionResult(CrudOperation.Create, "submodels/"+ submodelId);
104 }
105 /// <summary>
106 /// Deletes a specific Submodel at the Submodel repository
107 /// </summary>
108 /// <param name="submodelId">The Submodel's unique id</param>
109 /// <returns></returns>
110 /// <response code="200">Submodel deleted successfully</response>
111 [HttpDelete("submodels/{submodelId}", Name = "DeleteSubmodelFromRepoById")]
112 [Produces("application/json")]
113 [ProducesResponseType(typeof(Result), 200)]
114 public IActionResult DeleteSubmodelFromRepoById(string submodelId)
115 {
116 if (string.IsNullOrEmpty(submodelId))
117 return ResultHandling.NullResult(nameof(submodelId));
118
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100119 submodelId = HttpUtility.UrlDecode(submodelId);
120
Constantin Ziesche687f8882020-10-02 16:17:44 +0200121 var result = serviceProvider.DeleteSubmodel(submodelId);
122 return result.CreateActionResult(CrudOperation.Delete);
123 }
124
125 /*****************************************************************************************/
126 #region Routed Submodel Services
127
128 /// <summary>
129 /// Retrieves the minimized version of a Submodel, i.e. only the values of SubmodelElements are serialized and returned
130 /// </summary>
131 /// <param name="submodelId">The Submodel's unique id</param>
132 /// <returns></returns>
133 /// <response code="200">Success</response>
134 /// <response code="404">Submodel not found</response>
135 [HttpGet("submodels/{submodelId}/submodel/values", Name = "SubmodelRepo_GetSubmodelValues")]
136 [Produces("application/json")]
137 [ProducesResponseType(typeof(Result), 404)]
138 public IActionResult SubmodelRepo_GetSubmodelValues(string submodelId)
139 {
140 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
141 return result;
142
143 var service = new SubmodelController(provider);
144 return service.GetSubmodelValues();
145 }
146
147 /// <summary>
148 /// Retrieves all Submodel-Elements from the Submodel
149 /// </summary>
150 /// <param name="submodelId">The Submodel's unique id</param>
151 /// <returns></returns>
152 /// <response code="200">Returns a list of found Submodel-Elements</response>
153 /// <response code="404">Submodel not found</response>
154 [HttpGet("submodels/{submodelId}/submodel/submodelElements", Name = "SubmodelRepo_GetSubmodelElements")]
155 [Produces("application/json")]
156 [ProducesResponseType(typeof(SubmodelElement[]), 200)]
157 [ProducesResponseType(typeof(Result), 404)]
158 public IActionResult SubmodelRepo_GetSubmodelElements(string submodelId)
159 {
160 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
161 return result;
162
163 var service = new SubmodelController(provider);
164 return service.GetSubmodelElements();
165 }
166
167 /// <summary>
168 /// Creates or updates a Submodel-Element at the Submodel
169 /// </summary>
170 /// <param name="submodelId">The Submodel's unique id</param>
171 /// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
172 /// <param name="submodelElement">The Submodel-Element object</param>
173 /// <returns></returns>
174 /// <response code="201">Submodel-Element created successfully</response>
175 /// <response code="400">Bad Request</response>
176 /// <response code="404">Submodel not found</response>
177 [HttpPut("submodels/{submodelId}/submodel/submodelElements/{seIdShortPath}", Name = "SubmodelRepo_PutSubmodelElement")]
178 [Produces("application/json")]
179 [Consumes("application/json")]
180 [ProducesResponseType(typeof(SubmodelElement), 201)]
181 [ProducesResponseType(typeof(Result), 400)]
182 [ProducesResponseType(typeof(Result), 404)]
183 public IActionResult SubmodelRepo_PutSubmodelElement(string submodelId, string seIdShortPath, [FromBody] ISubmodelElement submodelElement)
184 {
185 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
186 return result;
187
188 var service = new SubmodelController(provider);
189 return service.PutSubmodelElement(seIdShortPath, submodelElement);
190 }
191 /// <summary>
192 /// Retrieves a specific Submodel-Element from the Submodel
193 /// </summary>
194 /// <param name="submodelId">The Submodel's unique id</param>
195 /// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
196 /// <returns></returns>
197 /// <response code="200">Returns the requested Submodel-Element</response>
198 /// <response code="404">Submodel / Submodel-Element not found</response>
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100199 [HttpGet("submodels/{submodelId}/submodel/submodelElements/{seIdShortPath}", Name = "SubmodelRepo_GetSubmodelElementById")]
Constantin Ziesche687f8882020-10-02 16:17:44 +0200200 [Produces("application/json")]
201 [ProducesResponseType(typeof(SubmodelElement), 200)]
202 [ProducesResponseType(typeof(Result), 404)]
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100203 public IActionResult SubmodelRepo_GetSubmodelElementById(string submodelId, string seIdShortPath)
Constantin Ziesche687f8882020-10-02 16:17:44 +0200204 {
205 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
206 return result;
207
208 var service = new SubmodelController(provider);
209 return service.GetSubmodelElementByIdShort(seIdShortPath);
210 }
211
212 /// <summary>
213 /// Retrieves the value of a specific Submodel-Element from the Submodel
214 /// </summary>
215 /// <param name="submodelId">The Submodel's unique id</param>
216 /// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
217 /// <returns></returns>
218 /// <response code="200">Returns the value of a specific Submodel-Element</response>
219 /// <response code="404">Submodel / Submodel-Element not found</response>
220 /// <response code="405">Method not allowed</response>
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100221 [HttpGet("submodels/{submodelId}/submodel/submodelElements/{seIdShortPath}/value", Name = "SubmodelRepo_GetSubmodelElementValueById")]
Constantin Ziesche687f8882020-10-02 16:17:44 +0200222 [Produces("application/json")]
223 [ProducesResponseType(typeof(object), 200)]
224 [ProducesResponseType(typeof(Result), 404)]
225 [ProducesResponseType(typeof(Result), 405)]
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100226 public IActionResult SubmodelRepo_GetSubmodelElementValueById(string submodelId, string seIdShortPath)
Constantin Ziesche687f8882020-10-02 16:17:44 +0200227 {
228 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
229 return result;
230
231 var service = new SubmodelController(provider);
232 return service.GetSubmodelElementValueByIdShort(seIdShortPath);
233 }
234
235 /// <summary>
236 /// Updates the Submodel-Element's value
237 /// </summary>
238 /// <param name="submodelId">The Submodel's unique id</param>
239 /// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
240 /// <param name="value">The new value</param>
241 /// <returns></returns>
242 /// <response code="200">Submodel-Element's value changed successfully</response>
243 /// <response code="404">Submodel / Submodel-Element not found</response>
244 /// <response code="405">Method not allowed</response>
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100245 [HttpPut("submodels/{submodelId}/submodel/submodelElements/{seIdShortPath}/value", Name = "SubmodelRepo_PutSubmodelElementValueById")]
Constantin Ziesche687f8882020-10-02 16:17:44 +0200246 [Produces("application/json")]
247 [Consumes("application/json")]
248 [ProducesResponseType(typeof(ElementValue), 200)]
249 [ProducesResponseType(typeof(Result), 404)]
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100250 public IActionResult SubmodelRepo_PutSubmodelElementValueById(string submodelId, string seIdShortPath, [FromBody] object value)
Constantin Ziesche687f8882020-10-02 16:17:44 +0200251 {
252 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
253 return result;
254
255 var service = new SubmodelController(provider);
256 return service.PutSubmodelElementValueByIdShort(seIdShortPath, value);
257 }
258
259 /// <summary>
260 /// Deletes a specific Submodel-Element from the Submodel
261 /// </summary>
262 /// <param name="submodelId">The Submodel's unique id</param>
263 /// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
264 /// <returns></returns>
265 /// <response code="204">Submodel-Element deleted successfully</response>
266 /// <response code="404">Submodel / Submodel-Element not found</response>
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100267 [HttpDelete("submodels/{submodelId}/submodel/submodelElements/{seIdShortPath}", Name = "SubmodelRepo_DeleteSubmodelElementById")]
Constantin Ziesche687f8882020-10-02 16:17:44 +0200268 [Produces("application/json")]
269 [ProducesResponseType(typeof(Result), 200)]
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100270 public IActionResult SubmodelRepo_DeleteSubmodelElementById(string submodelId, string seIdShortPath)
Constantin Ziesche687f8882020-10-02 16:17:44 +0200271 {
272 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
273 return result;
274
275 var service = new SubmodelController(provider);
276 return service.DeleteSubmodelElementByIdShort(seIdShortPath);
277 }
278
279 /// <summary>
280 /// Invokes a specific operation from the Submodel synchronously or asynchronously
281 /// </summary>
282 /// <param name="submodelId">The Submodel's unique id</param>
283 /// <param name="idShortPathToOperation">The IdShort path to the Operation</param>
284 /// <param name="invocationRequest">The parameterized request object for the invocation</param>
285 /// <param name="async">Determines whether the execution of the operation is asynchronous (true) or not (false)</param>
286 /// <returns></returns>
287 /// <response code="200">Operation invoked successfully</response>
288 /// <response code="400">Bad Request</response>
289 /// <response code="404">Submodel / Method handler not found</response>
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100290 [HttpPost("submodels/{submodelId}/submodel/submodelElements/{idShortPathToOperation}/invoke", Name = "SubmodelRepo_InvokeOperationById")]
Constantin Ziesche687f8882020-10-02 16:17:44 +0200291 [Produces("application/json")]
292 [Consumes("application/json")]
293 [ProducesResponseType(typeof(Result), 400)]
294 [ProducesResponseType(typeof(Result), 404)]
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100295 public IActionResult SubmodelRepo_InvokeOperationById(string submodelId, string idShortPathToOperation, [FromBody] InvocationRequest invocationRequest, [FromQuery] bool async)
Constantin Ziesche687f8882020-10-02 16:17:44 +0200296 {
297 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
298 return result;
299
300 var service = new SubmodelController(provider);
301 return service.InvokeOperationByIdShort(idShortPathToOperation, invocationRequest, async);
302 }
303
304 /// <summary>
305 /// Retrieves the result of an asynchronously started operation
306 /// </summary>
307 /// <param name="submodelId">The Submodel's unique id</param>
308 /// <param name="idShortPathToOperation">The IdShort path to the Operation</param>
309 /// <param name="requestId">The request id</param>
310 /// <returns></returns>
311 /// <response code="200">Result found</response>
312 /// <response code="400">Bad Request</response>
313 /// <response code="404">Submodel / Operation / Request not found</response>
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100314 [HttpGet("submodels/{submodelId}/submodel/submodelElements/{idShortPathToOperation}/invocationList/{requestId}", Name = "SubmodelRepo_GetInvocationResultById")]
Constantin Ziesche687f8882020-10-02 16:17:44 +0200315 [Produces("application/json")]
316 [ProducesResponseType(typeof(InvocationResponse), 200)]
317 [ProducesResponseType(typeof(Result), 400)]
318 [ProducesResponseType(typeof(Result), 404)]
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100319 public IActionResult SubmodelRepo_GetInvocationResultById(string submodelId, string idShortPathToOperation, string requestId)
Constantin Ziesche687f8882020-10-02 16:17:44 +0200320 {
321 if (IsNullOrNotFound(submodelId, out IActionResult result, out ISubmodelServiceProvider provider))
322 return result;
323
324 var service = new SubmodelController(provider);
325 return service.GetInvocationResultByIdShort(idShortPathToOperation, requestId);
326 }
327 #endregion
328
329 #region Helper
330 /// <summary>
331 /// Checks whether submodelId is null or Submodel Service Provider cannot be found
332 /// </summary>
333 /// <param name="submodelId">The Submodel's unique id</param>
334 /// <param name="result">The IActionResult in case submodelId is null or the provider cannot be found</param>
335 /// <param name="provider">The Submodel Service Provider</param>
336 /// <returns></returns>
337 public bool IsNullOrNotFound(string submodelId, out IActionResult result, out ISubmodelServiceProvider provider)
338 {
339 if (string.IsNullOrEmpty(submodelId))
340 {
341 result = ResultHandling.NullResult(nameof(submodelId));
342 provider = null;
343 return true;
344 }
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100345 submodelId = HttpUtility.UrlDecode(submodelId);
346 var retrievedProvider = serviceProvider.GetSubmodelServiceProvider(submodelId);
347 if (retrievedProvider.TryGetEntity(out provider))
Constantin Ziesche687f8882020-10-02 16:17:44 +0200348 {
Constantin Ziescheeb74d642020-11-04 17:57:12 +0100349 result = null;
350 return false;
351 }
352 else
353 {
354 provider = null;
Constantin Ziesche687f8882020-10-02 16:17:44 +0200355 result = NotFound(new Result(false, new NotFoundMessage("Submodel Provider")));
356 return true;
357 }
Constantin Ziesche687f8882020-10-02 16:17:44 +0200358 }
359
360 #endregion
361 }
362}