in internal/pkg/core/deployers/types/api.go [50:123]
func (api *API) Unmarshal(xmlData string, position artifacts.Position) (artifacts.API, error) {
decoder := xml.NewDecoder(strings.NewReader(xmlData))
newAPI := artifacts.API{}
newAPI.Position = position
for {
token, err := decoder.Token()
if err != nil {
break
}
switch elem := token.(type) {
case xml.StartElement:
switch elem.Name.Local {
case "api":
for _, attr := range elem.Attr {
switch attr.Name.Local {
case "context":
newAPI.Context = attr.Value
case "name":
newAPI.Name = attr.Value
newAPI.Position.Hierarchy = attr.Value
case "version":
newAPI.Version = attr.Value
case "version-type":
newAPI.VersionType = attr.Value
}
}
case "resource":
var resource = Resource{}
res, err := resource.Unmarshal(decoder, elem, newAPI.Position)
if err != nil {
return artifacts.API{}, err
}
newAPI.Resources = append(newAPI.Resources, res)
default:
// Skip unknown elements
if err := decoder.Skip(); err != nil {
return artifacts.API{}, err
}
}
case xml.EndElement:
// Stop when the </api> tag is encountered
break
}
}
// Validation checks
if newAPI.Context == "" {
return artifacts.API{}, fmt.Errorf("API context is required")
}
// Check that context starts with '/'
if newAPI.Context == "" || newAPI.Context[0] != '/' {
return artifacts.API{}, fmt.Errorf("API context must begin with '/' character")
}
if newAPI.Name == "" {
return artifacts.API{}, fmt.Errorf("API name is required")
}
// Check version and versionType consistency
hasVersion := newAPI.Version != ""
hasVersionType := newAPI.VersionType != ""
if hasVersion != hasVersionType {
return artifacts.API{}, fmt.Errorf("both version and version-type must be specified together")
}
// Validate versionType if specified
if hasVersionType && newAPI.VersionType != "context" && newAPI.VersionType != "url" {
return artifacts.API{}, fmt.Errorf("version-type must be either 'context' or 'url', got: %s", newAPI.VersionType)
}
return newAPI, nil
}