blob: 547301ec6956ddb0e18ebe99587aa48180bf8c5d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020 Robert Bosch GmbH
* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
using Microsoft.AspNetCore.Mvc;
using BaSyx.Models.Core.AssetAdministrationShell.Generics;
using BaSyx.Utils.ResultHandling;
using BaSyx.API.Components;
using System;
using Newtonsoft.Json.Linq;
using BaSyx.Models.Extensions;
using BaSyx.Models.Core.AssetAdministrationShell.Implementations;
using BaSyx.Models.Communication;
using System.Web;
using System.ComponentModel;
namespace BaSyx.API.Http.Controllers
{
/// <summary>
/// The Submodel Controller
/// </summary>
[DisplayName("Submodel Interface")]
public class SubmodelController : Controller
{
private readonly ISubmodelServiceProvider serviceProvider;
/// <summary>
/// The constructor for the Submodel Controller
/// </summary>
/// <param name="submodelServiceProvider">The Submodel Service Provider implementation provided by the dependency injection</param>
public SubmodelController(ISubmodelServiceProvider submodelServiceProvider)
{
serviceProvider = submodelServiceProvider;
}
/// <summary>
/// Retrieves the entire Submodel
/// </summary>
/// <returns></returns>
/// <response code="200">Success</response>
/// <response code="404">Submodel not found</response>
[HttpGet("submodel", Name = "GetSubmodel")]
[Produces("application/json")]
[ProducesResponseType(typeof(Submodel), 200)]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult GetSubmodel()
{
var result = serviceProvider.RetrieveSubmodel();
return result.CreateActionResult(CrudOperation.Retrieve);
}
/// <summary>
/// Retrieves the minimized version of a Submodel, i.e. only the values of SubmodelElements are serialized and returned
/// </summary>
/// <returns></returns>
/// <response code="200">Success</response>
/// <response code="404">Submodel not found</response>
[HttpGet("submodel/values", Name = "GetSubmodelValues")]
[Produces("application/json")]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult GetSubmodelValues()
{
var result = serviceProvider.RetrieveSubmodel();
if (result != null && result.Entity != null)
{
JObject minimizedSubmodel = result.Entity.MinimizeSubmodel();
return new JsonResult(minimizedSubmodel);
}
return result.CreateActionResult(CrudOperation.Retrieve);
}
/// <summary>
/// Retrieves a customizable table version of a Submodel
/// </summary>
/// <param name="columns">A comma-separated list of field names to structure the payload beeing returned</param>
/// <returns></returns>
/// <response code="200">Success</response>
/// <response code="404">Submodel not found</response>
[HttpGet("submodel/table", Name = "GetSubmodelAsTable")]
[Produces("application/json")]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult GetSubmodelAsTable([FromQuery] string columns)
{
if (string.IsNullOrEmpty(columns))
return ResultHandling.NullResult(nameof(columns));
var result = serviceProvider.RetrieveSubmodel();
if (result != null && result.Entity != null)
{
string[] columnNames = columns.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
JToken customizedSubmodel = result.Entity.CustomizeSubmodel(columnNames);
return new JsonResult(customizedSubmodel);
}
return result.CreateActionResult(CrudOperation.Retrieve);
}
/// <summary>
/// Retrieves all Submodel-Elements from the Submodel
/// </summary>
/// <returns></returns>
/// <response code="200">Returns a list of found Submodel-Elements</response>
/// <response code="404">Submodel not found</response>
[HttpGet("submodel/submodelElements", Name = "GetSubmodelElements")]
[Produces("application/json")]
[ProducesResponseType(typeof(SubmodelElement[]), 200)]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult GetSubmodelElements()
{
var result = serviceProvider.RetrieveSubmodelElements();
return result.CreateActionResult(CrudOperation.Retrieve);
}
/// <summary>
/// Creates or updates a Submodel-Element at the Submodel
/// </summary>
/// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
/// <param name="submodelElement">The Submodel-Element object</param>
/// <returns></returns>
/// <response code="201">Submodel-Element created successfully</response>
/// <response code="400">Bad Request</response>
[HttpPut("submodel/submodelElements/{seIdShortPath}", Name = "PutSubmodelElement")]
[Produces("application/json")]
[Consumes("application/json")]
[ProducesResponseType(typeof(SubmodelElement), 201)]
[ProducesResponseType(typeof(Result), 400)]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult PutSubmodelElement(string seIdShortPath, [FromBody] ISubmodelElement submodelElement)
{
if (string.IsNullOrEmpty(seIdShortPath))
return ResultHandling.NullResult(nameof(seIdShortPath));
if (submodelElement == null)
return ResultHandling.NullResult(nameof(submodelElement));
seIdShortPath = HttpUtility.UrlDecode(seIdShortPath);
var result = serviceProvider.CreateOrUpdateSubmodelElement(seIdShortPath, submodelElement);
return result.CreateActionResult(CrudOperation.Create, "submodel/submodelElements/" + seIdShortPath);
}
/// <summary>
/// Retrieves a specific Submodel-Element from the Submodel
/// </summary>
/// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
/// <returns></returns>
/// <response code="200">Returns the requested Submodel-Element</response>
/// <response code="404">Submodel Element not found</response>
[HttpGet("submodel/submodelElements/{seIdShortPath}", Name = "GetSubmodelElementByIdShort")]
[Produces("application/json")]
[ProducesResponseType(typeof(SubmodelElement), 200)]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult GetSubmodelElementByIdShort(string seIdShortPath)
{
if (string.IsNullOrEmpty(seIdShortPath))
return ResultHandling.NullResult(nameof(seIdShortPath));
seIdShortPath = HttpUtility.UrlDecode(seIdShortPath);
var result = serviceProvider.RetrieveSubmodelElement(seIdShortPath);
return result.CreateActionResult(CrudOperation.Retrieve);
}
/// <summary>
/// Retrieves the value of a specific Submodel-Element from the Submodel
/// </summary>
/// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
/// <returns></returns>
/// <response code="200">Returns the value of a specific Submodel-Element</response>
/// <response code="404">Submodel / Submodel-Element not found</response>
/// <response code="405">Method not allowed</response>
[HttpGet("submodel/submodelElements/{seIdShortPath}/value", Name = "GetSubmodelElementValueByIdShort")]
[Produces("application/json")]
[ProducesResponseType(typeof(object), 200)]
[ProducesResponseType(typeof(Result), 404)]
[ProducesResponseType(typeof(Result), 405)]
public IActionResult GetSubmodelElementValueByIdShort(string seIdShortPath)
{
if (string.IsNullOrEmpty(seIdShortPath))
return ResultHandling.NullResult(nameof(seIdShortPath));
seIdShortPath = HttpUtility.UrlDecode(seIdShortPath);
var result = serviceProvider.RetrieveSubmodelElementValue(seIdShortPath);
if (result.Success && result.Entity != null)
return new OkObjectResult(result.Entity.Value);
else
return result.CreateActionResult(CrudOperation.Retrieve);
}
/// <summary>
/// Updates the Submodel-Element's value
/// </summary>
/// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
/// <param name="value">The new value</param>
/// <returns></returns>
/// <response code="200">Submodel-Element's value changed successfully</response>
/// <response code="404">Submodel-Element not found</response>
/// <response code="405">Method not allowed</response>
[HttpPut("submodel/submodelElements/{seIdShortPath}/value", Name = "PutSubmodelElementValueByIdShort")]
[Produces("application/json")]
[Consumes("application/json")]
[ProducesResponseType(typeof(ElementValue), 200)]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult PutSubmodelElementValueByIdShort(string seIdShortPath, [FromBody] object value)
{
if (string.IsNullOrEmpty(seIdShortPath))
return ResultHandling.NullResult(nameof(seIdShortPath));
if (value == null)
return ResultHandling.NullResult(nameof(value));
seIdShortPath = HttpUtility.UrlDecode(seIdShortPath);
ElementValue elementValue = new ElementValue(value, value.GetType());
var result = serviceProvider.UpdateSubmodelElementValue(seIdShortPath, elementValue);
return result.CreateActionResult(CrudOperation.Update);
}
/// <summary>
/// Deletes a specific Submodel-Element from the Submodel
/// </summary>
/// <param name="seIdShortPath">The Submodel-Element's IdShort-Path</param>
/// <returns></returns>
/// <response code="204">Submodel-Element deleted successfully</response>
/// <response code="404">Submodel-Element not found</response>
[HttpDelete("submodel/submodelElements/{seIdShortPath}", Name = "DeleteSubmodelElementByIdShort")]
[Produces("application/json")]
[ProducesResponseType(typeof(Result), 200)]
public IActionResult DeleteSubmodelElementByIdShort(string seIdShortPath)
{
if (string.IsNullOrEmpty(seIdShortPath))
return ResultHandling.NullResult(nameof(seIdShortPath));
seIdShortPath = HttpUtility.UrlDecode(seIdShortPath);
var result = serviceProvider.DeleteSubmodelElement(seIdShortPath);
return result.CreateActionResult(CrudOperation.Delete);
}
/// <summary>
/// Invokes a specific operation from the Submodel synchronously or asynchronously
/// </summary>
/// <param name="idShortPathToOperation">The IdShort path to the Operation</param>
/// <param name="invocationRequest">The parameterized request object for the invocation</param>
/// <param name="async">Determines whether the execution of the operation is asynchronous (true) or not (false)</param>
/// <returns></returns>
/// <response code="200">Operation invoked successfully</response>
/// <response code="400">Bad Request</response>
/// <response code="404">Method handler not found</response>
[HttpPost("submodel/submodelElements/{idShortPathToOperation}/invoke", Name = "InvokeOperationByIdShortAsync")]
[Produces("application/json")]
[Consumes("application/json")]
[ProducesResponseType(typeof(Result), 400)]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult InvokeOperationByIdShort(string idShortPathToOperation, [FromBody] InvocationRequest invocationRequest, [FromQuery] bool async)
{
if (string.IsNullOrEmpty(idShortPathToOperation))
return ResultHandling.NullResult(nameof(idShortPathToOperation));
if (invocationRequest == null)
return ResultHandling.NullResult(nameof(invocationRequest));
idShortPathToOperation = HttpUtility.UrlDecode(idShortPathToOperation);
if (async)
{
IResult<CallbackResponse> result = serviceProvider.InvokeOperationAsync(idShortPathToOperation, invocationRequest);
return result.CreateActionResult(CrudOperation.Invoke);
}
else
{
IResult<InvocationResponse> result = serviceProvider.InvokeOperation(idShortPathToOperation, invocationRequest);
return result.CreateActionResult(CrudOperation.Invoke);
}
}
/// <summary>
/// Retrieves the result of an asynchronously started operation
/// </summary>
/// <param name="idShortPathToOperation">The IdShort path to the Operation</param>
/// <param name="requestId">The request id</param>
/// <returns></returns>
/// <response code="200">Result found</response>
/// <response code="400">Bad Request</response>
/// <response code="404">Operation / Request not found</response>
[HttpGet("submodel/submodelElements/{idShortPathToOperation}/invocationList/{requestId}", Name = "GetInvocationResultByIdShort")]
[Produces("application/json")]
[ProducesResponseType(typeof(InvocationResponse), 200)]
[ProducesResponseType(typeof(Result), 400)]
[ProducesResponseType(typeof(Result), 404)]
public IActionResult GetInvocationResultByIdShort(string idShortPathToOperation, string requestId)
{
if (string.IsNullOrEmpty(idShortPathToOperation))
return ResultHandling.NullResult(nameof(idShortPathToOperation));
if (string.IsNullOrEmpty(requestId))
return ResultHandling.NullResult(nameof(requestId));
idShortPathToOperation = HttpUtility.UrlDecode(idShortPathToOperation);
IResult<InvocationResponse> result = serviceProvider.GetInvocationResult(idShortPathToOperation, requestId);
return result.CreateActionResult(CrudOperation.Invoke);
}
}
}