diff --git a/models/mxgraph.go b/models/mxgraph.go index 7f227fc..71ce58f 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 { diff --git a/models/workflow.go b/models/workflow.go index b883a24..38f96ae 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 componant +// 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,6 +597,8 @@ 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 @@ -586,30 +611,33 @@ 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.mxCellToComponant(object.MxCell,ws) + if err != nil { + issues = append(issues, mxissues...) + } + returned_wf.UpdateObj(resObj,object.ID) + + // // retrieve the rType in the mxCell + // rType := w.getRtype(*object.MxCell.RID) + // // create a composant and add it to the appropriate list + // resObj := returned_wf.CreateResourceObject(rType) + // // use the addUserInput method with a map[string]string made of the + // resObj + + } + 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.mxCellToComponant(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": @@ -1005,9 +1033,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) mxCellToComponant(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 +// }