Refactoring code base to new structure, removing circular dependencies, creating response types

This commit is contained in:
Sonja Happ 2019-05-23 16:50:05 +02:00
parent b89a68296f
commit 144c97ce49
37 changed files with 1261 additions and 1353 deletions

View file

@ -1,26 +0,0 @@
package common
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
)
func ProvideErrorResponse(c *gin.Context, err error) bool {
if err != nil {
if err == gorm.ErrRecordNotFound {
errormsg := "Record not Found in DB: " + err.Error()
c.JSON(http.StatusNotFound, gin.H{
"error": errormsg,
})
} else {
errormsg := "Error on DB Query or transaction: " + err.Error()
c.JSON(http.StatusInternalServerError, gin.H{
"error": errormsg,
})
}
return true // Error
}
return false // No error
}

View file

@ -2,9 +2,6 @@ package common
import (
"time"
// "github.com/jinzhu/gorm"
"github.com/jinzhu/gorm/dialects/postgres"
)
// User data model
@ -32,8 +29,8 @@ type Simulation struct {
Name string `gorm:"not null"`
// Running state of simulation
Running bool `gorm:"default:false"`
// Start parameters of simulation
StartParameters postgres.Jsonb
// Start parameters of simulation as JSON string
StartParameters string
// Users that have access to the simulation
Users []User `gorm:"not null;many2many:user_simulations"`
// Models that belong to the simulation
@ -52,8 +49,8 @@ type Model struct {
OutputLength int `gorm:"default:1"`
// Number of input signals
InputLength int `gorm:"default:1"`
// Start parameters of model
StartParameters postgres.Jsonb
// Start parameters of model as JSON string
StartParameters string
// ID of simulation to which model belongs
SimulationID uint
// Simulator associated with model
@ -96,10 +93,10 @@ type Simulator struct {
State string `gorm:"default:''"`
// Time of last state update
StateUpdateAt time.Time
// Properties of simulator
Properties postgres.Jsonb
// Raw properties of simulator
RawProperties postgres.Jsonb
// Properties of simulator as JSON string
Properties string
// Raw properties of simulator as JSON string
RawProperties string
}
// Visualization data model
@ -141,8 +138,8 @@ type Widget struct {
Z int `gorm:"not null"`
// Locked state of widget
IsLocked bool `gorm:"default:false"`
// Custom properties of widget
CustomProperties postgres.Jsonb
// Custom properties of widget as JSON string
CustomProperties string
// ID of visualization to which widget belongs
VisualizationID uint `gorm:"not null"`
// Files that belong to widget (for example images)

95
common/responses.go Normal file
View file

@ -0,0 +1,95 @@
package common
import (
"time"
)
type UserResponse struct {
Username string `json:"Username"`
Role string `json:"Role"`
Mail string `json:"Mail"`
}
type SimulationResponse struct {
Name string `json:"Name"`
ID uint `json:"SimulationID"`
Running bool `json:"Running"`
StartParams string `json:"Starting Parameters"`
}
type ModelResponse struct {
Name string `json:"Name"`
OutputLength int `json:"OutputLength"`
InputLength int `json:"InputLength"`
SimulationID uint `json:"SimulationID"`
SimulatorID uint `json:"SimulatorID"`
StartParams string `json:"StartParams"`
InputMapping []Signal `json:"InputMapping"`
OutputMapping []Signal `json:"OutputMapping"`
}
type SimulatorResponse struct {
UUID string `json:"UUID"`
Host string `json:"Host"`
ModelType string `json:"ModelType"`
Uptime int `json:"Uptime"`
State string `json:"State"`
StateUpdateAt time.Time `json:"StateUpdateAt"`
Properties string `json:"Properties"`
RawProperties string `json:"RawProperties"`
}
type VisualizationResponse struct {
Name string `json:"Name"`
Grid int `json:"Grid"`
SimulationID uint `json:"SimulationID"`
}
type WidgetResponse struct {
Name string `json:"Name"`
Type string `json:"Type"`
Width uint `json:"Width"`
Height uint `json:"Height"`
MinWidth uint `json:"MinWidth"`
MinHeight uint `json:"MinHeight"`
X int `json:"X"`
Y int `json:"Y"`
Z int `json:"Z"`
VisualizationID uint `json:"VisualizationID"`
IsLocked bool `json:"IsLocked"`
CustomProperties string `json:"CustomProperties"`
}
type FileResponse struct {
Name string `json:"Name"`
ID uint `json:"FileID"`
Path string `json:"Path"`
Type string `json:"Type"`
Size uint `json:"Size"`
H uint `json:"ImageHeight"`
W uint `json:"ImageWidth"`
Date time.Time `json:"Date"`
}
// Response messages
type ResponseMsg struct{
Message string `json:"message"`
}
type ResponseMsgUsers struct {
Users []UserResponse `json:"users"`
}
type ResponseMsgUser struct {
User UserResponse `json:"user"`
}
type ResponseMsgSimulations struct {
Simulations []SimulationResponse `json:"simulations"`
}
type ResponseMsgSimulation struct {
Simulation SimulationResponse `json:"simulation"`
}

245
common/serializers.go Normal file
View file

@ -0,0 +1,245 @@
package common
import (
"github.com/gin-gonic/gin"
)
// User/s Serializers
type UsersSerializer struct {
Ctx *gin.Context
Users []User
}
func (self *UsersSerializer) Response() []UserResponse {
response := []UserResponse{}
for _, user := range self.Users {
serializer := UserSerializer{self.Ctx, user}
response = append(response, serializer.Response())
}
return response
}
type UserSerializer struct {
Ctx *gin.Context
User
}
func (self *UserSerializer) Response() UserResponse {
response := UserResponse{
Username: self.Username,
Role: self.Role,
Mail: self.Mail,
}
return response
}
// Simulation/s Serializers
type SimulationsSerializer struct {
Ctx *gin.Context
Simulations []Simulation
}
func (self *SimulationsSerializer) Response() []SimulationResponse {
response := []SimulationResponse{}
for _, simulation := range self.Simulations {
serializer := SimulationSerializer{self.Ctx, simulation}
response = append(response, serializer.Response())
}
return response
}
type SimulationSerializer struct {
Ctx *gin.Context
Simulation
}
func (self *SimulationSerializer) Response() SimulationResponse {
response := SimulationResponse{
Name: self.Name,
ID: self.ID,
Running: self.Running,
StartParams: self.StartParameters,
}
return response
}
// Model/s Serializers
type ModelsSerializer struct {
Ctx *gin.Context
Models []Model
}
func (self *ModelsSerializer) Response() []ModelResponse {
response := []ModelResponse{}
for _, model := range self.Models {
serializer := ModelSerializer{self.Ctx, model}
response = append(response, serializer.Response())
}
return response
}
type ModelSerializer struct {
Ctx *gin.Context
Model
}
func (self *ModelSerializer) Response() ModelResponse {
response := ModelResponse{
Name: self.Name,
OutputLength: self.OutputLength,
InputLength: self.InputLength,
SimulationID: self.SimulationID,
SimulatorID: self.SimulatorID,
StartParams: self.StartParameters,
//InputMapping
//OutputMapping
}
return response
}
// Simulator/s Serializers
type SimulatorsSerializer struct {
Ctx *gin.Context
Simulators []Simulator
}
func (self *SimulatorsSerializer) Response() []SimulatorResponse {
response := []SimulatorResponse{}
for _, simulator := range self.Simulators {
serializer := SimulatorSerializer{self.Ctx, simulator}
response = append(response, serializer.Response())
}
return response
}
type SimulatorSerializer struct {
Ctx *gin.Context
Simulator
}
func (self *SimulatorSerializer) Response() SimulatorResponse {
response := SimulatorResponse{
UUID: self.UUID,
Host: self.Host,
ModelType: self.Modeltype,
Uptime: self.Uptime,
State: self.State,
StateUpdateAt: self.StateUpdateAt,
}
return response
}
// Visualization/s Serializers
type VisualizationsSerializer struct {
Ctx *gin.Context
Visualizations []Visualization
}
func (self *VisualizationsSerializer) Response() []VisualizationResponse {
response := []VisualizationResponse{}
for _, visualization := range self.Visualizations {
serializer := VisualizationSerializer{self.Ctx, visualization}
response = append(response, serializer.Response())
}
return response
}
type VisualizationSerializer struct {
Ctx *gin.Context
Visualization
}
func (self *VisualizationSerializer) Response() VisualizationResponse {
response := VisualizationResponse{
Name: self.Name,
Grid: self.Grid,
SimulationID: self.SimulationID,
}
return response
}
// Widget/s Serializers
type WidgetsSerializer struct {
Ctx *gin.Context
Widgets []Widget
}
func (self *WidgetsSerializer) Response() []WidgetResponse {
response := []WidgetResponse{}
for _, widget := range self.Widgets {
serializer := WidgetSerializer{self.Ctx, widget}
response = append(response, serializer.Response())
}
return response
}
type WidgetSerializer struct {
Ctx *gin.Context
Widget
}
func (self *WidgetSerializer) Response() WidgetResponse {
response := WidgetResponse{
Name: self.Name,
Type: self.Type,
Width: self.Width,
Height: self.Height,
MinWidth: self.MinWidth,
MinHeight: self.MinHeight,
X: self.X,
Y: self.Y,
Z: self.Z,
VisualizationID: self.VisualizationID,
IsLocked: self.IsLocked,
//CustomProperties
}
return response
}
// File/s Serializers
type FilesSerializerNoAssoc struct {
Ctx *gin.Context
Files []File
}
func (self *FilesSerializerNoAssoc) Response() []FileResponse {
response := []FileResponse{}
for _, files := range self.Files {
serializer := FileSerializerNoAssoc{self.Ctx, files}
response = append(response, serializer.Response())
}
return response
}
type FileSerializerNoAssoc struct {
Ctx *gin.Context
File
}
func (self *FileSerializerNoAssoc) Response() FileResponse {
response := FileResponse{
Name: self.Name,
ID: self.ID,
Path: self.Path,
Type: self.Type,
Size: self.Size,
H: self.ImageHeight,
W: self.ImageWidth,
// Date
}
return response
}

93
common/utilities.go Normal file
View file

@ -0,0 +1,93 @@
package common
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
)
func ProvideErrorResponse(c *gin.Context, err error) bool {
if err != nil {
if err == gorm.ErrRecordNotFound {
errormsg := "Record not Found in DB: " + err.Error()
c.JSON(http.StatusNotFound, gin.H{
"error": errormsg,
})
} else {
errormsg := "Error on DB Query or transaction: " + err.Error()
c.JSON(http.StatusInternalServerError, gin.H{
"error": errormsg,
})
}
return true // Error
}
return false // No error
}
func GetSimulationID(c *gin.Context) (int, error) {
simID, err := strconv.Atoi(c.Param("simulationID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulation ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return -1, err
} else {
return simID, err
}
}
func GetModelID(c *gin.Context) (int, error) {
modelID, err := strconv.Atoi(c.Param("modelID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of model ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return -1, err
} else {
return modelID, err
}
}
func GetVisualizationID(c *gin.Context) (int, error) {
simID, err := strconv.Atoi(c.Param("visualizationID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of visualization ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return -1, err
} else {
return simID, err
}
}
func GetWidgetID(c *gin.Context) (int, error) {
widgetID, err := strconv.Atoi(c.Param("widgetID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of widget ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return -1, err
} else {
return widgetID, err
}
}

View file

@ -1,145 +0,0 @@
package endpoints
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
type responseMsg struct{
Message string `json:"message"`
}
var msgOK = responseMsg{
Message: "OK.",
}
type user struct{
Username string `json:"Username"`
Role string `json:"Role"`
Mail string `json:"Mail"`
}
type responseUsers struct {
Users []user `json:"users"`
}
var users = []user{
{
Username: "User_A",
Role: "user",
Mail: "",
},
{
Username: "User_B",
Role: "user",
Mail: "",
},
}
var msgUsers = responseUsers{
Users: users,
}
type simulation struct{
Name string `json:"Name"`
SimulationID uint `json:"SimulationID"`
Running bool `json:"Running"`
}
type responseSimulations struct {
Simulations []simulation `json:"simulations"`
}
type responseSimulation struct {
Simulation simulation `json:"simulation"`
}
var simulationA = simulation{
Name: "Simulation_A",
SimulationID: 1,
Running: false,
}
var simulationB = simulation{
Name: "Simulation_B",
SimulationID: 2,
Running: false,
}
var simulations = []simulation{
simulationA,
simulationB,
}
var msgSimulations = responseSimulations{
Simulations: simulations,
}
// Test /simulation endpoints
func TestSimulationEndpoints(t *testing.T) {
db := common.DummyInitDB()
defer db.Close()
common.DummyPopulateDB(db)
router := gin.Default()
api := router.Group("/api")
SimulationsRegister(api.Group("/simulations"))
msgOKjson, err := json.Marshal(msgOK)
if err !=nil {
panic(err)
}
msgUsersjson, err := json.Marshal(msgUsers)
if err !=nil {
panic(err)
}
// msgSimulationsjson, err := json.Marshal(msgSimulations)
// if err !=nil {
// panic(err)
// }
// test GET simulations/
var expected_response = "{\"simulations\":[{\"Name\":\"Simulation_A\",\"SimulationID\":1,\"Running\":false,\"Starting Parameters\":null},{\"Name\":\"Simulation_B\",\"SimulationID\":2,\"Running\":false,\"Starting Parameters\":null}]}"
testEndpoint(t, router, "/api/simulations/", "GET", "", 200, expected_response)
// test GET simulations/:SimulationID
expected_response = "{\"simulation\":{\"Name\":\"Simulation_A\",\"SimulationID\":1,\"Running\":false,\"Starting Parameters\":null}}"
testEndpoint(t, router, "/api/simulations/1", "GET", "", 200, expected_response)
// test GET simulations/:SimulationID/users
testEndpoint(t, router, "/api/simulations/1/users", "GET", "", 200, string(msgUsersjson))
// test DELETE simulations/:SimulationID/user/:username
testEndpoint(t, router, "/api/simulations/1/user/User_A", "DELETE", "", 200, string(msgOKjson))
// test PUT simulations/:SimulationID/user/:username
testEndpoint(t, router, "/api/simulations/1/user/User_A", "PUT", "", 200, string(msgOKjson))
// TODO add more tests
}
func testEndpoint(t *testing.T, router *gin.Engine, url string, method string, body string, expected_code int, expected_response string ) {
w := httptest.NewRecorder()
req, _ := http.NewRequest(method, url, nil)
router.ServeHTTP(w, req)
assert.Equal(t, expected_code, w.Code)
fmt.Println(w.Body.String())
assert.Equal(t, expected_response, w.Body.String())
}

View file

@ -1,184 +0,0 @@
package endpoints
import (
"fmt"
"net/http"
"strconv"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/serializers"
"github.com/gin-gonic/gin"
)
// modelReadAllEp godoc
// @Summary Get all models of simulation
// @ID GetAllModelsOfSimulation
// @Produce json
// @Tags model
// @Success 200 {array} common.Model "Array of models to which belong to simulation"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Router /simulations/{simulationID}/models [get]
func modelReadAllEp(c *gin.Context) {
simID, err := GetSimulationID(c)
if err != nil {
return
}
allModels, _, err := queries.FindAllModels(simID)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := serializers.ModelsSerializer{c, allModels}
c.JSON(http.StatusOK, gin.H{
"models": serializer.Response(),
})
}
// modelRegistrationEp godoc
// @Summary Add a model to a simulation
// @ID AddModelToSimulation
// @Tags model
// @Param inputModel body common.Model true "Model to be added"
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Router /simulations/{simulationID}/models [post]
func modelRegistrationEp(c *gin.Context) {
simID, err := GetSimulationID(c)
if err != nil {
return
}
var m common.Model
err = c.BindJSON(&m)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
err = queries.AddModel(simID, &m)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
func modelCloneEp(c *gin.Context) {
modelID, err := GetModelID(c)
if err != nil {
return
}
targetSimID, err := strconv.Atoi(c.PostForm("TargetSim"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of target sim ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
err = queries.CloneModel(targetSimID, modelID)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "Not implemented.",
})
}
}
func modelUpdateEp(c *gin.Context) {
modelID, err := GetModelID(c)
if err != nil {
return
}
var m common.Model
err = c.BindJSON(&m)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
err = queries.UpdateModel(modelID, &m)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
func modelReadEp(c *gin.Context) {
modelID, err := GetModelID(c)
if err != nil {
return
}
m, err := queries.FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := serializers.ModelSerializer{c, m}
c.JSON(http.StatusOK, gin.H{
"model": serializer.Response(),
})
}
func modelDeleteEp(c *gin.Context) {
simID, err := GetSimulationID(c)
if err != nil {
return
}
modelID, err := GetModelID(c)
if err != nil {
return
}
err = queries.DeleteModel(simID, modelID)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
func GetModelID(c *gin.Context) (int, error) {
modelID, err := strconv.Atoi(c.Param("ModelID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of model ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return -1, err
} else {
return modelID, err
}
}

View file

@ -1,88 +0,0 @@
package endpoints
import (
"github.com/gin-gonic/gin"
)
func SimulationsRegister(r *gin.RouterGroup) {
r.GET("/", getSimulationsEp)
//r.POST("/", simulationRegistrationEp)
//r.POST("/:SimulationID", simulationCloneEp)
//r.PUT("/:SimulationID", simulationUpdateEp)
r.GET("/:SimulationID", getSimulationEp)
//r.DELETE("/:SimulationID", simulationDeleteEp)
// Users
r.GET("/:SimulationID/users", userReadAllSimEp)
r.PUT("/:SimulationID/user/:username", userUpdateSimEp)
r.DELETE("/:SimulationID/user/:username", userDeleteSimEp)
// Models
r.GET("/:SimulationID/models/", modelReadAllEp)
r.POST("/:SimulationID/models/", modelRegistrationEp)
//r.POST("/:SimulationID/models/:ModelID", modelCloneEp)
r.PUT("/:SimulationID/models/:ModelID", modelUpdateEp)
r.GET("/:SimulationID/models/:ModelID", modelReadEp)
//r.DELETE("/:SimulationID/models/:ModelID", modelDeleteEp)
// Simulators
r.PUT("/:SimulationID/models/:ModelID/simulator", simulatorUpdateModelEp)
r.GET("/:SimulationID/models/:ModelID/simulator", simulatorReadModelEp)
// Input and Output Signals
r.POST("/:SimulationID/models/:ModelID/signals/:direction", signalRegistrationEp)
r.GET("/:SimulationID/models/:ModelID/signals/:direction", signalReadAllEp)
// Visualizations
r.GET("/:SimulationID/visualizations", visualizationReadAllEp)
r.POST("/:SimulationID/visualization", visualizationRegistrationEp)
//r.POST("/:SimulationID/visualization/:visualizationID", visualizationCloneEp)
r.PUT("/:SimulationID/visualization/:visualizationID", visualizationUpdateEp)
r.GET("/:SimulationID/visualization/:visualizationID", visualizationReadEp)
//r.DELETE("/:SimulationID/visualization/:visualizationID", visualizationDeleteEp)
// Widgets
r.GET("/:SimulationID/visualization/:visualizationID/widgets", widgetReadAllEp)
r.POST("/:SimulationID/visualization/:visualizationID/widget", widgetRegistrationEp)
//r.POST("/:SimulationID/visualization/:visualizationID/widget:widgetID", widgetCloneEp)
r.PUT("/:SimulationID/visualization/:visualizationID/widget/:widgetID", widgetUpdateEp)
r.GET("/:SimulationID/visualization/:visualizationID/widget/:widgetID", widgetReadEp)
//r.DELETE("/:SimulationID/visualization/:visualizationID/widget/:widgetID", widgetDeleteEp)
r.GET("/:SimulationID/models/:ModelID/files", fileMReadAllEp)
r.POST ("/:SimulationID/models/:ModelID/file", fileMRegistrationEp) // NEW in API
//r.POST ("/:SimulationID/models/:ModelID/file", fileMCloneEp) // NEW in API
r.GET("/:SimulationID/models/:ModelID/file", fileMReadEp) // NEW in API
r.PUT("/:SimulationID/models/:ModelID/file", fileMUpdateEp) // NEW in API
r.DELETE("/:SimulationID/models/:ModelID/file", fileMDeleteEp) // NEW in API
// Files of Widgets
r.GET("/:SimulationID/visualizations/:VisID/widgets/:WidgetID/files", fileWReadAllEp) // NEW in API
r.POST ("/:SimulationID/visualizations/:VisID/widgets/:WidgetID/file", fileWRegistrationEp) // NEW in API
//r.POST ("/:SimulationID/visualizations/:VisID/widgets/:WidgetID/file", fileWCloneEp) // NEW in API
r.GET("/:SimulationID/visualizations/:VisID/widgets/:WidgetID/file", fileWReadEp) // NEW in API
r.PUT("/:SimulationID/visualizations/:VisID/widgets/:WidgetID/file", fileWUpdateEp) // NEW in API
r.DELETE("/:SimulationID/visualizations/:VisID/widgets/:WidgetID/file", fileWDeleteEp) // NEW in API
}
func UsersRegister(r *gin.RouterGroup) {
r.GET("/", userReadAllEp)
r.POST("/", userRegistrationEp)
r.PUT("/:UserID", userUpdateEp)
r.GET("/:UserID", userReadEp)
r.GET("/:UserID/simulations", userReadSimEp)
r.DELETE("/:UserID", userDeleteEp)
//r.GET("/me", userSelfEp) // TODO redirect to users/:UserID
}
func SimulatorsRegister(r *gin.RouterGroup) {
r.GET("/", simulatorReadAllEp)
r.POST("/", simulatorRegistrationEp)
r.PUT("/:SimulatorID", simulatorUpdateEp)
r.GET("/:SimulatorID", simulatorReadEp)
r.DELETE("/:SimulatorID", simulatorDeleteEp)
r.POST("/:SimulatorID", simulatorSendActionEp)
}

View file

@ -1,84 +0,0 @@
package endpoints
import (
"net/http"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
)
func signalRegistrationEp(c *gin.Context) {
modelID, err := GetModelID(c)
if err != nil {
return
}
model, err := queries.FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
direction := c.Param("direction")
if !(direction == "out") && !(direction == "in") {
errormsg := "Bad request. Direction has to be in or out"
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
var sigs []common.Signal
err = c.BindJSON(&sigs)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
// Add signals to model and remove all existing Signals of the requested direction (if any)
err = queries.ReplaceSignals(&model, sigs, direction)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
func signalReadAllEp(c *gin.Context) {
modelID, err := GetModelID(c)
if err != nil {
return
}
model, err := queries.FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
direction := c.Param("direction")
if !(direction == "out") && !(direction == "in") {
errormsg := "Bad request. Direction has to be in or out"
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
var signals []common.Signal
if direction == "in" {
signals = model.InputMapping
} else {
signals = model.OutputMapping
}
c.JSON(http.StatusOK, gin.H{
"signals": signals,
})
}

View file

@ -1,112 +0,0 @@
package endpoints
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/serializers"
)
func simulatorReadAllEp(c *gin.Context) {
allSimulators, _, _ := queries.FindAllSimulators()
serializer := serializers.SimulatorsSerializer{c, allSimulators}
c.JSON(http.StatusOK, gin.H{
"simulators": serializer.Response(),
})
}
func simulatorRegistrationEp(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func simulatorUpdateEp(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func simulatorUpdateModelEp(c *gin.Context) {
// simulator ID as parameter of Query, e.g. simulations/:SimulationID/models/:ModelID/simulator?simulatorID=42
simulatorID, err := strconv.Atoi(c.Query("simulatorID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect simulator ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
modelID, err := GetModelID(c)
if err != nil {
return
}
simulator, err := queries.FindSimulator(simulatorID)
if common.ProvideErrorResponse(c, err) {
return
}
model, err := queries.FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
err = queries.UpdateSimulatorOfModel(&model, &simulator)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK",
})
}
}
func simulatorReadEp(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func simulatorReadModelEp(c *gin.Context) {
modelID, err := GetModelID(c)
if err != nil {
return
}
model, err := queries.FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
simulator, err := queries.FindSimulator(int(model.SimulatorID))
if common.ProvideErrorResponse(c, err) {
return
}
serializer := serializers.SimulatorSerializer{c, simulator}
c.JSON(http.StatusOK, gin.H{
"simulator": serializer.Response(),
})
}
func simulatorDeleteEp(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func simulatorSendActionEp(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}

1
go.sum
View file

@ -138,6 +138,7 @@ github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJ
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 h1:BasDe+IErOQKrMVXab7UayvSlIpiyGwRvuX3EKYY7UA=
github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=
github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780 h1:vG/gY/PxA3v3l04qxe3tDjXyu3bozii8ulSlIPOYKhI=
github.com/ugorji/go/codec v0.0.0-20190320090025-2dc34c0b8780/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=

View file

@ -1,99 +0,0 @@
package queries
import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
func FindAllModels(simID int) ([]common.Model, int, error) {
db := common.GetDB()
var models []common.Model
sim, err := FindSimulation(simID)
if err != nil {
return models, 0, err
}
err = db.Model(sim).Related(&models, "Models").Error
return models, len(models), err
}
func FindModel(modelID int) (common.Model, error){
db := common.GetDB()
var m common.Model
err := db.First(&m, modelID).Error
return m, err
}
func AddModel(simID int, model *common.Model) error {
db := common.GetDB()
sim, err := FindSimulation(simID)
if err != nil {
return err
}
err = db.Model(&sim).Association("Models").Append(model).Error
return err
}
func CloneModel(targetSim int, modelID int) error {
// TODO TO BE IMPLEMENTED
// Check if target sim exists
// Check if model exists
// Get all Signals of Model
// Get Simulator of Model
// Get Files of model
// Add new model object to DB and associate with target sim
// Add new signal objects to DB and associate with new model object (careful with directions)
// Associate Simulator with new Model object
var err error
return err
}
func UpdateModel(modelID int , modelUpdate *common.Model) error {
db := common.GetDB()
m, err := FindModel(modelID)
if err != nil {
return err
}
// only Name and Start Params can be updated directly by the user
err = db.Model(&m).Updates(map[string]interface{}{"Name": modelUpdate.Name, "StartParameters": modelUpdate.StartParameters}).Error
return err
}
func DeleteModel(simID int , modelID int ) error {
db := common.GetDB()
sim, err := FindSimulation(simID)
if err != nil {
return err
}
m, err := FindModel(modelID)
if err != nil {
return err
}
//remove relationship between simulation and model
err = db.Model(&sim).Association("Models").Delete(m).Error
if err != nil {
return err
}
// TODO remove File Associations and files on disk
// TODO remove Signal Associations and Signals in DB
// TODO how to treat simulator association?
//remove model itself from DB
//TODO: do we want this??
err = db.Delete(&m).Error
return err
}
func UpdateSimulatorOfModel(model *common.Model, simulator *common.Simulator) error {
db := common.GetDB()
err := db.Model(model).Association("Simulator").Replace(simulator).Error
return err
}

View file

@ -1,20 +0,0 @@
package queries
import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
func ReplaceSignals(model *common.Model, signals []common.Signal, direction string) error {
db := common.GetDB()
var err error
if direction == "in" {
err = db.Model(model).Select("InputMapping").Update("InputMapping", signals).Error
} else {
err = db.Model(model).Select("OutputMapping").Update("OutputMapping", signals).Error
}
return err
}

144
routes/endpoints_test.go Normal file
View file

@ -0,0 +1,144 @@
package routes
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/file"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/model"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulator"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/visualization"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/widget"
)
var msgOK = common.ResponseMsg{
Message: "OK.",
}
var user_A = common.UserResponse{
Username: "User_A",
Role: "user",
Mail: "",
}
var user_B = common.UserResponse{
Username: "User_B",
Role: "user",
Mail: "",
}
var myUsers = []common.UserResponse{
user_B,
user_A,
}
var msgUsers = common.ResponseMsgUsers{
Users: myUsers,
}
var simulationA = common.SimulationResponse{
Name: "Simulation_A",
ID: 1,
Running: false,
}
var simulationB = common.SimulationResponse{
Name: "Simulation_B",
ID: 2,
Running: false,
}
var mySimulations = []common.SimulationResponse{
simulationA,
simulationB,
}
var msgSimulations = common.ResponseMsgSimulations{
Simulations: mySimulations,
}
var msgSimulation = common.ResponseMsgSimulation{
Simulation: simulationA,
}
// Test /simulation endpoints
func TestSimulationEndpoints(t *testing.T) {
db := common.DummyInitDB()
defer db.Close()
common.DummyPopulateDB(db)
router := gin.Default()
api := router.Group("/api")
simulation.RegisterSimulationEndpoints(api.Group("/simulations"))
file.RegisterFileEndpoints(api.Group("/simulations"))
model.RegisterModelEndpoints(api.Group("/simulations"))
visualization.RegisterVisualizationEndpoints(api.Group("/simulations"))
widget.RegisterWidgetEndpoints(api.Group("/simulations"))
user.RegisterUserEndpointsForSimulation(api.Group("/simulations")) // TODO ugly structure
user.RegisterUserEndpoints(api.Group("/users"))
simulator.RegisterSimulatorEndpoints(api.Group("/simulators"))
msgOKjson, err := json.Marshal(msgOK)
if err !=nil {
panic(err)
}
msgUsersjson, err := json.Marshal(msgUsers)
if err !=nil {
panic(err)
}
msgSimulationsjson, err := json.Marshal(msgSimulations)
if err !=nil {
panic(err)
}
msgSimulationjson, err := json.Marshal(msgSimulation)
if err !=nil {
panic(err)
}
// test GET simulations/
testEndpoint(t, router, "/api/simulations/", "GET", "", 200, string(msgSimulationsjson))
// test GET simulations/:SimulationID
testEndpoint(t, router, "/api/simulations/1", "GET", "", 200, string(msgSimulationjson))
// test GET simulations/:SimulationID/users
testEndpoint(t, router, "/api/simulations/1/users", "GET", "", 200, string(msgUsersjson))
// test DELETE simulations/:SimulationID/user/:username
testEndpoint(t, router, "/api/simulations/1/user/User_A", "DELETE", "", 200, string(msgOKjson))
// test PUT simulations/:SimulationID/user/:username
testEndpoint(t, router, "/api/simulations/1/user/User_A", "PUT", "", 200, string(msgOKjson))
// TODO add more tests
}
func testEndpoint(t *testing.T, router *gin.Engine, url string, method string, body string, expected_code int, expected_response string ) {
w := httptest.NewRecorder()
req, _ := http.NewRequest(method, url, nil)
router.ServeHTTP(w, req)
assert.Equal(t, expected_code, w.Code)
fmt.Println(w.Body.String())
assert.Equal(t, expected_response, w.Body.String())
}

View file

@ -1,22 +1,34 @@
package endpoints
package file
import (
"fmt"
"strconv"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/serializers"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
// fileMReadAllEp godoc
func RegisterFileEndpoints(r *gin.RouterGroup){
r.GET("/:simulationID/models/:modelID/files", GetFilesOfModel)
r.POST ("/:simulationID/models/:modelID/file", AddFileToModel)
//r.POST ("/:simulationID/models/:modelID/file", CloneFileOfModel)
r.GET("/:simulationID/models/:modelID/file", GetFileOfModel)
r.PUT("/:simulationID/models/:modelID/file", UpdateFileOfModel)
r.DELETE("/:simulationID/models/:modelID/file", DeleteFileOfModel)
r.GET("/:simulationID/visualizations/:visualizationID/widgets/:widgetID/files", GetFilesOfWidget)
r.POST ("/:simulationID/visualizations/:visualizationID/widgets/:widgetID/file", AddFileToWidget)
//r.POST ("/:simulationID/visualizations/:visualizationID/widgets/:widgetID/file", CloneFileOfWidget)
r.GET("/:simulationID/visualizations/:visualizationID/widgets/:widgetID/file", GetFileOfWidget)
r.PUT("/:simulationID/visualizations/:visualizationID/widgets/:widgetID/file", UpdateFileOfWidget)
r.DELETE("/:simulationID/visualizations/:visualizationID/widgets/:widgetID/file", DeleteFileOfWidget)
}
// GetFilesOfModel godoc
// @Summary Get all parameters of files of model
// @ID GetAllModelFileParams
// @ID GetFilesOfModel
// @Tags file
// @Success 200 {array} common.File "File parameters requested by user"
// @Failure 401 "Unauthorized Access"
@ -26,7 +38,7 @@ import (
// @Param simulationID path int true "Simulation ID"
// @Param modelID path int true "Model ID"
// @Router simulations/{simulationID}/models/{modelID}/files [get]
func fileMReadAllEp(c *gin.Context) {
func GetFilesOfModel(c *gin.Context) {
simulationID, modelID, err := getRequestParams(c)
if err != nil{
@ -34,10 +46,10 @@ func fileMReadAllEp(c *gin.Context) {
}
// Find files' properties in DB and return in HTTP response, no change to DB
allFiles, _, err := queries.FindFiles(c, -1, modelID, simulationID)
allFiles, _, err := FindFiles(c, -1, modelID, simulationID)
if common.ProvideErrorResponse(c, err) == false {
serializer := serializers.FilesSerializerNoAssoc{c, allFiles}
serializer := common.FilesSerializerNoAssoc{c, allFiles}
c.JSON(http.StatusOK, gin.H{
"files": serializer.Response(),
})
@ -45,9 +57,9 @@ func fileMReadAllEp(c *gin.Context) {
}
// fileMRegistrationEp godoc
// AddFileToModel godoc
// @Summary Get all parameters of files of model
// @ID PostFileToModel
// @ID AddFileToModel
// @Tags file
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
@ -57,7 +69,7 @@ func fileMReadAllEp(c *gin.Context) {
// @Param simulationID path int true "Simulation ID"
// @Param modelID path int true "Model ID"
// @Router simulations/{simulationID}/models/{modelID}/file [post]
func fileMRegistrationEp(c *gin.Context) {
func AddFileToModel(c *gin.Context) {
simulationID, modelID, err := getRequestParams(c)
if err != nil{
@ -65,11 +77,11 @@ func fileMRegistrationEp(c *gin.Context) {
}
// Save file locally and register file in DB, HTTP response is set by this method
queries.RegisterFile(c,-1, modelID, simulationID)
RegisterFile(c,-1, modelID, simulationID)
}
func fileMCloneEp(c *gin.Context) {
func CloneFileOfModel(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
@ -77,7 +89,7 @@ func fileMCloneEp(c *gin.Context) {
}
func fileMReadEp(c *gin.Context) {
func GetFileOfModel(c *gin.Context) {
simulationID, modelID, err := getRequestParams(c)
if err != nil{
@ -85,10 +97,10 @@ func fileMReadEp(c *gin.Context) {
}
// Read file from disk and return in HTTP response, no change to DB
queries.ReadFile(c, -1, modelID, simulationID)
ReadFile(c, -1, modelID, simulationID)
}
func fileMUpdateEp(c *gin.Context) {
func UpdateFileOfModel(c *gin.Context) {
simulationID, modelID, err := getRequestParams(c)
if err != nil{
@ -96,10 +108,10 @@ func fileMUpdateEp(c *gin.Context) {
}
// Update file locally and update file entry in DB, HTTP response is set by this method
queries.UpdateFile(c,-1, modelID, simulationID)
UpdateFile(c,-1, modelID, simulationID)
}
func fileMDeleteEp(c *gin.Context) {
func DeleteFileOfModel(c *gin.Context) {
simulationID, modelID, err := getRequestParams(c)
if err != nil{
@ -107,12 +119,12 @@ func fileMDeleteEp(c *gin.Context) {
}
// Delete file from disk and remove entry from DB, HTTP response is set by this method
queries.DeleteFile(c, -1, modelID, simulationID)
DeleteFile(c, -1, modelID, simulationID)
}
func fileWReadAllEp(c *gin.Context) {
func GetFilesOfWidget(c *gin.Context) {
simulationID, widgetID, err := getRequestParams(c)
if err != nil{
@ -120,10 +132,10 @@ func fileWReadAllEp(c *gin.Context) {
}
// Find files' properties in DB and return in HTTP response, no change to DB
allFiles, _, err := queries.FindFiles(c, widgetID, -1, simulationID)
allFiles, _, err := FindFiles(c, widgetID, -1, simulationID)
if common.ProvideErrorResponse(c, err) == false {
serializer := serializers.FilesSerializerNoAssoc{c, allFiles}
serializer := common.FilesSerializerNoAssoc{c, allFiles}
c.JSON(http.StatusOK, gin.H{
"files": serializer.Response(),
})
@ -131,7 +143,7 @@ func fileWReadAllEp(c *gin.Context) {
}
func fileWRegistrationEp(c *gin.Context) {
func AddFileToWidget(c *gin.Context) {
simulationID, widgetID, err := getRequestParams(c)
if err != nil{
@ -139,11 +151,11 @@ func fileWRegistrationEp(c *gin.Context) {
}
// Save file locally and register file in DB, HTTP response is set by this method
queries.RegisterFile(c,widgetID, -1, simulationID)
RegisterFile(c,widgetID, -1, simulationID)
}
func fileWCloneEp(c *gin.Context) {
func CloneFileOfWidget(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
@ -151,7 +163,7 @@ func fileWCloneEp(c *gin.Context) {
}
func fileWReadEp(c *gin.Context) {
func GetFileOfWidget(c *gin.Context) {
simulationID, widgetID, err := getRequestParams(c)
if err != nil{
@ -159,10 +171,10 @@ func fileWReadEp(c *gin.Context) {
}
// Read file from disk and return in HTTP response, no change to DB
queries.ReadFile(c, widgetID, -1, simulationID)
ReadFile(c, widgetID, -1, simulationID)
}
func fileWUpdateEp(c *gin.Context) {
func UpdateFileOfWidget(c *gin.Context) {
simulationID, widgetID, err := getRequestParams(c)
if err != nil{
@ -170,10 +182,10 @@ func fileWUpdateEp(c *gin.Context) {
}
// Update file locally and update file entry in DB, HTTP response is set by this method
queries.UpdateFile(c,widgetID, -1, simulationID)
UpdateFile(c,widgetID, -1, simulationID)
}
func fileWDeleteEp(c *gin.Context) {
func DeleteFileOfWidget(c *gin.Context) {
simulationID, widgetID, err := getRequestParams(c)
if err != nil{
@ -181,7 +193,7 @@ func fileWDeleteEp(c *gin.Context) {
}
// Delete file from disk and remove entry from DB, HTTP response is set by this method
queries.DeleteFile(c, widgetID, -1, simulationID)
DeleteFile(c, widgetID, -1, simulationID)
}
@ -254,9 +266,9 @@ func getRequestParams(c *gin.Context) (int, int, error){
}
var subID int
subID, err = GetModelID(c)
subID, err = common.GetModelID(c)
if err != nil{
subID, err = GetWidgetID(c)
subID, err = common.GetWidgetID(c)
if err != nil {
return -1, -1, err
}

View file

@ -1,4 +1,4 @@
package queries
package file
import (
"fmt"
@ -13,6 +13,9 @@ import (
_ "github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/model"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/widget"
)
//func FindAllFiles() ([]common.File, int, error) {
@ -103,18 +106,18 @@ func RegisterFile(c *gin.Context, widgetID int, modelID int, simulationID int){
size := file_header.Size
// Check if simulation and widget or model exist in DB
_, err = FindSimulation(simulationID)
_, err = simulation.FindSimulation(simulationID)
if common.ProvideErrorResponse(c, err) {
return
}
if modelID != -1 {
_, err = FindModel(modelID)
_, err = model.FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
} else if widgetID != -1 {
_, err = FindWidget(widgetID)
_, err = widget.FindWidget(widgetID)
if common.ProvideErrorResponse(c, err) {
return
}

View file

@ -0,0 +1,314 @@
package model
import (
"fmt"
"net/http"
"strconv"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulator"
"github.com/gin-gonic/gin"
)
func RegisterModelEndpoints(r *gin.RouterGroup){
r.GET("/:simulationID/models/", GetModels)
r.POST("/:simulationID/models/", AddModel)
r.POST("/:simulationID/models/:modelID", CloneModel)
r.PUT("/:simulationID/models/:modelID", UpdateModel)
r.GET("/:simulationID/models/:modelID", GetModel)
r.DELETE("/:simulationID/models/:modelID", DeleteModel)
r.PUT("/:simulationID/models/:modelID/simulator", UpdateSimulator)
r.GET("/:simulationID/models/:modelID/simulator", GetSimulator)
r.POST("/:simulationID/models/:modelID/signals/:direction", UpdateSignals)
r.GET("/:simulationID/models/:modelID/signals/:direction", GetSignals)
}
// GetModels godoc
// @Summary Get all models of simulation
// @ID GetModels
// @Produce json
// @Tags model
// @Success 200 {array} common.ModelResponse "Array of models to which belong to simulation"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Router /simulations/{simulationID}/models [get]
func GetModels(c *gin.Context) {
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
allModels, _, err := FindAllModels(simID)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := common.ModelsSerializer{c, allModels}
c.JSON(http.StatusOK, gin.H{
"models": serializer.Response(),
})
}
// AddModel godoc
// @Summary Add a model to a simulation
// @ID AddModel
// @Tags model
// @Param inputModel body common.ModelResponse true "Model to be added"
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Router /simulations/{simulationID}/models [post]
func AddModel(c *gin.Context) {
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
var m Model
err = c.BindJSON(&m)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
err = m.addToSimulation(simID)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
func CloneModel(c *gin.Context) {
// modelID, err := routes.GetModelID(c)
// if err != nil {
// return
// }
//
// targetSimID, err := strconv.Atoi(c.PostForm("TargetSim"))
// if err != nil {
// errormsg := fmt.Sprintf("Bad request. No or incorrect format of target sim ID")
// c.JSON(http.StatusBadRequest, gin.H{
// "error": errormsg,
// })
// return
// }
// TODO TO BE IMPLEMENTED
// Check if target sim exists
// Check if model exists
// Get all Signals of Model
// Get Simulator of Model
// Get Files of model
// Add new model object to DB and associate with target sim
// Add new signal objects to DB and associate with new model object (careful with directions)
// Associate Simulator with new Model object
c.JSON(http.StatusOK, gin.H{
"message": "Not implemented.",
})
}
func UpdateModel(c *gin.Context) {
modelID, err := common.GetModelID(c)
if err != nil {
return
}
var m Model
err = c.BindJSON(&m)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
err = m.UpdateModel(modelID)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
func GetModel(c *gin.Context) {
modelID, err := common.GetModelID(c)
if err != nil {
return
}
m, err := FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := common.ModelSerializer{c, m}
c.JSON(http.StatusOK, gin.H{
"model": serializer.Response(),
})
}
func DeleteModel(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "Not implemented.",
})
}
func GetSimulator(c *gin.Context) {
modelID, err := common.GetModelID(c)
if err != nil {
return
}
m, err := FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
smtr, err := simulator.FindSimulator(int(m.SimulatorID))
if common.ProvideErrorResponse(c, err) {
return
}
serializer := common.SimulatorSerializer{c, smtr}
c.JSON(http.StatusOK, gin.H{
"simulator": serializer.Response(),
})
}
func UpdateSimulator(c *gin.Context) {
// simulator ID as parameter of Query, e.g. simulations/:SimulationID/models/:ModelID/simulator?simulatorID=42
simulatorID, err := strconv.Atoi(c.Query("simulatorID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect simulator ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
modelID, err := common.GetModelID(c)
if err != nil {
return
}
smtr, err := simulator.FindSimulator(simulatorID)
if common.ProvideErrorResponse(c, err) {
return
}
_m, err := FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
var m = Model{_m}
err = m.UpdateSimulator(&smtr)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK",
})
}
}
func UpdateSignals(c *gin.Context) {
modelID, err := common.GetModelID(c)
if err != nil {
return
}
_m, err := FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
direction := c.Param("direction")
if !(direction == "out") && !(direction == "in") {
errormsg := "Bad request. Direction has to be in or out"
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
var sigs []common.Signal
err = c.BindJSON(&sigs)
if err != nil {
errormsg := "Bad request. Error binding form data to JSON: " + err.Error()
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
// Add signals to model and remove all existing Signals of the requested direction (if any)
var m = Model{_m}
err = m.UpdateSignals(sigs, direction)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
})
}
}
func GetSignals(c *gin.Context) {
modelID, err := common.GetModelID(c)
if err != nil {
return
}
m, err := FindModel(modelID)
if common.ProvideErrorResponse(c, err) {
return
}
direction := c.Param("direction")
if !(direction == "out") && !(direction == "in") {
errormsg := "Bad request. Direction has to be in or out"
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return
}
var signals []common.Signal
if direction == "in" {
signals = m.InputMapping
} else {
signals = m.OutputMapping
}
c.JSON(http.StatusOK, gin.H{
"signals": signals,
})
}

View file

@ -0,0 +1,74 @@
package model
import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
)
type Model struct{
common.Model
}
func FindAllModels(simID int) ([]common.Model, int, error) {
db := common.GetDB()
var models []common.Model
sim, err := simulation.FindSimulation(simID)
if err != nil {
return models, 0, err
}
err = db.Model(sim).Related(&models, "Models").Error
return models, len(models), err
}
func FindModel(modelID int) (common.Model, error){
db := common.GetDB()
var m common.Model
err := db.First(&m, modelID).Error
return m, err
}
func (m *Model) addToSimulation(simID int) error {
db := common.GetDB()
sim, err := simulation.FindSimulation(simID)
if err != nil {
return err
}
err = db.Model(&sim).Association("Models").Append(m).Error
return err
}
func (m *Model) UpdateModel(modelID int) error {
db := common.GetDB()
model_to_update, err := FindModel(modelID)
if err != nil {
return err
}
// only Name and Start Params can be updated directly by the user
err = db.Model(&model_to_update).Updates(map[string]interface{}{"Name": m.Name, "StartParameters": m.StartParameters}).Error
return err
}
func (m *Model) UpdateSimulator(simulator *common.Simulator) error {
db := common.GetDB()
err := db.Model(m).Association("Simulator").Replace(simulator).Error
return err
}
func (m *Model) UpdateSignals(signals []common.Signal, direction string) error {
db := common.GetDB()
var err error
if direction == "in" {
err = db.Model(m).Select("InputMapping").Update("InputMapping", signals).Error
} else {
err = db.Model(m).Select("OutputMapping").Update("OutputMapping", signals).Error
}
return err
}

View file

@ -1,106 +1,96 @@
package endpoints
package simulation
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/serializers"
)
// getSimulationsEp godoc
func RegisterSimulationEndpoints(r *gin.RouterGroup){
r.GET("/", GetSimulations)
r.POST("/", AddSimulation)
r.POST("/:simulationID", CloneSimulation)
r.PUT("/:simulationID", UpdateSimulation)
r.GET("/:simulationID", GetSimulation)
r.DELETE("/:simulationID", DeleteSimulation)
}
// GetSimulations godoc
// @Summary Get all simulations
// @ID GetAllSimulations
// @ID GetSimulations
// @Produce json
// @Tags simulation
// @Success 200 {array} common.Simulation "Array of simulations to which user has access"
// @Success 200 {array} common.SimulationResponse "Array of simulations to which user has access"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Router /simulations [get]
func getSimulationsEp(c *gin.Context) {
func GetSimulations(c *gin.Context) {
//TODO Identify user who is issuing the request and return only those simulations that are known to the user
allSimulations, _, _ := queries.FindAllSimulations()
serializer := serializers.SimulationsSerializer{c, allSimulations}
allSimulations, _, _ := FindAllSimulations()
serializer := common.SimulationsSerializer{c, allSimulations}
c.JSON(http.StatusOK, gin.H{
"simulations": serializer.Response(),
})
}
func simulationRegistrationEp(c *gin.Context) {
func AddSimulation(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func simulationCloneEp(c *gin.Context) {
func CloneSimulation(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func simulationUpdateEp(c *gin.Context) {
func UpdateSimulation(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
// getSimulationEp godoc
// GetSimulation godoc
// @Summary Get simulation
// @ID GetSimulation
// @Produce json
// @Tags simulation
// @Success 200 {object} common.Simulation "Simulation requested by user"
// @Success 200 {object} common.SimulationResponse "Simulation requested by user"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Param simulationID path int true "Simulation ID"
// @Router /simulations/{simulationID} [get]
func getSimulationEp(c *gin.Context) {
func GetSimulation(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := serializers.SimulationSerializer{c, sim}
serializer := common.SimulationSerializer{c, sim}
c.JSON(http.StatusOK, gin.H{
"simulation": serializer.Response(),
})
}
func simulationDeleteEp(c *gin.Context) {
func DeleteSimulation(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func GetSimulationID(c *gin.Context) (int, error) {
simID, err := strconv.Atoi(c.Param("SimulationID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of simulation ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return -1, err
} else {
return simID, err
}
}

View file

@ -1,4 +1,4 @@
package queries
package simulation
import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"

View file

@ -0,0 +1,58 @@
package simulator
import (
"net/http"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
func RegisterSimulatorEndpoints(r *gin.RouterGroup){
r.GET("/", GetSimulators)
r.POST("/", AddSimulator)
r.PUT("/:simulatorID", UpdateSimulator)
r.GET("/:simulatorID", GetSimulator)
r.DELETE("/:simulatorID", DeleteSimulator)
r.POST("/:simulatorID", SendActionToSimulator)
}
func GetSimulators(c *gin.Context) {
allSimulators, _, _ := FindAllSimulators()
serializer := common.SimulatorsSerializer{c, allSimulators}
c.JSON(http.StatusOK, gin.H{
"simulators": serializer.Response(),
})
}
func AddSimulator(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func UpdateSimulator(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func GetSimulator(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func DeleteSimulator(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func SendActionToSimulator(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}

View file

@ -1,4 +1,4 @@
package queries
package simulator
import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"

View file

@ -1,4 +1,4 @@
package endpoints
package user
import (
"net/http"
@ -6,71 +6,86 @@ import (
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/serializers"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
)
func RegisterUserEndpoints(r *gin.RouterGroup){
r.GET("/", GetUsers)
r.POST("/", AddUser)
r.PUT("/:userID", UpdateUser)
r.GET("/:userID", GetUser)
r.GET("/:userID/simulations", GetSimulationsOfUser)
r.DELETE("/:userID", DeleteUser)
//r.GET("/me", userSelfEp) // TODO redirect to users/:userID
}
func userReadAllEp(c *gin.Context) {
allUsers, _, _ := queries.FindAllUsers()
serializer := serializers.UsersSerializer{c, allUsers}
func RegisterUserEndpointsForSimulation(r *gin.RouterGroup){
r.GET("/:simulationID/users", GetUsersOfSimulation)
r.PUT("/:simulationID/user/:username", UpdateUserOfSimulation)
r.DELETE("/:simulationID/user/:username", DeleteUserOfSimulation)
}
func GetUsers(c *gin.Context) {
allUsers, _, _ := FindAllUsers()
serializer := common.UsersSerializer{c, allUsers}
c.JSON(http.StatusOK, gin.H{
"users": serializer.Response(),
})
}
// userReadAllSimEp godoc
// GetUsersOfSimulation godoc
// @Summary Get users of simulation
// @ID GetAllUsersOfSimulation
// @ID GetUsersOfSimulation
// @Produce json
// @Tags user
// @Success 200 {array} common.User "Array of users that have access to the simulation"
// @Success 200 {array} common.UserResponse "Array of users that have access to the simulation"
// @Failure 401 "Unauthorized Access"
// @Failure 403 "Access forbidden."
// @Failure 404 "Not found"
// @Failure 500 "Internal server error"
// @Param simulationID path int true "Simulation ID"
// @Router /simulations/{simulationID}/users [get]
func userReadAllSimEp(c *gin.Context) {
func GetUsersOfSimulation(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
// Find all users of simulation
allUsers, _, err := queries.FindAllUsersSim(&sim)
allUsers, _, err := FindAllUsersSim(&sim)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := serializers.UsersSerializer{c, allUsers}
serializer := common.UsersSerializer{c, allUsers}
c.JSON(http.StatusOK, gin.H{
"users": serializer.Response(),
})
}
func userRegistrationEp(c *gin.Context) {
func AddUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func userUpdateEp(c *gin.Context) {
func UpdateUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
// userUpdateSimEp godoc
// UpdateUserOfSimulation godoc
// @Summary Add user to simulation
// @ID AddUserToSimulation
// @ID UpdateUserOfSimulation
// @Tags user
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
@ -80,27 +95,27 @@ func userUpdateEp(c *gin.Context) {
// @Param simulationID path int true "Simulation ID"
// @Param username path int true "Username of user to be added"
// @Router /simulations/{simulationID}/users/{username} [put]
func userUpdateSimEp(c *gin.Context) {
func UpdateUserOfSimulation(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
username := c.Param("username")
user, err := queries.FindUserByName(username)
user, err := FindUserByName(username)
if common.ProvideErrorResponse(c, err) {
return
}
err = queries.AddUserToSim(&sim, &user)
err = AddUserToSim(&sim, &user)
if common.ProvideErrorResponse(c, err){
return
}
@ -110,27 +125,27 @@ func userUpdateSimEp(c *gin.Context) {
})
}
func userReadEp(c *gin.Context) {
func GetUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func userReadSimEp(c *gin.Context) {
func GetSimulationsOfUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func userDeleteEp(c *gin.Context) {
func DeleteUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
// userDeleteSimEp godoc
// DeleteUserOfSimulation godoc
// @Summary Delete user from simulation
// @ID DeleteUserFromSimulation
// @ID DeleteUserOfSimulation
// @Tags user
// @Success 200 "OK."
// @Failure 401 "Unauthorized Access"
@ -140,21 +155,21 @@ func userDeleteEp(c *gin.Context) {
// @Param simulationID path int true "Simulation ID"
// @Param username path int true "Username of user"
// @Router /simulations/{simulationID}/users/{username} [delete]
func userDeleteSimEp(c *gin.Context) {
func DeleteUserOfSimulation(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
username := c.Param("username")
err = queries.RemoveUserFromSim(&sim, username)
err = RemoveUserFromSim(&sim, username)
if common.ProvideErrorResponse(c, err) {
return
}
@ -163,9 +178,3 @@ func userDeleteSimEp(c *gin.Context) {
"message": "OK.",
})
}
func userSelfEp(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}

View file

@ -1,4 +1,4 @@
package queries
package user
import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"

View file

@ -1,44 +1,52 @@
package endpoints
package visualization
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/serializers"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
)
func visualizationReadAllEp(c *gin.Context) {
func RegisterVisualizationEndpoints(r *gin.RouterGroup){
simID, err := GetSimulationID(c)
r.GET("/:simulationID/visualizations", GetVisualizations)
r.POST("/:simulationID/visualization", AddVisualization)
r.POST("/:simulationID/visualization/:visualizationID", CloneVisualization)
r.PUT("/:simulationID/visualization/:visualizationID", UpdateVisualization)
r.GET("/:simulationID/visualization/:visualizationID", GetVisualization)
r.DELETE("/:simulationID/visualization/:visualizationID", DeleteVisualization)
}
func GetVisualizations(c *gin.Context) {
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
allVisualizations, _, _ := queries.FindAllVisualizationsOfSim(&sim)
serializer := serializers.VisualizationsSerializer{c, allVisualizations}
allVisualizations, _, _ := FindAllVisualizationsOfSim(&sim)
serializer := common.VisualizationsSerializer{c, allVisualizations}
c.JSON(http.StatusOK, gin.H{
"visualizations": serializer.Response(),
})
}
func visualizationRegistrationEp(c *gin.Context) {
func AddVisualization(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
@ -54,7 +62,7 @@ func visualizationRegistrationEp(c *gin.Context) {
}
// add visualization to DB and add association to simulation
err = queries.AddVisualizationToSim(&sim, &vis)
err = AddVisualizationToSim(&sim, &vis)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK",
@ -62,25 +70,25 @@ func visualizationRegistrationEp(c *gin.Context) {
}
}
func visualizationCloneEp(c *gin.Context) {
func CloneVisualization(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func visualizationUpdateEp(c *gin.Context) {
func UpdateVisualization(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
visID, err := GetVisualizationID(c)
visID, err := common.GetVisualizationID(c)
if err != nil {
return
}
@ -95,7 +103,7 @@ func visualizationUpdateEp(c *gin.Context) {
return
}
err = queries.UpdateVisualizationOfSim(&sim, vis, visID)
err = UpdateVisualizationOfSim(&sim, vis, visID)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK",
@ -103,53 +111,38 @@ func visualizationUpdateEp(c *gin.Context) {
}
}
func visualizationReadEp(c *gin.Context) {
func GetVisualization(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
visID, err := GetVisualizationID(c)
visID, err := common.GetVisualizationID(c)
if err != nil {
return
}
visualization, err := queries.FindVisualizationOfSim(&sim, visID)
visualization, err := FindVisualizationOfSim(&sim, visID)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := serializers.VisualizationSerializer{c, visualization}
serializer := common.VisualizationSerializer{c, visualization}
c.JSON(http.StatusOK, gin.H{
"visualization": serializer.Response(),
})
}
func visualizationDeleteEp(c *gin.Context) {
func DeleteVisualization(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func GetVisualizationID(c *gin.Context) (int, error) {
simID, err := strconv.Atoi(c.Param("visualizationID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of visualization ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return -1, err
} else {
return simID, err
}
}

View file

@ -1,4 +1,4 @@
package queries
package visualization
import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"

View file

@ -1,69 +1,75 @@
package endpoints
package widget
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/serializers"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/visualization"
)
func RegisterWidgetEndpoints(r *gin.RouterGroup){
r.GET("/:simulationID/visualization/:visualizationID/widgets", GetWidgets)
r.POST("/:simulationID/visualization/:visualizationID/widget", AddWidget)
r.POST("/:simulationID/visualization/:visualizationID/widget:widgetID", CloneWidget)
r.PUT("/:simulationID/visualization/:visualizationID/widget/:widgetID", UpdateWidget)
r.GET("/:simulationID/visualization/:visualizationID/widget/:widgetID", GetWidget)
r.DELETE("/:simulationID/visualization/:visualizationID/widget/:widgetID", DeleteWidget)
}
func widgetReadAllEp(c *gin.Context) {
func GetWidgets(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
visID, err := GetVisualizationID(c)
visID, err := common.GetVisualizationID(c)
if err != nil {
return
}
vis, err := queries.FindVisualizationOfSim(&sim, visID)
vis, err := visualization.FindVisualizationOfSim(&sim, visID)
if common.ProvideErrorResponse(c, err) {
return
}
widgets,_, err := queries.FindWidgetsOfVisualization(&vis)
widgets,_, err := FindWidgetsOfVisualization(&vis)
if common.ProvideErrorResponse(c, err) {
return
}
serializer := serializers.WidgetsSerializer{c, widgets}
serializer := common.WidgetsSerializer{c, widgets}
c.JSON(http.StatusOK, gin.H{
"widgets": serializer.Response(),
})
}
func widgetRegistrationEp(c *gin.Context) {
func AddWidget(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
visID, err := GetVisualizationID(c)
visID, err := common.GetVisualizationID(c)
if err != nil {
return
}
vis, err := queries.FindVisualizationOfSim(&sim, visID)
vis, err := visualization.FindVisualizationOfSim(&sim, visID)
if common.ProvideErrorResponse(c, err) {
return
}
@ -78,7 +84,7 @@ func widgetRegistrationEp(c *gin.Context) {
return
}
err = queries.AddWidgetToVisualization(&vis, &widget_input)
err = AddWidgetToVisualization(&vis, &widget_input)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK.",
@ -88,34 +94,34 @@ func widgetRegistrationEp(c *gin.Context) {
}
func widgetCloneEp(c *gin.Context) {
func CloneWidget(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "NOT implemented",
})
}
func widgetUpdateEp(c *gin.Context) {
simID, err := GetSimulationID(c)
func UpdateWidget(c *gin.Context) {
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
visID, err := GetVisualizationID(c)
visID, err := common.GetVisualizationID(c)
if err != nil {
return
}
vis, err := queries.FindVisualizationOfSim(&sim, visID)
vis, err := visualization.FindVisualizationOfSim(&sim, visID)
if common.ProvideErrorResponse(c, err) {
return
}
widgetID, err := GetWidgetID(c)
widgetID, err := common.GetWidgetID(c)
if err != nil {
return
}
@ -130,7 +136,7 @@ func widgetUpdateEp(c *gin.Context) {
return
}
err = queries.UpdateWidgetOfVisualization(&vis, widget_input, widgetID)
err = UpdateWidgetOfVisualization(&vis, widget_input, widgetID)
if common.ProvideErrorResponse(c, err) == false {
c.JSON(http.StatusOK, gin.H{
"message": "OK",
@ -138,41 +144,41 @@ func widgetUpdateEp(c *gin.Context) {
}
}
func widgetReadEp(c *gin.Context) {
func GetWidget(c *gin.Context) {
simID, err := GetSimulationID(c)
simID, err := common.GetSimulationID(c)
if err != nil {
return
}
sim, err := queries.FindSimulation(simID)
sim, err := simulation.FindSimulation(simID)
if common.ProvideErrorResponse(c, err) {
return
}
visID, err := GetVisualizationID(c)
visID, err := common.GetVisualizationID(c)
if err != nil {
return
}
visualization, err := queries.FindVisualizationOfSim(&sim, visID)
vis, err := visualization.FindVisualizationOfSim(&sim, visID)
if common.ProvideErrorResponse(c, err) {
return
}
widgetID, err := GetWidgetID(c)
widgetID, err := common.GetWidgetID(c)
if err != nil {
return
}
widget, err := queries.FindWidgetOfVisualization(&visualization, widgetID)
serializer := serializers.WidgetSerializer{c, widget}
widget, err := FindWidgetOfVisualization(&vis, widgetID)
serializer := common.WidgetSerializer{c, widget}
c.JSON(http.StatusOK, gin.H{
"widget": serializer.Response(),
})
}
func widgetDeleteEp(c *gin.Context) {
func DeleteWidget(c *gin.Context) {
// simID, err := GetSimulationID(c)
// if err != nil {
@ -215,18 +221,3 @@ func widgetDeleteEp(c *gin.Context) {
}
func GetWidgetID(c *gin.Context) (int, error) {
widgetID, err := strconv.Atoi(c.Param("WidgetID"))
if err != nil {
errormsg := fmt.Sprintf("Bad request. No or incorrect format of widget ID")
c.JSON(http.StatusBadRequest, gin.H{
"error": errormsg,
})
return -1, err
} else {
return widgetID, err
}
}

View file

@ -1,4 +1,4 @@
package queries
package widget
import (
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"

View file

@ -1,53 +0,0 @@
package serializers
import (
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
// File/s Serializers
type FilesSerializerNoAssoc struct {
Ctx *gin.Context
Files []common.File
}
func (self *FilesSerializerNoAssoc) Response() []FileResponseNoAssoc {
response := []FileResponseNoAssoc{}
for _, files := range self.Files {
serializer := FileSerializerNoAssoc{self.Ctx, files}
response = append(response, serializer.Response())
}
return response
}
type FileSerializerNoAssoc struct {
Ctx *gin.Context
common.File
}
type FileResponseNoAssoc struct {
Name string `json:"Name"`
ID uint `json:"FileID"`
Path string `json:"Path"`
Type string `json:"Type"`
Size uint `json:"Size"`
H uint `json:"ImageHeight"`
W uint `json:"ImageWidth"`
// Date
}
func (self *FileSerializerNoAssoc) Response() FileResponseNoAssoc {
response := FileResponseNoAssoc{
Name: self.Name,
ID: self.ID,
Path: self.Path,
Type: self.Type,
Size: self.Size,
H: self.ImageHeight,
W: self.ImageWidth,
// Date
}
return response
}

View file

@ -1,54 +0,0 @@
package serializers
import (
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm/dialects/postgres"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
type ModelsSerializer struct {
Ctx *gin.Context
Models []common.Model
}
func (self *ModelsSerializer) Response() []ModelResponse {
response := []ModelResponse{}
for _, model := range self.Models {
serializer := ModelSerializer{self.Ctx, model}
response = append(response, serializer.Response())
}
return response
}
type ModelSerializer struct {
Ctx *gin.Context
common.Model
}
type ModelResponse struct {
Name string `json:"Name"`
OutputLength int `json:"OutputLength"`
InputLength int `json:"InputLength"`
SimulationID uint `json:"SimulationID"`
SimulatorID uint `json:"SimulatorID"`
StartParams postgres.Jsonb `json:"StartParams"`
//StartParams postgres.Jsonb `json:"Starting Parameters"`
//Output Mapping
//Input Mapping
}
func (self *ModelSerializer) Response() ModelResponse {
response := ModelResponse{
Name: self.Name,
OutputLength: self.OutputLength,
InputLength: self.InputLength,
SimulationID: self.SimulationID,
SimulatorID: self.SimulatorID,
StartParams: self.StartParameters,
//InputMapping
//OutputMapping
}
return response
}

View file

@ -1 +0,0 @@
package serializers

View file

@ -1,44 +0,0 @@
package serializers
import (
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm/dialects/postgres"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
type SimulationsSerializer struct {
Ctx *gin.Context
Simulations []common.Simulation
}
func (self *SimulationsSerializer) Response() []SimulationResponse {
response := []SimulationResponse{}
for _, simulation := range self.Simulations {
serializer := SimulationSerializer{self.Ctx, simulation}
response = append(response, serializer.Response())
}
return response
}
type SimulationSerializer struct {
Ctx *gin.Context
common.Simulation
}
type SimulationResponse struct {
Name string `json:"Name"`
ID uint `json:"SimulationID"`
Running bool `json:"Running"`
StartParams postgres.Jsonb `json:"Starting Parameters"`
}
func (self *SimulationSerializer) Response() SimulationResponse {
response := SimulationResponse{
Name: self.Name,
ID: self.ID,
Running: self.Running,
StartParams: self.StartParameters,
}
return response
}

View file

@ -1,52 +0,0 @@
package serializers
import (
"time"
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
type SimulatorsSerializer struct {
Ctx *gin.Context
Simulators []common.Simulator
}
func (self *SimulatorsSerializer) Response() []SimulatorResponse {
response := []SimulatorResponse{}
for _, simulator := range self.Simulators {
serializer := SimulatorSerializer{self.Ctx, simulator}
response = append(response, serializer.Response())
}
return response
}
type SimulatorSerializer struct {
Ctx *gin.Context
common.Simulator
}
type SimulatorResponse struct {
UUID string `json:"UUID"`
Host string `json:"Host"`
ModelType string `json:"ModelType"`
Uptime int `json:"Uptime"`
State string `json:"State"`
StateUpdateAt time.Time `json:"StateUpdateAt"`
// Properties
// Raw Properties
}
func (self *SimulatorSerializer) Response() SimulatorResponse {
response := SimulatorResponse{
UUID: self.UUID,
Host: self.Host,
ModelType: self.Modeltype,
Uptime: self.Uptime,
State: self.State,
StateUpdateAt: self.StateUpdateAt,
}
return response
}

View file

@ -1,45 +0,0 @@
package serializers
import (
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
type UsersSerializer struct {
Ctx *gin.Context
Users []common.User
}
func (self *UsersSerializer) Response() []UserResponse {
response := []UserResponse{}
for _, user := range self.Users {
serializer := UserSerializer{self.Ctx, user}
response = append(response, serializer.Response())
}
return response
}
type UserSerializer struct {
Ctx *gin.Context
common.User
}
type UserResponse struct {
Username string `json:"Username"`
Role string `json:"Role"`
Mail string `json:"Mail"`
}
func (self *UserSerializer) Response() UserResponse {
response := UserResponse{
Username: self.Username,
Role: self.Role,
Mail: self.Mail,
}
return response
}

View file

@ -1,49 +0,0 @@
package serializers
import (
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/queries"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
type VisualizationsSerializer struct {
Ctx *gin.Context
Visualizations []common.Visualization
}
func (self *VisualizationsSerializer) Response() []VisualizationResponse {
response := []VisualizationResponse{}
for _, visualization := range self.Visualizations {
serializer := VisualizationSerializer{self.Ctx, visualization}
response = append(response, serializer.Response())
}
return response
}
type VisualizationSerializer struct {
Ctx *gin.Context
common.Visualization
}
type VisualizationResponse struct {
Name string `json:"Name"`
Grid int `json:"Grid"`
SimulationID uint `json:"SimulationID"`
Widgets []WidgetResponse
}
func (self *VisualizationSerializer) Response() VisualizationResponse {
w, _, _:= queries.FindVisualizationWidgets(&self.Visualization)
widgetsSerializer := WidgetsSerializer{self.Ctx, w}
response := VisualizationResponse{
Name: self.Name,
Grid: self.Grid,
SimulationID: self.SimulationID,
Widgets: widgetsSerializer.Response(),
}
return response
}

View file

@ -1,60 +0,0 @@
package serializers
import (
"github.com/gin-gonic/gin"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
)
type WidgetsSerializer struct {
Ctx *gin.Context
Widgets []common.Widget
}
func (self *WidgetsSerializer) Response() []WidgetResponse {
response := []WidgetResponse{}
for _, widget := range self.Widgets {
serializer := WidgetSerializer{self.Ctx, widget}
response = append(response, serializer.Response())
}
return response
}
type WidgetSerializer struct {
Ctx *gin.Context
common.Widget
}
type WidgetResponse struct {
Name string `json:"Name"`
Type string `json:"Type"`
Width uint `json:"Width"`
Height uint `json:"Height"`
MinWidth uint `json:"MinWidth"`
MinHeight uint `json:"MinHeight"`
X int `json:"X"`
Y int `json:"Y"`
Z int `json:"Z"`
VisualizationID uint `json:"VisualizationID"`
IsLocked bool `json:"IsLocked"`
//CustomProperties
}
func (self *WidgetSerializer) Response() WidgetResponse {
response := WidgetResponse{
Name: self.Name,
Type: self.Type,
Width: self.Width,
Height: self.Height,
MinWidth: self.MinWidth,
MinHeight: self.MinHeight,
X: self.X,
Y: self.Y,
Z: self.Z,
VisualizationID: self.VisualizationID,
IsLocked: self.IsLocked,
//CustomProperties
}
return response
}

View file

@ -5,10 +5,15 @@ import (
"github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/endpoints"
_ "git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/apidocs" // apidocs folder is generated by Swag CLI, you have to import it
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/common"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/file"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/model"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulation"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/simulator"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/user"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/visualization"
"git.rwth-aachen.de/acs/public/villas/villasweb-backend-go/routes/widget"
)
@ -36,18 +41,18 @@ func main() {
r := gin.Default()
api := r.Group("/api")
// use ginSwagger middleware to
endpoints.UsersRegister(api.Group("/users"))
//file.FilesRegister(api.Group("/files"))
//project.ProjectsRegister(api.Group("/projects"))
endpoints.SimulationsRegister(api.Group("/simulations"))
//model.ModelsRegister(api.Group("/simulations"))
endpoints.SimulatorsRegister(api.Group("/simulators"))
//visualization.VisualizationsRegister(api.Group("/visualizations"))
simulation.RegisterSimulationEndpoints(api.Group("/simulations"))
file.RegisterFileEndpoints(api.Group("/simulations"))
model.RegisterModelEndpoints(api.Group("/simulations"))
visualization.RegisterVisualizationEndpoints(api.Group("/simulations"))
widget.RegisterWidgetEndpoints(api.Group("/simulations"))
user.RegisterUserEndpointsForSimulation(api.Group("/simulations"))
user.RegisterUserEndpoints(api.Group("/users"))
simulator.RegisterSimulatorEndpoints(api.Group("/simulators"))
r.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))