diff --git a/pkg/util/xml.go b/pkg/util/xml.go index aa52ee9..9eb5392 100644 --- a/pkg/util/xml.go +++ b/pkg/util/xml.go @@ -3,6 +3,7 @@ package util import ( "encoding/xml" "slices" + "sort" "strings" ) @@ -36,6 +37,9 @@ func NewXMLConfiguration() *XMLConfiguration { func NewXMLConfigurationFromString(xmlData string) (*XMLConfiguration, error) { config := &XMLConfiguration{} + + xmlData = strings.TrimLeft(xmlData, " \t\n\r") + headerEnd := strings.Index(xmlData, "") if headerEnd != -1 { config.Header = xmlData[:headerEnd] @@ -62,7 +66,7 @@ func (x *XMLConfiguration) GetProperty(name string) (Property, bool) { return Property{}, false } -func (x *XMLConfiguration) AddProperty(p Property) { +func (x *XMLConfiguration) addProperty(p Property) { for i, existingProperty := range x.Configuration.Properties { if existingProperty.Name == p.Name { x.Configuration.Properties[i] = p // update @@ -72,14 +76,27 @@ func (x *XMLConfiguration) AddProperty(p Property) { x.Configuration.Properties = append(x.Configuration.Properties, p) // add } +func (x *XMLConfiguration) sort() { + sort.Slice(x.Configuration.Properties, func(i, j int) bool { + return x.Configuration.Properties[i].Name < x.Configuration.Properties[j].Name + }) +} + +func (x *XMLConfiguration) AddProperty(p Property) { + x.addProperty(p) + x.sort() +} + func (x *XMLConfiguration) AddPropertyWithString(name, value, description string) { x.AddProperty(Property{Name: name, Value: value, Description: description}) } func (x *XMLConfiguration) AddPropertiesWithMap(properties map[string]string) { for name, value := range properties { - x.AddProperty(Property{Name: name, Value: value}) + x.addProperty(Property{Name: name, Value: value}) } + + x.sort() } func (x *XMLConfiguration) DeleteProperties(names ...string) { @@ -102,6 +119,7 @@ func (x *XMLConfiguration) getHeader() string { } func (x *XMLConfiguration) Marshal() (string, error) { + x.sort() data, err := xml.MarshalIndent(x.Configuration, "", " ") if err != nil { return "", err diff --git a/pkg/util/xml_test.go b/pkg/util/xml_test.go index e3fc6eb..ec7a9b5 100644 --- a/pkg/util/xml_test.go +++ b/pkg/util/xml_test.go @@ -1,6 +1,8 @@ package util -import "testing" +import ( + "testing" +) func TestXMLConfiguration(t *testing.T) { xmlData := ` @@ -43,8 +45,7 @@ func TestXMLConfiguration(t *testing.T) { ` - expectedXMLData := ` - + expectedXMLData := ` + + hive.metastore.db.type + DERBY + Expects one of [derby, oracle, mysql, mssql, postgres]. Type of database used by the metastore. Information schema & JDBCStorageHandler depend on it. + hive.metastore.warehouse.dir /user/hive/warehouse @@ -76,11 +82,6 @@ func TestXMLConfiguration(t *testing.T) { For example, jdbc:postgresql://myhost/db?ssl=true for postgres database. - - hive.metastore.db.type - DERBY - Expects one of [derby, oracle, mysql, mssql, postgres]. Type of database used by the metastore. Information schema & JDBCStorageHandler depend on it. - ` @@ -269,6 +270,14 @@ func TestXMLConfiguration_AddProperty(t *testing.T) { if p.Value != "value1" { t.Errorf("Property 'property1' has incorrect value. Expected: value1, Got: %s", p.Value) } + + property.Value = "value2" + config.AddProperty(property) + + p, ok = config.GetProperty("property1") + if !ok { + t.Errorf("Expected property 'property1' not found") + } } func TestXMLConfiguration_DeleteProperties(t *testing.T) { @@ -323,3 +332,38 @@ func TestXMLConfiguration_Marshal(t *testing.T) { t.Errorf("Marshalled XML does not match expected XML. Expected:\n%s\nGot:\n%s", expectedXML, xmlData) } } + +func TestXMLConfiguration_Marshal_NoHeader(t *testing.T) { + xmlData := ` + + + property1 + value1 + + +` + + expectedXML := ` + + + + property1 + value1 + + +` + + config, err := NewXMLConfigurationFromString(xmlData) + if err != nil { + t.Errorf("Failed to create XML configuration from string: %v", err) + } + + xmlData, err = config.Marshal() + if err != nil { + t.Errorf("Failed to marshal XML configuration: %v", err) + } + + if xmlData != expectedXML { + t.Errorf("Marshalled XML does not match expected XML. Expected:\n%s\nGot:\n%s", expectedXML, xmlData) + } +}