func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Provide a tidal templating\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Usage:\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, " %s [options] [templates ....]\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "General Options:\n") fmt.Fprintf(os.Stderr, "\n") flag.PrintDefaults() } var base string flag.StringVar(&base, "base", "../..", "base of delta files on disk") var header string flag.StringVar(&header, "header", "", "output header before proccessing any templates") var footer string flag.StringVar(&footer, "footer", "", "output footer after all templates have been proccessed") flag.Parse() db, err := metadb.NewMetaDB(base) if err != nil { fmt.Fprintf(os.Stderr, "problem loading meta db %s: %v\n", base, err) os.Exit(1) } tides := make(map[string]Tide) gauges, err := db.Gauges() if err != nil { fmt.Fprintf(os.Stderr, "problem loading gauges from db %s: %v\n", base, err) os.Exit(1) } for _, gauge := range gauges { station, err := db.Station(gauge.Code) if err != nil { fmt.Fprintf(os.Stderr, "problem loading stations from db %s [%s]: %v\n", base, gauge.Code, err) os.Exit(1) } constituents, err := db.Constituents(gauge.Code) if err != nil { fmt.Fprintf(os.Stderr, "problem loading constituents from db %s [%s]: %v\n", base, gauge.Code, err) os.Exit(1) } sites, err := db.Sites(gauge.Code) if err != nil { fmt.Fprintf(os.Stderr, "problem loading sites from db %s [%s]: %v\n", base, gauge.Code, err) os.Exit(1) } installs := make(map[string][]Install) for _, site := range sites { sensors, err := db.InstalledSensors(gauge.Code, site.Location) if err != nil { fmt.Fprintf(os.Stderr, "problem loading sensors from db %s [%s]: %v\n", base, gauge.Code, err) os.Exit(1) } for _, sensor := range sensors { connections, err := db.Connections(gauge.Code, site.Location) if err != nil { fmt.Fprintf(os.Stderr, "problem loading connections from db %s [%s]: %v\n", base, gauge.Code, err) os.Exit(1) } for _, connection := range connections { if connection.Start.After(sensor.End) { continue } if connection.End.Before(sensor.Start) { continue } dataloggers, err := db.DeployedDataloggers(connection.Place, connection.Role) if err != nil { fmt.Fprintf(os.Stderr, "problem loading connections from db %s [%s]: %v\n", base, gauge.Code, err) os.Exit(1) } for _, datalogger := range dataloggers { if connection.Start.After(datalogger.End) { continue } if connection.End.Before(datalogger.Start) { continue } if _, ok := installs[site.Location]; !ok { installs[site.Location] = []Install{} } installs[site.Location] = append(installs[site.Location], Install{ Sensor: sensor, Datalogger: datalogger, Start: func() time.Time { if sensor.Start.After(datalogger.Start) { return sensor.Start } return datalogger.Start }(), End: func() time.Time { if sensor.End.Before(datalogger.End) { return sensor.End } return datalogger.End }(), }) } } } } tides[gauge.Code] = Tide{ Gauge: gauge, Station: station, Constituents: constituents, Installs: installs, } } if header != "" { fmt.Fprintln(os.Stdout, header) } for _, t := range flag.Args() { conf, err := ioutil.ReadFile(t) if err != nil { fmt.Fprintf(os.Stderr, "problem reading template file %s: %v\n", t, err) os.Exit(1) } tmpl, err := template.New("config").Funcs( template.FuncMap{ "add": func(a, b float64) float64 { return a + b }, "sub": func(a, b float64) float64 { return a - b }, "mult": func(a, b float64) float64 { return a * b }, "div": func(a, b float64) float64 { if b != 0.0 { return a / b } return 0.0 }, "lower": func(str string) string { return strings.ToLower(str) }, "upper": func(str string) string { return strings.ToUpper(str) }, "now": func() time.Time { return time.Now() }, "before": func(a, b time.Time) bool { return a.Before(b) }, "after": func(a, b time.Time) bool { return a.After(b) }, "dict": func(values ...interface{}) (map[string]interface{}, error) { if len(values)%2 != 0 { return nil, fmt.Errorf("invalid dict call") } dict := make(map[string]interface{}, len(values)/2) for i := 0; i < len(values); i += 2 { key, ok := values[i].(string) if !ok { return nil, fmt.Errorf("dict keys must be strings") } dict[key] = values[i+1] } return dict, nil }, "array": func(values ...interface{}) []interface{} { var array []interface{} for i := 0; i < len(values); i++ { array = append(array, values[i]) } return array }, }, ).Parse(string(conf)) if err != nil { fmt.Fprintf(os.Stderr, "problem compiling template: %v\n", err) os.Exit(1) } var res bytes.Buffer if err := tmpl.Execute(&res, tides); err != nil { fmt.Fprintf(os.Stderr, "problem parsing template: %v\n", err) os.Exit(1) } fmt.Fprintln(os.Stdout, res.String()) } if footer != "" { fmt.Fprintln(os.Stdout, footer) } }
func main() { var source string flag.StringVar(&source, "source", "GeoNet", "stationxml source") var sender string flag.StringVar(&sender, "sender", "WEL(GNS_Test)", "stationxml sender") var module string flag.StringVar(&module, "module", "Delta", "stationxml module") var output string flag.StringVar(&output, "output", "-", "output xml file") var base string flag.StringVar(&base, "base", "../..", "base of delta files on disk") var network string flag.StringVar(&network, "network", "../../network", "base network directory") var install string flag.StringVar(&install, "install", "../../install", "base installs directory") var stationRegexp string flag.StringVar(&stationRegexp, "stations", "[A-Z0-9]+", "regex selection of stations") var stationList string flag.StringVar(&stationList, "station-list", "", "regex selection of stations from file") var channelRegexp string flag.StringVar(&channelRegexp, "channels", "[A-Z0-9]+", "regex selection of channels") var channelList string flag.StringVar(&channelList, "channel-list", "", "regex selection of channels from file") var networkRegexp string flag.StringVar(&networkRegexp, "networks", "[A-Z0-9]+", "regex selection of networks") var networkList string flag.StringVar(&networkList, "network-list", "", "regex selection of networks from file") flag.Usage = func() { fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Build a network StationXML file from delta meta & response information\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Usage:\n") fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, " %s [options]\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "Options:\n") fmt.Fprintf(os.Stderr, "\n") flag.PrintDefaults() fmt.Fprintf(os.Stderr, "\n") } flag.Parse() // load delta meta helper db, err := metadb.NewMetaDB(base) if err != nil { fmt.Fprintf(os.Stderr, "problem loading meta db %s: %v\n", base, err) os.Exit(1) } builder := Build{ Networks: func() *regexp.Regexp { re, err := Matcher(networkList, networkRegexp) if err != nil { log.Fatalf("unable to compile network matcher: %v", err) } return re }(), Stations: func() *regexp.Regexp { re, err := Matcher(stationList, stationRegexp) if err != nil { log.Fatalf("unable to compile network matcher: %v", err) } return re }(), Channels: func() *regexp.Regexp { re, err := Matcher(channelList, channelRegexp) if err != nil { log.Fatalf("unable to compile network matcher: %v", err) } return re }(), } // build a representation of the network networks, err := builder.Construct(db) if err != nil { log.Fatalf("error: unable to build networks list: %v", err) } // render station xml root := stationxml.NewFDSNStationXML(source, sender, module, "", networks) if ok := root.IsValid(); ok != nil { log.Fatalf("error: invalid stationxml file") } // marshal into xml res, err := root.Marshal() if err != nil { log.Fatalf("error: unable to marshal stationxml: %v", err) } // output as needed ... switch output { case "-": fmt.Fprintln(os.Stdout, string(res)) default: if err := os.MkdirAll(filepath.Dir(output), 0755); err != nil { log.Fatalf("error: unable to create directory %s: %v", filepath.Dir(output), err) } if err := ioutil.WriteFile(output, res, 0644); err != nil { log.Fatalf("error: unable to write file %s: %v", output, err) } } }
func TestBuild(t *testing.T) { // load delta meta helper db, err := metadb.NewMetaDB("./testdata") if err != nil { t.Fatalf("problem loading meta db: %v\n", err) } // load in the test data and convert to stationxml indented text raw, err := ioutil.ReadFile("./testdata/test.xml") if err != nil { t.Fatalf("error: unable to load test stationxml file: %v", err) } var x stationxml.FDSNStationXML if err := xml.Unmarshal(raw, &x); err != nil { t.Fatalf("error: unable to unmarshal stationxml file: %v", err) } b1, err := xml.MarshalIndent(&x, "", " ") if err != nil { t.Fatalf("error: unable to unmarshal stationxml file: %v", err) } var builder Build // build networks and construct stationxml n, err := builder.Construct(db) if err != nil { t.Fatalf("error: unable to build networks list: %v", err) } c, err := stationxml.ParseDateTime("2016-12-13T11:40:46") if err != nil { t.Fatalf("error: unable to parse creation date: %v", err) } y := stationxml.FDSNStationXML{ NameSpace: stationxml.FDSNNameSpace, SchemaVersion: stationxml.FDSNSchemaVersion, Source: "GeoNet", Sender: "WEL(GNS_Test)", Module: "Delta", Networks: n, Created: c, } b2, err := xml.MarshalIndent(&y, "", " ") if err != nil { t.Fatalf("error: unable to marshal stationxml data: %v", err) } // compare stored with computed if string(b1) != string(b2) { t.Error("**** stationxml mismatch ****") f1, err := ioutil.TempFile(os.TempDir(), "tmp") if err != nil { t.Fatal(err) } defer os.Remove(f1.Name()) f1.Write(b1) f2, err := ioutil.TempFile(os.TempDir(), "tmp") if err != nil { t.Fatal(err) } defer os.Remove(f2.Name()) f2.Write(b2) cmd := exec.Command("diff", "-c", f1.Name(), f2.Name()) stdout, err := cmd.StdoutPipe() if err != nil { t.Fatal(err) } err = cmd.Start() if err != nil { t.Fatal(err) } defer cmd.Wait() diff, err := ioutil.ReadAll(stdout) if err != nil { t.Fatal(err) } t.Error(string(diff)) } }