diff --git a/README.md b/README.md
index b626da2..b4771ab 100644
--- a/README.md
+++ b/README.md
@@ -63,4 +63,37 @@ This script should be updated to be ran from anywhere.
# More documentation
-[Visit the docs/ directory](/docs/)
\ No newline at end of file
+[Visit the docs/ directory](/docs/)
+
+## UML
+
+We are currently using [goplantuml](https://github.com/jfeliu007/goplantuml/) to generate the oject diagrams directly from the go files. This tools creates `.plums` files directly from the directory where the go files are located. These UML files can then be visualized using plantuml and the VS Code extensions plantuml.
+
+**Setting up the plantuml environment** :
+
+```
+# Downloading the go tool goplantuml
+go get github.com/jfeliu007/goplantuml/parser
+go install github.com/jfeliu007/goplantuml/cmd/goplantuml@latest
+
+# Install the plantuml environment
+sudo apt install default-jre
+sudo apt install plantuml
+
+```
+**Rich PlantUML extension Link**: https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml or search it in the marketplace panel of VS Code
+
+**Generate and view an UML diagram**
+
+```
+goplantuml path/to/code/directory > path/to/dest/file.puml
+```
+
+- open the .puml file generated
+- alt + d to have the extension preview the plantUML code
+- right click inside the .puml and select 'Export Current Diagram' to create an image file
+- the output will be generated in a `out/` directory in the current path
+
+### Note
+
+Only `.puml` files ought to be commited to the git repository, because their nature allows to track changes, while image file do not fit the purpose of versioning.
\ No newline at end of file
diff --git a/docs/UML/plantuml/diagram_object_controllers.puml b/docs/UML/plantuml/diagram_object_controllers.puml
new file mode 100644
index 0000000..1355311
--- /dev/null
+++ b/docs/UML/plantuml/diagram_object_controllers.puml
@@ -0,0 +1,77 @@
+@startuml
+namespace controllers {
+ class ComputingController << (S,Aquamarine) >> {
+ + GetOneComputing(ID string)
+ + PostComputing(body models.ComputingNEWModel)
+ + GetMultipleComputing(IDs []string)
+
+ }
+ class DataController << (S,Aquamarine) >> {
+ + GetOneData(ID string)
+ + GetMultipleData(IDs []string)
+ + PostData(body models.DataNEWModel)
+
+ }
+ class DatacenterController << (S,Aquamarine) >> {
+ + GetMultipleDatacenter(IDs []string)
+ + GetOneDatacenter(ID string)
+ + PostDatacenter(body models.DatacenterNEWModel)
+
+ }
+ class ScheduleController << (S,Aquamarine) >> {
+ + CreateSchedule(dcName string, workflowName string, cron string, duration uint, startDate time.Time, stopDate time.Time, requirements models.ExecutionRequirementsModel)
+ + CheckSchedule(cron string, duration uint, startDate time.Time, stopDate time.Time, requirements models.ExecutionRequirementsModel)
+ + GetSchedules(startDate time.Time, stopDate time.Time)
+ + GetNextSchedules(baseDate time.Time)
+ + GetPreviousSchedules(baseDate time.Time)
+
+ }
+ class SearchController << (S,Aquamarine) >> {
+ + FindByWord(word string)
+
+ }
+ class StorageController << (S,Aquamarine) >> {
+ + GetOneStorage(ID string)
+ + GetMultipleStorage(IDs []string)
+ + PostStorage(body models.StorageNEWModel)
+
+ }
+ class UserController << (S,Aquamarine) >> {
+ + Login()
+ + Logout()
+
+ }
+ class WorkflowController << (S,Aquamarine) >> {
+ + CreateWorkflow(workflowName string)
+ + ListWorkflows()
+ + GetWorkflow(workflowName string)
+ + AddElementWorkflow(workflowName string, rID string)
+ + MxGraphParser(workflowName string, xmlData string)
+ + MxGraphParserConsume(workflowName string)
+ + LinkElementsWorkflow(workflowName string, rObjIDsource string, rObjIDtarger string, isInput bool)
+ + GetWorkflowSchedule(workflowName string)
+ + SetWorkflowSchedule(workflowName string, cronString string, events string, isService bool, startDate time.Time, stopDate time.Time, duration uint)
+ + CheckWorkflowSchedule(workflowName string)
+ + BookWorkflowSchedule(workflowName string)
+
+ }
+ class WorkspaceController << (S,Aquamarine) >> {
+ + AddModel(id string, rtype string)
+ + ListWorkspace()
+ + ListWorkspaceModel()
+ + DeleteElement(id string, rtype string)
+
+ }
+}
+"web.Controller" *-- "controllers.ComputingController"
+"web.Controller" *-- "controllers.DataController"
+"web.Controller" *-- "controllers.DatacenterController"
+"web.Controller" *-- "controllers.ScheduleController"
+"web.Controller" *-- "controllers.SearchController"
+"web.Controller" *-- "controllers.StorageController"
+"web.Controller" *-- "controllers.UserController"
+"web.Controller" *-- "controllers.WorkflowController"
+"web.Controller" *-- "controllers.WorkspaceController"
+
+
+@enduml
diff --git a/docs/UML/plantuml/diagram_object_models.puml b/docs/UML/plantuml/diagram_object_models.puml
new file mode 100644
index 0000000..983ac5b
--- /dev/null
+++ b/docs/UML/plantuml/diagram_object_models.puml
@@ -0,0 +1,347 @@
+@startuml
+namespace models {
+ class ComputingModel << (S,Aquamarine) >> {
+ + ID string
+
+ - getRtype() rtype.Rtype
+ - getName() string
+
+ + AddUserInput(inputs map[string]interface{})
+
+ }
+ class ComputingNEWModel << (S,Aquamarine) >> {
+ + Name string
+ + Description string
+ + ShortDescription string
+ + Logo string
+ + Type string
+ + Owner string
+ + License string
+ + Price uint
+ + ExecutionRequirements ExecutionRequirementsModel
+ + Dinputs []string
+ + Doutputs []string
+ + Image string
+ + Command string
+ + Arguments []string
+ + Environment []string
+ + Ports []string
+
+ }
+ class ComputingObject << (S,Aquamarine) >> {
+ + ReferenceID primitive.ObjectID
+ + Inputs []string
+ + Outputs []string
+ + DataCenterID string
+
+ - getHost() *string
+ - setReference(rID primitive.ObjectID)
+ - getReference() primitive.ObjectID
+ - getRtype() rtype.Rtype
+ - getModel() (ResourceModel, error)
+ - getName() *string
+ - isLinked(rObjID string) LinkingState
+ - addLink(direction LinkingState, rID string)
+
+ }
+ class DCstatus << (S,Aquamarine) >> {
+ + DCname string
+ + DCobjID string
+ + IsReachable bool
+ + IsAvailable bool
+ + Booked *ScheduleInfo
+ + ErrorMessage string
+
+ }
+ class DataIO << (S,Aquamarine) >> {
+ + Counter uint
+
+ }
+ class DataModel << (S,Aquamarine) >> {
+ + ID string
+
+ - getRtype() rtype.Rtype
+ - getName() string
+
+ }
+ class DataNEWModel << (S,Aquamarine) >> {
+ + Name string
+ + Description string
+ + ShortDescription string
+ + Logo string
+ + Dtype string
+ + Type string
+ + Example string
+ + Protocol []string
+ + Location string
+
+ }
+ class DataObject << (S,Aquamarine) >> {
+ + ReferenceID primitive.ObjectID
+
+ - getHost() *string
+ - getModel() (ResourceModel, error)
+ - setReference(rID primitive.ObjectID)
+ - getReference() primitive.ObjectID
+ - getRtype() rtype.Rtype
+ - getName() *string
+ - isLinked(rID string) LinkingState
+ - addLink(direction LinkingState, rObjID string)
+
+ }
+ class DatacenterCpuModel << (S,Aquamarine) >> {
+ + Cores uint
+ + Architecture string
+ + Shared bool
+ + MinimumMemory uint
+ + Platform string
+
+ }
+ class DatacenterGpuModel << (S,Aquamarine) >> {
+ + CudaCores uint
+ + Model string
+ + Memory uint
+ + TensorCores uint
+
+ }
+ class DatacenterMemoryModel << (S,Aquamarine) >> {
+ + Size uint
+ + Ecc bool
+
+ }
+ class DatacenterModel << (S,Aquamarine) >> {
+ + ID string
+
+ - getRtype() rtype.Rtype
+ - getName() string
+
+ + GetTotalCPUs() uint
+ + GetTotalGPUs() uint
+ + GetTotalRAM() uint
+
+ }
+ class DatacenterNEWModel << (S,Aquamarine) >> {
+ + Name string
+ + Type string
+ + Acronym string
+ + Hosts []string
+ + Description string
+ + ShortDescription string
+ + Logo string
+ + CPU DatacenterCpuModel
+ + RAM DatacenterMemoryModel
+ + GPU []DatacenterGpuModel
+ + Owner string
+ + BookingPrice int
+
+ }
+ class DatacenterObject << (S,Aquamarine) >> {
+ + ReferenceID primitive.ObjectID
+
+ - setReference(rID primitive.ObjectID)
+ - getModel() (ResourceModel, error)
+ - getReference() primitive.ObjectID
+ - getHost() *string
+ - getRtype() rtype.Rtype
+ - getName() *string
+ - isLinked(rID string) LinkingState
+ - addLink(direction LinkingState, rObjID string)
+
+ }
+ class ExecutionRequirementsModel << (S,Aquamarine) >> {
+ + CPUs uint
+ + GPUs uint
+ + RAM uint
+ + Parallel bool
+ + ScalingModel uint
+ + DiskIO string
+
+ }
+ class MxCell << (S,Aquamarine) >> {
+ + XMLName xml.Name
+ + ID string
+ + Parent *string
+ + RID *string
+ + Source *string
+ + Target *string
+
+ }
+ class MxGraphModel << (S,Aquamarine) >> {
+ + XMLName xml.Name
+ + Root struct{xml.Name, []MxCell, *[]Object}
+
+ }
+ class Object << (S,Aquamarine) >> {
+ + XMLName xml.Name
+ + ID string
+ + Command *string
+ + Args *string
+ + Env *string
+ + MxCell MxCell
+
+ }
+ class RepositoryModel << (S,Aquamarine) >> {
+ + Credentials string
+ + Url string
+
+ }
+ interface ResourceModel {
+ - getRtype() rtype.Rtype
+ - getName() string
+
+ }
+ interface ResourceObject {
+ - getHost() *string
+ - getName() *string
+ - getModel() (ResourceModel, error)
+ - getRtype() rtype.Rtype
+ - setReference(rObjID primitive.ObjectID)
+ - getReference() primitive.ObjectID
+ - isLinked(rObjID string) LinkingState
+ - addLink(direction LinkingState, rObjID string)
+
+ }
+ class ScheduleDB << (S,Aquamarine) >> {
+ + StartDate time.Time
+ + StopDate time.Time
+ + Workflow string
+ + ResourceQty ExecutionRequirementsModel
+
+ }
+ class ScheduleInfo << (S,Aquamarine) >> {
+ + Total int
+ + NextExecutions []string
+
+ }
+ class SearchResult << (S,Aquamarine) >> {
+ + Computing []ComputingModel
+ + Datacenter []DatacenterModel
+ + Storage []StorageModel
+ + Data []DataModel
+
+ }
+ class StorageModel << (S,Aquamarine) >> {
+ + ID string
+
+ - getRtype() rtype.Rtype
+ - getName() string
+
+ + AddUserInput(inputs map[string]interface{})
+
+ }
+ class StorageNEWModel << (S,Aquamarine) >> {
+ + Name string
+ + Description string
+ + ShortDescription string
+ + Logo string
+ + Type string
+ + DCacronym string
+ + URL string
+ + Size uint
+ + Encryption bool
+ + Redundancy string
+ + Throughput string
+ + BookingPrice uint
+
+ }
+ class StorageObject << (S,Aquamarine) >> {
+ + ReferenceID primitive.ObjectID
+ + Inputs []string
+ + Outputs []string
+
+ - getHost() *string
+ - getModel() (ResourceModel, error)
+ - setReference(rID primitive.ObjectID)
+ - getReference() primitive.ObjectID
+ - getRtype() rtype.Rtype
+ - getName() *string
+ - isLinked(rObjID string) LinkingState
+ - addLink(direction LinkingState, rObjID string)
+
+ }
+ class UserModel << (S,Aquamarine) >> {
+ + ID string
+ + Username string
+ + Password string
+ + Email string
+
+ }
+ class Workflow << (S,Aquamarine) >> {
+ + Data map[string]DataObject
+ + Computing map[string]ComputingObject
+ + Storage map[string]StorageObject
+ + Datacenter map[string]DatacenterObject
+ + Schedules WorkflowSchedule
+ + MxgraphXML string
+
+ + GetExecutionRequirements(dcIDobj string) (ExecutionRequirementsModel, error)
+ + GetResource(rObjID *string) ResourceObject
+ + GetResourceMapByRtype(rt rtype.Rtype) interface{}
+ + CreateResourceObject(rt rtype.Rtype) ResourceObject
+ + AddObj(robj ResourceObject) *primitive.ObjectID
+ + UpdateDB(userID string, workflowName string) error
+ + UpdateObj(robj ResourceObject, objID string)
+
+ }
+ class WorkflowSchedule << (S,Aquamarine) >> {
+ + IsService bool
+ + StartDate time.Time
+ + StopDate time.Time
+ + Cron string
+ + Duration uint
+ + Events string
+ + IsBooked bool
+
+ }
+ class Workspace << (S,Aquamarine) >> {
+ + UserID string
+ + Workflows map[string]Workflow
+ + Data []string
+ + Computing []string
+ + Datacenter []string
+ + Storage []string
+
+ - getRtype(rID string) rtype.Rtype
+ - updateDB() error
+
+ + ConsumeMxGraphModel(xmlmodel MxGraphModel) (*Workflow, error, []error)
+ + GetResources() map[rtype.Rtype][]string
+ + GetWorkflow(workflowName string) *Workflow
+ + GetWorkflows() []string
+ + NewResource(rID string, rType string) error
+ + GetAllWorkspacesProjects() chan *Workflow
+
+ }
+ class WorkspaceModel << (S,Aquamarine) >> {
+ + UserID string
+ + Data []DataModel
+ + Computing []ComputingModel
+ + Datacenter []DatacenterModel
+ + Storage []StorageModel
+
+ }
+ class models.LinkingState << (T, #FF7700) >> {
+ }
+ class mxissue << (S,Aquamarine) >> {
+ - msg string
+
+ + Error() string
+
+ }
+}
+"models.ComputingNEWModel" *-- "models.ComputingModel"
+"models.DataNEWModel" *-- "models.DataModel"
+"models.DatacenterNEWModel" *-- "models.DatacenterModel"
+"models.StorageNEWModel" *-- "models.StorageModel"
+
+"models.ResourceModel" <|-- "models.ComputingModel"
+"models.ResourceObject" <|-- "models.ComputingObject"
+"models.ResourceModel" <|-- "models.DataModel"
+"models.ResourceObject" <|-- "models.DataObject"
+"models.ResourceModel" <|-- "models.DatacenterModel"
+"models.ResourceObject" <|-- "models.DatacenterObject"
+"models.ResourceModel" <|-- "models.StorageModel"
+"models.ResourceObject" <|-- "models.StorageObject"
+
+"__builtin__.uint" #.. "models.LinkingState"
+@enduml
diff --git a/models/computing.go b/models/computing.go
index c0f539a..7a50246 100644
--- a/models/computing.go
+++ b/models/computing.go
@@ -1,11 +1,13 @@
package models
import (
+ "encoding/xml"
"fmt"
"strings"
"cloud.o-forge.io/core/oc-catalog/models/rtype"
"cloud.o-forge.io/core/oc-catalog/services"
+ structtomap "github.com/Klathmon/StructToMap"
"github.com/beego/beego/v2/core/logs"
"go.mongodb.org/mongo-driver/bson/primitive"
)
@@ -35,7 +37,7 @@ type ComputingNEWModel struct {
ShortDescription string `json:"short_description,omitempty" required:"true" validate:"required"`
Logo string `json:"logo,omitempty" required:"true" validate:"required"`
- // Type string `json:"type,omitempty" required:"true"`
+ Type string `json:"type,omitempty" required:"true"`
Owner string `json:"owner,omitempty"`
License string `json:"license,omitempty"`
Price uint `json:"price,omitempty"`
@@ -49,7 +51,7 @@ type ComputingNEWModel struct {
Command string `json:"command,omitempty"`
Arguments []string `json:"arguments,omitempty"`
Environment []string `json:"environment,omitempty"`
- // Ports []string `json:"ports,omitempty"`
+ Ports []string `json:"ports,omitempty"`
// CustomDeployment string `json:"custom_deployment,omitempty"`
@@ -77,6 +79,11 @@ type ComputingObject struct {
Inputs []string `json:"inputs"`
Outputs []string `json:"outputs"`
+ Image string `json:"image,omitempty"`
+ Command string `json:"command,omitempty"`
+ Arguments []string `json:"arguments,omitempty"`
+ Environment []string `json:"environment,omitempty"`
+ Ports []string `json:"ports,omitempty"`
DataCenterID string `json:"datacenterID" description:"Datacenter where the computing will be executed"`
}
@@ -174,19 +181,45 @@ func PostOneComputing(obj ComputingNEWModel) (ID string, err error) {
return postOneResource(obj, rtype.COMPUTING)
}
-func (obj ComputingModel) AddUserInput(inputs map[string]interface{} ){
+func (obj *ComputingObject) AddUserInput(inputs []xml.Attr){
+
+ logs.Alert("AddUserInput() is going to throw some alerts while mxGraph GUI is not updated to adapt the inputs to the componant")
+
// So far only a few input to handle so a switch with a case for each type of attribute
// is enough, to prevent too much complexity
- for key, value := range inputs {
- switch strings.ToLower(key) {
+
+ for _, j := range(inputs){
+ setting, _ := structtomap.Convert(j)
+ // fmt.Println(strings.ToLower(setting["Name"]))
+ name := setting["Name"].(xml.Name).Local
+ value := setting["Value"]
+ switch name {
case "command":
obj.Command = value.(string)
- case "arguments":
- obj.Arguments = value.([]string)
+ case "args":
+ empty, sliced_arguments := getSliceSettings(value.(string))
+ if (!empty){
+ obj.Arguments = sliced_arguments
+ }
case "env" :
- obj.Environment = value.([]string)
+ empty, sliced_arguments := getSliceSettings(value.(string))
+ if (!empty){
+ obj.Environment = sliced_arguments
+ }
default:
- logs.Alert(fmt.Printf("%s is not an attribute of storage componants", key))
+ logs.Alert(fmt.Printf("%s is not an attribute of computing componants", name))
}
+
}
+
+
+}
+
+func getSliceSettings(string_to_parse string)(empty bool, sliced_string []string){
+ if len(string_to_parse) == 0 {
+ return true, nil
+ }
+ empty = false
+ sliced_string = strings.Split(string_to_parse," ")
+ return
}
\ No newline at end of file
diff --git a/models/data.go b/models/data.go
index d812d83..6efefa9 100644
--- a/models/data.go
+++ b/models/data.go
@@ -22,19 +22,6 @@ type DataNEWModel struct {
Location string `json:"location" required:"true" validate:"required"`
}
-type DataModel struct {
- ID string `json:"ID" bson:"_id" required:"true" validate:"required"`
- DataNEWModel `bson:",inline"`
-}
-
-func (obj DataModel) getRtype() rtype.Rtype {
- return rtype.DATA
-}
-
-func (model DataModel) getName() string {
- return model.Name
-}
-
type DataIO struct {
Counter uint `description:"Incremental number starting from 0"`
}
@@ -43,6 +30,18 @@ type DataObject struct {
ReferenceID primitive.ObjectID `json:"referenceID" description:"Data model ID"`
}
+type DataModel struct {
+ ID string `json:"ID" bson:"_id" required:"true" validate:"required"`
+ DataNEWModel `bson:",inline"`
+}
+
+func (obj DataModel) getRtype() rtype.Rtype {
+ return rtype.DATA
+}
+
+func (model DataModel) getName() string {
+ return model.Name
+}
func (obj DataObject) getHost() *string {
return nil // Host is DC only attribute
}
diff --git a/models/mxgraph.go b/models/mxgraph.go
index 7f227fc..fec9773 100644
--- a/models/mxgraph.go
+++ b/models/mxgraph.go
@@ -8,8 +8,9 @@ type MxGraphModel struct {
XMLName xml.Name `xml:"mxGraphModel"`
Root struct {
- XMLName xml.Name `xml:"root"`
- MxCell []MxCell `xml:"mxCell"`
+ XMLName xml.Name `xml:"root"`
+ MxCell []MxCell `xml:"mxCell"`
+ MxObject *[]MxObject `xml:"object"`
}
}
@@ -20,6 +21,15 @@ type MxCell struct {
RID *string `xml:"rID,attr"`
Source *string `xml:"source,attr"`
Target *string `xml:"target,attr"`
+ Rtype *string `xml:"rType,attr"`
+}
+
+
+type MxObject struct {
+ XMLName xml.Name `xml:"object"`
+ ID string `xml:"id,attr"`
+ Settings []xml.Attr `xml:",any,attr"`
+ MxCell MxCell `xml:"mxCell"`
}
type mxissue struct {
@@ -33,3 +43,4 @@ func (m *mxissue) Error() string {
func newMxIssue(message string) error {
return &mxissue{message}
}
+
diff --git a/models/workflow.go b/models/workflow.go
index b883a24..f8bb70e 100644
--- a/models/workflow.go
+++ b/models/workflow.go
@@ -4,6 +4,8 @@ import (
"context"
"encoding/xml"
"errors"
+ "net/url"
+ "os"
"sort"
"time"
@@ -71,18 +73,25 @@ type ResourceObject interface {
addLink(direction LinkingState, rObjID string)
}
+// This type allows to process computing and storage component
+// which can get input from the user
+type EditableResourceObject interface{
+ ResourceObject
+ addUserInput(map[string]interface{})
+}
+
// Get a sum of all execution requirements attached to a DC obj
-func (w Workflow) GetExecutionRequirements(dcIDobj string) (ret ExecutionRequirementsModel, err error) {
+func (wf Workflow) GetExecutionRequirements(dcIDobj string) (ret ExecutionRequirementsModel, err error) {
// Find the id of the DC obj
- if _, ok := w.Datacenter[dcIDobj]; !ok {
+ if _, ok := wf.Datacenter[dcIDobj]; !ok {
return ExecutionRequirementsModel{}, errors.New("DC obj" + dcIDobj + " doesn't exist in the Workflow")
}
// Get all elements that are attached to the DC
- for _, computingObj := range w.Computing {
+ for _, computingObj := range wf.Computing {
if computingObj.DataCenterID == dcIDobj {
mymodel, err := computingObj.getModel()
if err != nil {
@@ -159,6 +168,7 @@ func (w *Workflow) CreateResourceObject(rt rtype.Rtype) ResourceObject {
default:
res = nil
}
+
return res
}
@@ -510,6 +520,14 @@ func ParseMxGraph(username, workflowName, xmlData string) (err error, mxissues [
//return errors.New("Can't modify a booked workflow"), nil
}
+ decodedValue, err := url.QueryUnescape(xmlData)
+ if err != nil {
+ return err, nil
+ }
+
+ // TEMPORARY test the xml created
+ os.WriteFile("graph.xml", []byte(decodedValue), 0660)
+
var xmlModel MxGraphModel
// logs.Debug(xmlData)
@@ -518,13 +536,17 @@ func ParseMxGraph(username, workflowName, xmlData string) (err error, mxissues [
return err, nil
}
+ // Move the attribute of the object's tags into the mxCell's for an easier processing
+
+ // currentWorkflow.extractMxCell(xmlModel)
+
targetWorkspaceWorkflow, err, mxissues := userWorkspace.ConsumeMxGraphModel(xmlModel)
if err != nil {
return err, nil
}
targetWorkspaceWorkflow.MxgraphXML = xmlData
- targetWorkspaceWorkflow.Schedules = currentWorkflow.Schedules //TODO: Probably we should move schudles outside the workflow
+ targetWorkspaceWorkflow.Schedules = currentWorkflow.Schedules //TODO: Probably we should move schedules outside the workflow
_, err = services.MngoCollWorkspace.UpdateOne(services.MngoCtx,
primitive.M{"_id": username},
@@ -564,7 +586,8 @@ func FindSliceInSlice(slice1 []string, slice2 []string) (int, int, bool) {
return -1, -1, false
}
-func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Workflow, err error, issues []error) {
+// TODO : correct this method to suppport mxcells with settings
+func (ws Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Workflow, err error, issues []error) {
returned_wf = &Workflow{}
@@ -574,11 +597,13 @@ func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Work
return xmlmodel.Root.MxCell[i].RID != nil
})
+
+
// For each cell of the xml graph,
- // in the case cell has a rID retrieve its rType from the value of rID of the componant in the worfklow
- // retrieve the componant's type
+ // in the case cell has a rID retrieve its rType from the value of rID of the component in the worfklow
+ // retrieve the component's type
// create an object from the rType
- // update the existing workflow with the new componant
+ // update the existing workflow with the new component
// or by defautlt : the cell represents an arrow
// if the source or the target of the arrow is a datacenter
// define which end of the arrow is the DC
@@ -586,30 +611,39 @@ func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Work
// create a computing object
// attach the DC to it
// update the workflow with the object : create the list of this type of component or update the list with the id of the component with the object
+
+ for _, object := range *xmlmodel.Root.MxObject{
+
+ resObj, err, mxissues := returned_wf.mxCellToComponent(object.MxCell,ws)
+ if err != nil {
+ issues = append(issues, mxissues...)
+ }
+
+ // add the component to the worflow's attribute that stores
+ // all components in a map[string]Component where the key
+ // is the component's ID in the mxGraph and the value the Component object
+ returned_wf.UpdateObj(resObj,object.ID)
+
+ // Construct the object corresponding to the componant's type and use its addUserInput method
+ if(resObj.getRtype() == rtype.COMPUTING){
+ comp_obj := returned_wf.GetResource(&object.ID).(*ComputingObject)
+ comp_obj.AddUserInput(object.Settings)
+ returned_wf.UpdateObj(comp_obj,object.ID)
+ }
+ // if(resObj.getRtype() == rtype.DATA){
+ // }
+
+ }
+
for _, cell := range xmlmodel.Root.MxCell {
switch {
case cell.RID != nil:
- // Case of a Resource
- rType := w.getRtype(*cell.RID)
-
- if rType == rtype.INVALID {
- return nil,
- errors.New("Refering to a rID that is not in the workflow"),
- nil
- }
-
- // Generate ObjectID for the reference ID
- rIDObj, err := primitive.ObjectIDFromHex(*cell.RID)
+ resObj, err, mxissues := returned_wf.mxCellToComponent(cell,ws)
if err != nil {
- return nil,
- errors.New("Bad ID format: " + *cell.RID),
- nil
+ issues = append(issues, mxissues...)
}
- resObj := returned_wf.CreateResourceObject(rType)
- resObj.setReference(rIDObj)
-
returned_wf.UpdateObj(resObj, cell.ID)
case cell.ID == "0" || cell.ID == "1":
@@ -677,7 +711,7 @@ func (w Workspace) ConsumeMxGraphModel(xmlmodel MxGraphModel) (returned_wf *Work
// datalist := make(map[string]bool)
- // Test wether the computing componants are linked with a DC
+ // Test wether the computing components are linked with a DC
for _, comp := range returned_wf.Computing {
if comp.DataCenterID == "" {
issues = append(issues, errors.New("Computing "+*comp.getName()+" without a Datacenter"))
@@ -1005,9 +1039,49 @@ func CheckAndBookWorkflowSchedule(username, workflowName string, book bool) (myR
SchedulesDB: ¤tWorkflow.Schedules}},
)
- if err != nil {
+ if err != nil {
logs.Critical("Internal error when updating in DB: " + err.Error())
}
return myRet, nil
}
+
+// Not sure if this method handles error propagation well
+func (wf Workflow) mxCellToComponent(cell MxCell, ws Workspace) (resObj ResourceObject,err error, issues []error){
+ rType := ws.getRtype(*cell.RID)
+
+ if rType == rtype.INVALID {
+ return nil,
+ errors.New("Refering to a rID that is not in the workflow"),
+ nil
+ }
+
+ // Generate ObjectID for the reference ID
+ rIDObj, err := primitive.ObjectIDFromHex(*cell.RID)
+ if err != nil {
+ return nil,
+ errors.New("Bad ID format: " + *cell.RID),
+ nil
+ }
+
+ resObj = wf.CreateResourceObject(rType)
+ resObj.setReference(rIDObj)
+
+ return
+}
+
+// func (ws Workspace) extractMxCell(xmlModel MxGraphModel){
+// // Iterate through all objects of the MxGraph
+// graphObjects := xmlModel.Root.MxObject
+// for _, object := range(*graphObjects){
+// current_obj_id, _ := strconv.Atoi(object.ID)
+// inside_cell_id := strconv.Itoa(current_obj_id + 1)
+
+// cell := ws.GetResource(&inside_cell_id)
+// // component := w.GetResource(cell.RID)
+// fmt.Print(cell)
+// }
+// // Extract the mxCell object
+// // Invoke the addParameter method from the component
+// // Edit the ID to get the object's one
+// }