Add generic xml importer

Also, extract some common functionality to clients/lib and provide unittests.

Fixes issue #30
This commit is contained in:
Chris Masone
2015-07-13 14:15:52 -07:00
parent 8fe0c86e31
commit 6ca8bfad74
5 changed files with 158 additions and 37 deletions

View File

@@ -3,49 +3,14 @@ package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"github.com/attic-labs/noms/clients/lib"
"github.com/attic-labs/noms/datas"
"github.com/attic-labs/noms/dataset"
"github.com/attic-labs/noms/types"
)
func nomsValueFromObject(o interface{}) types.Value {
switch o := o.(type) {
case string:
return types.NewString(o)
case bool:
return types.Bool(o)
case float64:
return types.Float64(o)
case nil:
return nil
case []interface{}:
out := types.NewList()
for _, v := range o {
nv := nomsValueFromObject(v)
if nv != nil {
out = out.Append(nv)
}
}
return out
case map[string]interface{}:
out := types.NewMap()
for k, v := range o {
nv := nomsValueFromObject(v)
if nv != nil {
out = out.Set(types.NewString(k), nv)
}
}
return out
default:
fmt.Println(o, "is of a type I don't know how to handle")
}
return nil
}
func main() {
datasetDataStoreFlags := dataset.DatasetDataFlags()
flag.Parse()
@@ -77,7 +42,7 @@ func main() {
roots := ds.Roots()
value := nomsValueFromObject(jsonObject)
value := lib.NomsValueFromObject(jsonObject)
ds.Commit(datas.NewRootSet().Insert(
datas.NewRoot().SetParents(

44
clients/lib/lib.go Normal file
View File

@@ -0,0 +1,44 @@
package lib
import (
"fmt"
"github.com/attic-labs/noms/types"
)
// NomsValueFromObject takes a generic Go interface and recursively
// resolves the types within so that it can build up and return
// a Noms Value with the same structure.
func NomsValueFromObject(o interface{}) types.Value {
switch o := o.(type) {
case string:
return types.NewString(o)
case bool:
return types.Bool(o)
case float64:
return types.Float64(o)
case nil:
return nil
case []interface{}:
out := types.NewList()
for _, v := range o {
nv := NomsValueFromObject(v)
if nv != nil {
out = out.Append(nv)
}
}
return out
case map[string]interface{}:
out := types.NewMap()
for k, v := range o {
nv := NomsValueFromObject(v)
if nv != nil {
out = out.Set(types.NewString(k), nv)
}
}
return out
default:
fmt.Println(o, "is of a type I don't know how to handle")
}
return nil
}

50
clients/lib/lib_test.go Normal file
View File

@@ -0,0 +1,50 @@
package lib
import (
"testing"
"github.com/attic-labs/noms/types"
"github.com/stretchr/testify/suite"
)
func TestLibTestSuite(t *testing.T) {
suite.Run(t, &LibTestSuite{})
}
type LibTestSuite struct {
suite.Suite
}
func (suite *LibTestSuite) TestPrimitiveTypes() {
suite.EqualValues(types.NewString("expected"), NomsValueFromObject("expected"))
suite.EqualValues(types.Bool(false), NomsValueFromObject(false))
suite.EqualValues(types.Float64(1.7), NomsValueFromObject(1.7))
suite.False(NomsValueFromObject(1.7).Equals(types.Bool(true)))
}
func (suite *LibTestSuite) TestCompositeTypes() {
// [false true]
suite.EqualValues(
types.NewList().Append(types.Bool(false)).Append(types.Bool(true)),
NomsValueFromObject([]interface{}{false, true}))
// [[false true]]
suite.EqualValues(
types.NewList().Append(
types.NewList().Append(types.Bool(false)).Append(types.Bool(true))),
NomsValueFromObject([]interface{}{[]interface{}{false, true}}))
// {"string": "string",
// "list": [false true],
// "map": {"nested": "string"}
// }
m := types.NewMap(
types.NewString("string"), types.NewString("string"),
types.NewString("list"), types.NewList().Append(types.Bool(false)).Append(types.Bool(true)),
types.NewString("map"), types.NewMap(types.NewString("nested"), types.NewString("string")))
suite.EqualValues(m, NomsValueFromObject(map[string]interface{}{
"string": "string",
"list": []interface{}{false, true},
"map": map[string]interface{}{"nested": "string"},
}))
}

1
clients/xml_importer/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
xml_importer

View File

@@ -0,0 +1,61 @@
package main
import (
"flag"
"log"
"net/http"
"github.com/attic-labs/noms/clients/lib"
"github.com/attic-labs/noms/datas"
"github.com/attic-labs/noms/dataset"
"github.com/attic-labs/noms/types"
"github.com/clbanning/mxj"
)
func myNomsValueFromObject(o interface{}) types.Value {
switch o := o.(type) {
case mxj.Map:
return lib.NomsValueFromObject(o.Old())
default:
return lib.NomsValueFromObject(o)
}
}
func main() {
datasetDataStoreFlags := dataset.DatasetDataFlags()
flag.Parse()
ds := datasetDataStoreFlags.CreateStore()
if ds == nil {
flag.Usage()
return
}
url := flag.Arg(0)
if url == "" {
flag.Usage()
return
}
res, err := http.Get(url)
defer res.Body.Close()
if err != nil {
log.Fatalf("Error fetching %s: %+v\n", url, err)
} else if res.StatusCode != 200 {
log.Fatalf("Error fetching %s: %s\n", url, res.Status)
}
xmlObject, err := mxj.NewMapXmlReader(res.Body)
if err != nil {
log.Fatalln("Error decoding XML: ", err)
}
roots := ds.Roots()
value := myNomsValueFromObject(xmlObject)
ds.Commit(datas.NewRootSet().Insert(
datas.NewRoot().SetParents(
roots.NomsValue()).SetValue(
value)))
}