Commit a83d4243 authored by Sylvain Renault's avatar Sylvain Renault
Browse files

New file structures (one subfolder for all custom modules).

Implementation as for STF 620.
No implementation for new endpoints for world storage.
No implementation for world analysis.
parent bfcffe4f
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -27,17 +27,21 @@ server/programs/MongoDB/
#generated readme
server/worldstorage/README.md

#!ETSI-ARF/Models/
#!ETSI-ARF/Controllers/
#!ETSI-ARF/Services/

# all generated directories
wwwroot/
Attributes/
Authentication/
Controllers/
Converters/
Filters/
Formatters/
Models/
OpenAPI/
Properties/
wwwroot/
Models
Controllers/

# generated Program.cs
#Program.cs
+25 −14
Original line number Diff line number Diff line
@@ -19,14 +19,13 @@ It includes description and code for a fully functional server with MongoDB inte

## Repo Content

|   |  File / Folder |                                                                                    Description                                                                                    |
|   |  Files / Folders |                                                                                    Description                                                                                    |
|:-:|:--------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| 📂 | openapi         | A git submodule (ForgeETSI ) pointing to the repo containing the API specification file                                                                                                |
| 📂 | server  | The folder where the library code will be generated, the openapi generator is set to not overwrite some files used to generate and initialiue the ASP.Net server system |
| 📂 | server/programs/MongoDB | This folder contains the MongoDB service. The World Storage database should be created or imported in a folder of your choice which path has to be editied in the .bat file |
| 📂 | server/src/Org.OpenAPITools | This is the location where the ASP.Net code will be generated |
| 📂 | server/src/Org.OpenAPITools/ControllersImpl | THis folder contains the code implementating the REST end-paths for the different objects in API |
| 📂 | server/src/Org.OpenAPITools/Services | This folder contains MongoDB database settings and access methods for each API |
| 📂 | arf005         | A submodule pointing to the git containing the API specification file                                                                                                |
| 📂 | server/worldstorage/src/ETSI.ARF.OpenAPI.WorldStorage | This is the location where the ASP.Net code will be generated |
| 📂 | server/worldstorage/src/ETSI.ARF.OpenAPI.WorldStorage/ETSI-ARF | THis folder contains codes implementating the REST end-paths for the different objects in API |

## Requirements

@@ -54,13 +53,17 @@ Open `NuGet Package Manager` and add `MongoDB.Driver`.
### File adaptations
Change version number in all files if a new version is provided.

### Implementation folder (new)
### Custom folder (new)
All custom files are now in the folder 'ETSI-ARF'. Nothing to do adapt manually after generation. But you have to provide the implementation of new endpoints because they are now directly declared as abstract (default).

The folder contains following subfolders:
`Controllers`
`ControllersImpl`
`ModelsExt`
`Services`

Compare files folder in "`ETSI-ARF/Controllers`" with the corresponding files in "`Controllers`" and insert if necessary the new methods.
### Folder 'ControllersImp'

The modules in this folder implement the endpoints. Compare files folder in "`ETSI-ARF/ControllersImpl`" with the corresponding files in "`Controllers`" and implement if necessary the new methods.

Methods should be the same with "`override`" instead of "`abstract`".

@@ -72,9 +75,11 @@ Add
  using MongoDB.Driver;
```

Add a private readonly service class variable like in the already existing files, e.g.:
Add one or more private readonly services class variable like in the already existing files, e.g.:
```
private readonly TrackableService _trackableService;
private readonly WorldAnchorService _worldAnchorService;
private readonly WorldLinkService _worldLinkService;
```

Add a constructor with this service class variable like in the already existing files.
@@ -82,13 +87,14 @@ Add a constructor with this service class variable like in the already existing
public TrackablesApiControllerImpl(TrackableService trackableService)
{
    _trackableService = trackableService;
    // etc.
}
```

Implement endpoint code using the appropriate MogoDB methods of the corresponding classes from the folder `Services` (which you may be have to create).
Implement endpoint code using the appropriate MongoDB methods of the corresponding classes from the folder `Services` (which you may be have to create).

### In the folder `Models`
Add to the classes to be stored in the database (i.e. `Trackable.cs`, `WorldAnchor.cs`, `WorldLink.cs`) inherited from `IModels` (definition of the extra UUID): 
### Folder `ModelsExt`
The modules inside this folder are for extensions of the generated API data structures. Add all the classes to be stored in the database (i.e. `TrackableExt.cs`, `WorldAnchorExt.cs`, `WorldLinkExt.cs`) inherited from `IModels`. (definition of the extra UUID): 
```
  using MongoDB.Bson;
  using MongoDB.Bson.Serialization.Attributes;
@@ -100,12 +106,17 @@ and at the value that is to become the MongoDB ID, add:
  [BsonRepresentation(BsonType.String)]
```

If some members won't be saved in the MongoDB then use this keyword:
```
[BsonIgnore]
```

### Folder `Services`
The folder `Services` should contain one common class with the DatabaseSettings (`DatabaseSettings.cs`) and one with the database-access-methods (create, get, update, remove) for each API. If some are missing create them like the ones you find there. Be aware to add the reference to these in the file `startup.cs` in this case.
The folder `Services` is for handling the data with the MongoDB. It should contain one common class with the DatabaseSettings (`DatabaseSettings.cs`) and one with the database-access-methods (create, get, update, remove) for each API. If some are missing create them like the ones you find there. Be aware to add the reference to these in the file `startup.cs` in this case.

The naming in the DatabaseSettings is the same as defined in `appsettings.json`, which you have to extend when creating new classes in this folder. Change `appsettings.json` in the folder `docker` accordingly. Make sure that the ConnectionString for the database contains the correct IP address as specified in `docker-compose.yml`.

### In the folder `wwwroot`
## Extra folder `wwwroot`
Add in `openapi-original.json` in section `servers` the urls of the servers you want to use with swagger-ui

# MongoDB
+0 −102
Original line number Diff line number Diff line
//
// ARF - Augmented Reality Framework (ETSI ISG ARF)
//
// Copyright 2022 ETSI
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Last change: June 2022
//

/*
 * World Storage API
 *
 * API ensuring interoperability between an authoring tool and a World Storage service
 *
 * The version of the OpenAPI document: 1.0.0
 * 
 * Generated by: https://openapi-generator.tech
 */

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Swashbuckle.AspNetCore.Annotations;
using Swashbuckle.AspNetCore.SwaggerGen;
using Newtonsoft.Json;
using Org.OpenAPITools.Attributes;
using Org.OpenAPITools.Models;
using Microsoft.OpenApi.Models;

namespace Org.OpenAPITools.Controllers
{
  /// <summary>
  /// 
  /// </summary>
  [ApiController]
  public class DefaultApiControllerImpl : DefaultApiController
  {

    /// <summary>
        /// Get the state of the server.
    /// </summary>
    /// <response code="200">OK, world storage server ready.</response>
    [HttpGet]
    [Route("/admin")]
    [ValidateModelState]
    [SwaggerOperation("GetAdmin")]
    [SwaggerResponse(statusCode: 200, type: typeof(string), description: "OK, world storage server ready.")]
    public override IActionResult GetAdmin()
    {
      string version = "OK world storage server ready";
      return new ObjectResult(version);
      //return StatusCode(200, new ObjectResult(version));
    }

    /// <summary>
        /// Test the server availability.
    /// </summary>
        /// <response code="200">Ok, returns a string message.</response>
    [HttpGet]
    [Route("/ping")]
    [ValidateModelState]
    [SwaggerOperation("GetPing")]
        [SwaggerResponse(statusCode: 200, type: typeof(string), description: "Ok, returns a string message.")]
    public override IActionResult GetPing()
    {
      string answer = "OK, world storage alive.";
      return new ObjectResult(answer);
      //      return StatusCode(200, new ObjectResult(answer));
    }

    /// <summary>
    /// Get the version of the ARF API.
    /// </summary>
    /// <response code="200">Current version.</response>
    [HttpGet]
    [Route("/version")]
    [ValidateModelState]
    [SwaggerOperation("GetVersion")]
    [SwaggerResponse(statusCode: 200, type: typeof(string), description: "Current version.")]
    public override IActionResult GetVersion()
    {
      string version = "1.0.0";
      return new ObjectResult(version);
      //return StatusCode(200, new ObjectResult(version));
    }

  }
}
+0 −220
Original line number Diff line number Diff line
//
// ARF - Augmented Reality Framework (ETSI ISG ARF)
//
// Copyright 2022 ETSI
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Last change: June 2022
//

/*
 * World Storage API
 *
 * API ensuring interoperability between an authoring tool and a World Storage service
 *
 * The version of the OpenAPI document: 1.0.0
 * 
 * Generated by: https://openapi-generator.tech
 */

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Swashbuckle.AspNetCore.Annotations;
using Swashbuckle.AspNetCore.SwaggerGen;
using Newtonsoft.Json;
using Org.OpenAPITools.Attributes;
using Org.OpenAPITools.Models;
using Org.OpenAPITools.Services;
using MongoDB.Driver;

namespace Org.OpenAPITools.Controllers
{
  /// <summary>
  /// 
  /// </summary>
  [ApiController]
  public class TrackablesApiControllerImpl : TrackablesApiController
  {

    private readonly TrackableService _trackableService;

    /// <summary>
    /// 
    /// </summary>
    public TrackablesApiControllerImpl(TrackableService trackableService)
    {
      _trackableService = trackableService;
    }


    /// <summary>
    /// Create a Trackable.
    /// </summary>
    /// <remarks>Create a new Trackable from a json object containing all the required informations and add it to the world storage. &lt;br&gt;As a result you will get the ID of the newly created Trackable.</remarks>
    /// <param name="trackable">The Trackable to be added to the world storage.</param>
    /// <response code="200">OK, return the UUID of the Trackable defined by the world storage.</response>
    /// <response code="201">Null response.</response>
    /// <response code="400">Bad request.</response>
    /// <response code="409">Invalid UUID, id must be a Nil value.</response>
    /// <response code="0">Unexpected error.</response>
    [HttpPost]
    [Route("/trackables")]
    [Consumes("application/json")]
    [ValidateModelState]
    [SwaggerOperation("AddTrackable")]
    [SwaggerResponse(statusCode: 200, type: typeof(string), description: "OK, return the UUID of the Trackable defined by the world storage.")]
    [SwaggerResponse(statusCode: 201, type: typeof(string), description: "Null response.")]
    [SwaggerResponse(statusCode: 400, type: typeof(string), description: "Bad request.")]
    [SwaggerResponse(statusCode: 409, type: typeof(string), description: "Invalid UUID, id must be a Nil value.")]
    [SwaggerResponse(statusCode: 0, type: typeof(Error), description: "Unexpected error.")]
    public override IActionResult AddTrackable([FromBody] Trackable trackable)
    {
      if (String.IsNullOrEmpty(trackable.UUID.ToString()))
      {
        trackable.UUID = Guid.NewGuid();
      }
      try
      {
        Trackable mytrackable = _trackableService.Create(trackable);
        return StatusCode(200, mytrackable.UUID.ToString());
      }
      catch (Exception e)
      {
        return StatusCode(400, e.Message);
      }
    }

    /// <summary>
    /// Delete a Trackable.
    /// </summary>
    /// <remarks>Delete a single Trackable stored in the world storage from its ID.</remarks>
    /// <param name="trackableUUID">Trackable UUID to delete.</param>
    /// <response code="200">OK, delete successful.</response>
    /// <response code="400">Invalid UUID supplied.</response>
    /// <response code="404">Not found, could not find UUID in database.</response>
    [HttpDelete]
    [Route("/trackables/{trackableUUID}")]
    [ValidateModelState]
    [SwaggerOperation("DeleteTrackable")]
    [SwaggerResponse(statusCode: 200, type: typeof(string), description: "OK, delete successful.")]
    [SwaggerResponse(statusCode: 400, type: typeof(string), description: "Invalid UUID supplied.")]
    [SwaggerResponse(statusCode: 404, type: typeof(string), description: "Not found, could not find UUID in database.")]
    public override IActionResult DeleteTrackable([FromRoute(Name = "trackableUUID")][Required] Guid trackableUUID)
    {
      DeleteResult answer = _trackableService.Remove(trackableUUID);
      // check, if used in WorldLink
      string result = "ok";
      string worldlinkinfo = "";
      List<WorldLink> worldlinklistfrom = _trackableService.GetWorldLinkUUIDFrom(trackableUUID);
      foreach (WorldLink worldlink in worldlinklistfrom)
      {
        worldlinkinfo += worldlink.UUID.ToString() + "; ";
        worldlink.UUIDFrom = Guid.Empty;
        worldlink.TypeFrom = ObjectType.NotIdentifiedEnum;
        _trackableService.UpdateWorldLink(worldlink.UUID, worldlink);
      }
      List<WorldLink> worldlinklistto = _trackableService.GetWorldLinkUUIDTo(trackableUUID);
      foreach (WorldLink worldlink in worldlinklistto)
      {
        worldlinkinfo += worldlink.UUID.ToString() + "; ";
        worldlink.UUIDTo = Guid.Empty;
        worldlink.TypeTo = ObjectType.NotIdentifiedEnum;
        _trackableService.UpdateWorldLink(worldlink.UUID, worldlink);
      }
      if (worldlinkinfo.Length > 1)
      {
        result += ", removed object was referenced in " + worldlinkinfo + " and removed there as well";
      }
      return (answer.IsAcknowledged && answer.DeletedCount > 0) ? new ObjectResult(result) : StatusCode(404, "Not found, could not find UUID in database.");
    }

    /// <summary>
    /// Find a Trackable by its UUID.
    /// </summary>
    /// <remarks>Get a single Trackable stored in the world storage from its ID.</remarks>
    /// <param name="trackableUUID">UUID of the Trackable to retrieve.</param>
    /// <response code="200">Successful operation.</response>
    /// <response code="400">Invalid UUID supplied.</response>
    /// <response code="404">Not found, could not find UUID in database.</response>
    [HttpGet]
    [Route("/trackables/{trackableUUID}")]
    [ValidateModelState]
    [SwaggerOperation("GetTrackableById")]
    [SwaggerResponse(statusCode: 200, type: typeof(Trackable), description: "Successful operation.")]
    [SwaggerResponse(statusCode: 400, type: typeof(string), description: "Invalid UUID supplied.")]
    [SwaggerResponse(statusCode: 404, type: typeof(string), description: "Not found, could not find UUID in database.")]
    public override IActionResult GetTrackableById([FromRoute(Name = "trackableUUID")][Required] Guid trackableUUID)
    {
      Trackable trackable = _trackableService.Get(trackableUUID);
      return (null != trackable) ? new ObjectResult(trackable) : StatusCode(404, "Not found, could not find UUID in database.");
    }

    /// <summary>
    /// Return all the Trackables.
    /// </summary>
    /// <remarks>Get all the Trackables currently being stored in the world storage.</remarks>
    /// <response code="200">OK, return all the Trackables defined by the world storage.</response>
    /// <response code="201">Null response.</response>
    /// <response code="0">Unexpected error.</response>
    [HttpGet]
    [Route("/trackables")]
    [ValidateModelState]
    [SwaggerOperation("GetTrackables")]
    [SwaggerResponse(statusCode: 200, type: typeof(List<Trackable>), description: "OK, return all the Trackables defined by the world storage.")]
    [SwaggerResponse(statusCode: 201, type: typeof(string), description: "Null response.")]
    [SwaggerResponse(statusCode: 0, type: typeof(Error), description: "Unexpected error.")]
    public override IActionResult GetTrackables()
    {
      List<Trackable> trackablelist = _trackableService.Get();
      return new ObjectResult(trackablelist);
    }



    /// <summary>
    /// Modify a Trackable.
    /// </summary>
    /// <remarks>Modify an existing Trackable given a json object containing all the required informations. &lt;br&gt; **Please note that ID of the object is required in the JSON**</remarks>
    /// <param name="trackable">The Trackable to be modified in the world storage.</param>
    /// <response code="200">OK, return the UUID of the modified Trackable.</response>
    /// <response code="400">Bad request.</response>
    /// <response code="404">Not found, could not find UUID in database.</response>
    /// <response code="0">Unexpected error.</response>
    [HttpPut]
    [Route("/trackables")]
    [Consumes("application/json")]
    [ValidateModelState]
    [SwaggerOperation("ModifyTrackable")]
    [SwaggerResponse(statusCode: 200, type: typeof(string), description: "OK, return the UUID of the modified Trackable.")]
    [SwaggerResponse(statusCode: 400, type: typeof(string), description: "Bad request.")]
    [SwaggerResponse(statusCode: 404, type: typeof(string), description: "Not found, could not find UUID in database.")]
    [SwaggerResponse(statusCode: 0, type: typeof(Error), description: "Unexpected error.")]
    public override IActionResult ModifyTrackable([FromBody] Trackable trackable)
    {
      ReplaceOneResult result = _trackableService.Update(trackable.UUID, trackable);
      if (result.MatchedCount == 0)
      {
        return StatusCode(404, "Not found, could not find UUID in database.");
      }
      else
      {
        return StatusCode(200, trackable.UUID.ToString());
      }
    }
  }
}
+0 −222

File deleted.

Preview size limit exceeded, changes collapsed.

Loading