2013-08-01 17:31:47 +04:00
|
|
|
package query
|
2013-05-17 12:29:23 +04:00
|
|
|
|
|
|
|
import (
|
2013-08-02 12:08:01 +04:00
|
|
|
"encoding/json"
|
2013-05-17 12:29:23 +04:00
|
|
|
"flag"
|
2013-08-01 17:31:47 +04:00
|
|
|
"fmt"
|
2013-05-17 12:29:23 +04:00
|
|
|
"log"
|
2013-08-01 15:35:00 +04:00
|
|
|
"os"
|
2013-08-02 12:08:01 +04:00
|
|
|
"strconv"
|
2013-08-01 17:31:47 +04:00
|
|
|
|
|
|
|
"goposm/cache"
|
2013-08-02 12:08:01 +04:00
|
|
|
"goposm/element"
|
2013-05-17 12:29:23 +04:00
|
|
|
)
|
|
|
|
|
2013-08-01 17:31:47 +04:00
|
|
|
var flags = flag.NewFlagSet("query-cache", flag.ExitOnError)
|
|
|
|
|
2013-05-17 12:29:23 +04:00
|
|
|
var (
|
2013-08-01 17:31:47 +04:00
|
|
|
nodeId = flags.Int64("node", -1, "node")
|
|
|
|
wayId = flags.Int64("way", -1, "way")
|
|
|
|
relId = flags.Int64("rel", -1, "relation")
|
|
|
|
full = flags.Bool("full", false, "recurse into relations/ways")
|
|
|
|
deps = flags.Bool("deps", false, "show dependent ways/relations")
|
|
|
|
cachedir = flags.String("cachedir", "/tmp/goposm", "cache directory")
|
2013-05-17 12:29:23 +04:00
|
|
|
)
|
|
|
|
|
2013-08-02 12:08:01 +04:00
|
|
|
type nodes map[string]*node
|
|
|
|
type ways map[string]*way
|
|
|
|
type relations map[string]*relation
|
|
|
|
|
|
|
|
type node struct {
|
|
|
|
element.Node
|
|
|
|
Ways ways `json:"ways,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type way struct {
|
|
|
|
element.Way
|
|
|
|
Nodes nodes `json:"nodes,omitempty"`
|
|
|
|
Relations relations `json:"relations,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type relation struct {
|
|
|
|
element.Relation
|
|
|
|
Ways ways `json:"ways,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type result struct {
|
|
|
|
Nodes nodes `json:"nodes,omitempty"`
|
|
|
|
Ways ways `json:"ways,omitempty"`
|
|
|
|
Relations relations `json:"relations,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func collectRelations(osmCache *cache.OSMCache, ids []int64, recurse bool) relations {
|
|
|
|
rels := make(relations)
|
2013-05-17 12:29:23 +04:00
|
|
|
for _, id := range ids {
|
2013-08-02 12:08:01 +04:00
|
|
|
sid := strconv.FormatInt(id, 10)
|
2013-05-17 12:29:23 +04:00
|
|
|
rel, err := osmCache.Relations.GetRelation(id)
|
|
|
|
if err == cache.NotFound {
|
2013-08-02 12:08:01 +04:00
|
|
|
rels[sid] = nil
|
2013-05-17 12:29:23 +04:00
|
|
|
} else if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
} else {
|
2013-08-02 12:08:01 +04:00
|
|
|
rels[sid] = &relation{*rel, nil}
|
2013-05-17 12:29:23 +04:00
|
|
|
if recurse {
|
2013-08-02 12:08:01 +04:00
|
|
|
memberWayIds := []int64{}
|
2013-05-17 12:29:23 +04:00
|
|
|
for _, m := range rel.Members {
|
2013-08-02 12:08:01 +04:00
|
|
|
if m.Type == element.WAY {
|
|
|
|
memberWayIds = append(memberWayIds, m.Id)
|
|
|
|
}
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
2013-08-02 12:08:01 +04:00
|
|
|
rels[sid].Ways = collectWays(osmCache, nil, memberWayIds, true, false)
|
|
|
|
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-02 12:08:01 +04:00
|
|
|
return rels
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
|
|
|
|
2013-08-02 12:08:01 +04:00
|
|
|
func collectWays(osmCache *cache.OSMCache, diffCache *cache.DiffCache, ids []int64, recurse, deps bool) ways {
|
|
|
|
ws := make(ways)
|
2013-05-17 12:29:23 +04:00
|
|
|
for _, id := range ids {
|
2013-08-02 12:08:01 +04:00
|
|
|
sid := strconv.FormatInt(id, 10)
|
|
|
|
w, err := osmCache.Ways.GetWay(id)
|
2013-05-17 12:29:23 +04:00
|
|
|
if err == cache.NotFound {
|
2013-08-02 12:08:01 +04:00
|
|
|
ws[sid] = nil
|
2013-05-17 12:29:23 +04:00
|
|
|
} else if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
} else {
|
2013-08-02 12:08:01 +04:00
|
|
|
ws[sid] = &way{*w, nil, nil}
|
2013-05-17 12:29:23 +04:00
|
|
|
if recurse {
|
2013-08-02 12:08:01 +04:00
|
|
|
ws[sid].Nodes = collectNodes(osmCache, nil, w.Refs, false)
|
2013-05-30 18:04:14 +04:00
|
|
|
}
|
2013-08-02 12:08:01 +04:00
|
|
|
if deps {
|
|
|
|
rels := diffCache.Ways.Get(id)
|
|
|
|
if len(rels) != 0 {
|
|
|
|
ws[sid].Relations = collectRelations(osmCache, rels, false)
|
|
|
|
}
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-02 12:08:01 +04:00
|
|
|
return ws
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
|
|
|
|
2013-08-02 12:08:01 +04:00
|
|
|
func collectNodes(osmCache *cache.OSMCache, diffCache *cache.DiffCache, ids []int64, deps bool) nodes {
|
|
|
|
ns := make(nodes)
|
2013-05-17 12:29:23 +04:00
|
|
|
for _, id := range ids {
|
2013-08-02 12:08:01 +04:00
|
|
|
sid := strconv.FormatInt(id, 10)
|
|
|
|
n, err := osmCache.Nodes.GetNode(id)
|
2013-05-17 12:29:23 +04:00
|
|
|
if err != cache.NotFound && err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2013-08-02 12:08:01 +04:00
|
|
|
if n == nil {
|
|
|
|
n, err = osmCache.Coords.GetCoord(id)
|
2013-05-17 12:29:23 +04:00
|
|
|
if err == cache.NotFound {
|
2013-08-02 12:08:01 +04:00
|
|
|
ns[sid] = nil
|
2013-05-17 12:29:23 +04:00
|
|
|
} else if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2013-08-02 12:08:01 +04:00
|
|
|
if n != nil {
|
|
|
|
ns[sid] = &node{*n, nil}
|
|
|
|
if deps {
|
|
|
|
ways := diffCache.Coords.Get(id)
|
|
|
|
if len(ways) != 0 {
|
|
|
|
ns[sid].Ways = collectWays(osmCache, diffCache, ways, false, true)
|
|
|
|
}
|
2013-05-30 18:04:14 +04:00
|
|
|
}
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
|
|
|
}
|
2013-08-02 12:08:01 +04:00
|
|
|
return ns
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
|
|
|
|
2013-08-01 17:31:47 +04:00
|
|
|
func Usage() {
|
|
|
|
fmt.Fprintf(os.Stderr, "Usage of %s %s:\n\n", os.Args[0], os.Args[1])
|
|
|
|
flags.PrintDefaults()
|
|
|
|
fmt.Fprintln(os.Stderr, "\nQuery cache for nodes/ways/relations.")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2013-08-02 12:08:01 +04:00
|
|
|
func printJson(obj interface{}) {
|
|
|
|
bytes, err := json.MarshalIndent(obj, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
fmt.Println(string(bytes))
|
|
|
|
}
|
|
|
|
|
2013-08-01 17:31:47 +04:00
|
|
|
func Query(args []string) {
|
|
|
|
flags.Usage = Usage
|
|
|
|
|
|
|
|
if len(args) == 0 {
|
|
|
|
Usage()
|
|
|
|
}
|
|
|
|
|
|
|
|
err := flags.Parse(args)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2013-05-17 12:29:23 +04:00
|
|
|
log.SetFlags(0)
|
2013-08-01 15:35:00 +04:00
|
|
|
log.SetOutput(os.Stdout)
|
2013-05-17 12:29:23 +04:00
|
|
|
|
|
|
|
osmCache := cache.NewOSMCache(*cachedir)
|
2013-08-01 17:31:47 +04:00
|
|
|
err = osmCache.Open()
|
2013-05-17 12:29:23 +04:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2013-05-30 18:04:14 +04:00
|
|
|
diffCache := cache.NewDiffCache(*cachedir)
|
|
|
|
err = diffCache.Open()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if *full && *deps {
|
|
|
|
log.Fatal("cannot use -full and -deps option together")
|
|
|
|
}
|
2013-05-17 12:29:23 +04:00
|
|
|
|
2013-08-02 12:08:01 +04:00
|
|
|
result := result{}
|
|
|
|
|
2013-05-17 12:29:23 +04:00
|
|
|
if *relId != -1 {
|
2013-08-02 12:08:01 +04:00
|
|
|
result.Relations = collectRelations(osmCache, []int64{*relId}, *full)
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if *wayId != -1 {
|
2013-08-02 12:08:01 +04:00
|
|
|
result.Ways = collectWays(osmCache, diffCache, []int64{*wayId}, *full, *deps)
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
2013-05-30 18:04:14 +04:00
|
|
|
|
2013-05-17 12:29:23 +04:00
|
|
|
if *nodeId != -1 {
|
2013-08-02 12:08:01 +04:00
|
|
|
result.Nodes = collectNodes(osmCache, diffCache, []int64{*nodeId}, *deps)
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|
|
|
|
|
2013-08-02 12:08:01 +04:00
|
|
|
printJson(result)
|
2013-05-17 12:29:23 +04:00
|
|
|
}
|