2013-05-14 12:04:11 +04:00
|
|
|
package mapping
|
2013-05-13 15:58:44 +04:00
|
|
|
|
|
|
|
import (
|
2015-08-11 20:22:01 +03:00
|
|
|
"io/ioutil"
|
2017-06-03 03:49:45 +03:00
|
|
|
"regexp"
|
2014-08-11 12:18:08 +04:00
|
|
|
|
|
|
|
"github.com/omniscale/imposm3/element"
|
2017-05-11 12:08:06 +03:00
|
|
|
"github.com/omniscale/imposm3/mapping/config"
|
2015-08-11 20:22:01 +03:00
|
|
|
|
2017-05-12 15:52:20 +03:00
|
|
|
"github.com/pkg/errors"
|
2015-08-11 20:22:01 +03:00
|
|
|
"gopkg.in/yaml.v2"
|
2013-05-13 15:58:44 +04:00
|
|
|
)
|
|
|
|
|
2017-05-11 10:37:12 +03:00
|
|
|
type orderedDestTable struct {
|
|
|
|
DestTable
|
|
|
|
order int
|
|
|
|
}
|
|
|
|
|
|
|
|
type TagTableMapping map[Key]map[Value][]orderedDestTable
|
|
|
|
|
2017-05-11 12:08:06 +03:00
|
|
|
func (tt TagTableMapping) addFromMapping(mapping config.KeyValues, table DestTable) {
|
2017-05-11 10:37:12 +03:00
|
|
|
for key, vals := range mapping {
|
|
|
|
for _, v := range vals {
|
2017-05-11 12:08:06 +03:00
|
|
|
vals, ok := tt[Key(key)]
|
|
|
|
tbl := orderedDestTable{DestTable: table, order: v.Order}
|
2017-05-11 10:37:12 +03:00
|
|
|
if ok {
|
2017-05-11 12:08:06 +03:00
|
|
|
vals[Value(v.Value)] = append(vals[Value(v.Value)], tbl)
|
2017-05-11 10:37:12 +03:00
|
|
|
} else {
|
2017-05-11 12:08:06 +03:00
|
|
|
tt[Key(key)] = make(map[Value][]orderedDestTable)
|
|
|
|
tt[Key(key)][Value(v.Value)] = append(tt[Key(key)][Value(v.Value)], tbl)
|
2017-05-11 10:37:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tt TagTableMapping) asTagMap() tagMap {
|
|
|
|
result := make(tagMap)
|
|
|
|
for k, vals := range tt {
|
|
|
|
result[k] = make(map[Value]struct{})
|
|
|
|
for v := range vals {
|
|
|
|
result[k][v] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
2013-05-27 13:24:22 +04:00
|
|
|
|
|
|
|
type DestTable struct {
|
|
|
|
Name string
|
|
|
|
SubMapping string
|
|
|
|
}
|
2013-05-17 17:44:50 +04:00
|
|
|
|
2013-10-28 11:41:24 +04:00
|
|
|
type TableType string
|
|
|
|
|
2014-06-19 13:51:15 +04:00
|
|
|
func (tt *TableType) UnmarshalJSON(data []byte) error {
|
|
|
|
switch string(data) {
|
|
|
|
case "":
|
|
|
|
return errors.New("missing table type")
|
|
|
|
case `"point"`:
|
|
|
|
*tt = PointTable
|
|
|
|
case `"linestring"`:
|
|
|
|
*tt = LineStringTable
|
|
|
|
case `"polygon"`:
|
|
|
|
*tt = PolygonTable
|
|
|
|
case `"geometry"`:
|
|
|
|
*tt = GeometryTable
|
2016-01-04 13:19:28 +03:00
|
|
|
case `"relation"`:
|
|
|
|
*tt = RelationTable
|
|
|
|
case `"relation_member"`:
|
|
|
|
*tt = RelationMemberTable
|
2014-06-19 13:51:15 +04:00
|
|
|
}
|
2017-05-12 15:52:20 +03:00
|
|
|
return errors.New("unknown type " + string(data))
|
2014-06-19 13:51:15 +04:00
|
|
|
}
|
|
|
|
|
2013-10-28 11:41:24 +04:00
|
|
|
const (
|
2016-01-04 13:19:28 +03:00
|
|
|
PolygonTable TableType = "polygon"
|
|
|
|
LineStringTable TableType = "linestring"
|
|
|
|
PointTable TableType = "point"
|
|
|
|
GeometryTable TableType = "geometry"
|
|
|
|
RelationTable TableType = "relation"
|
|
|
|
RelationMemberTable TableType = "relation_member"
|
2013-10-28 11:41:24 +04:00
|
|
|
)
|
|
|
|
|
2017-05-11 12:08:06 +03:00
|
|
|
type Mapping struct {
|
2017-05-12 15:52:20 +03:00
|
|
|
Conf config.Mapping
|
|
|
|
PointMatcher NodeMatcher
|
|
|
|
LineStringMatcher WayMatcher
|
|
|
|
PolygonMatcher RelWayMatcher
|
|
|
|
RelationMatcher RelationMatcher
|
|
|
|
RelationMemberMatcher RelationMatcher
|
2017-05-11 12:08:06 +03:00
|
|
|
}
|
|
|
|
|
2018-06-05 20:08:42 +03:00
|
|
|
func FromFile(filename string) (*Mapping, error) {
|
|
|
|
b, err := ioutil.ReadFile(filename)
|
2013-05-17 17:44:50 +04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-06-05 20:08:42 +03:00
|
|
|
return New(b)
|
|
|
|
}
|
2013-05-17 17:44:50 +04:00
|
|
|
|
2018-06-05 20:08:42 +03:00
|
|
|
func New(b []byte) (*Mapping, error) {
|
2013-05-17 17:44:50 +04:00
|
|
|
mapping := Mapping{}
|
2018-06-05 20:08:42 +03:00
|
|
|
err := yaml.Unmarshal(b, &mapping.Conf)
|
2013-05-17 17:44:50 +04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2013-05-29 10:47:26 +04:00
|
|
|
err = mapping.prepare()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-05-12 15:52:20 +03:00
|
|
|
|
|
|
|
err = mapping.createMatcher()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2013-05-17 17:44:50 +04:00
|
|
|
return &mapping, nil
|
2013-05-13 15:58:44 +04:00
|
|
|
}
|
|
|
|
|
2013-05-29 10:47:26 +04:00
|
|
|
func (m *Mapping) prepare() error {
|
2017-05-11 12:08:06 +03:00
|
|
|
for name, t := range m.Conf.Tables {
|
2013-05-14 18:15:35 +04:00
|
|
|
t.Name = name
|
2014-06-24 15:54:10 +04:00
|
|
|
if t.OldFields != nil {
|
|
|
|
// todo deprecate 'fields'
|
2017-05-10 17:38:30 +03:00
|
|
|
t.Columns = t.OldFields
|
2014-06-24 15:54:10 +04:00
|
|
|
}
|
2017-05-12 15:52:20 +03:00
|
|
|
if t.Type == "" {
|
|
|
|
return errors.Errorf("missing type for table %s", name)
|
|
|
|
}
|
2017-05-12 16:04:39 +03:00
|
|
|
|
|
|
|
if TableType(t.Type) == GeometryTable {
|
|
|
|
if t.Mapping != nil || t.Mappings != nil {
|
|
|
|
return errors.Errorf("table with type:geometry requires type_mapping for table %s", name)
|
|
|
|
}
|
|
|
|
}
|
2013-05-13 15:58:44 +04:00
|
|
|
}
|
2014-06-19 13:51:15 +04:00
|
|
|
|
2017-05-11 12:08:06 +03:00
|
|
|
for name, t := range m.Conf.GeneralizedTables {
|
2013-05-22 13:48:34 +04:00
|
|
|
t.Name = name
|
|
|
|
}
|
2013-05-29 10:47:26 +04:00
|
|
|
return nil
|
2013-05-13 15:58:44 +04:00
|
|
|
}
|
|
|
|
|
2017-05-12 15:52:20 +03:00
|
|
|
func (m *Mapping) createMatcher() error {
|
|
|
|
var err error
|
|
|
|
m.PointMatcher, err = m.pointMatcher()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
m.LineStringMatcher, err = m.lineStringMatcher()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
m.PolygonMatcher, err = m.polygonMatcher()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
m.RelationMatcher, err = m.relationMatcher()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
m.RelationMemberMatcher, err = m.relationMemberMatcher()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-05-11 10:37:12 +03:00
|
|
|
func (m *Mapping) mappings(tableType TableType, mappings TagTableMapping) {
|
2017-05-11 12:08:06 +03:00
|
|
|
for name, t := range m.Conf.Tables {
|
|
|
|
if TableType(t.Type) != GeometryTable && TableType(t.Type) != tableType {
|
2013-05-13 15:58:44 +04:00
|
|
|
continue
|
|
|
|
}
|
2015-09-25 14:36:23 +03:00
|
|
|
mappings.addFromMapping(t.Mapping, DestTable{Name: name})
|
2013-05-27 13:24:22 +04:00
|
|
|
|
|
|
|
for subMappingName, subMapping := range t.Mappings {
|
2015-09-25 14:36:23 +03:00
|
|
|
mappings.addFromMapping(subMapping.Mapping, DestTable{Name: name, SubMapping: subMappingName})
|
2013-05-13 15:58:44 +04:00
|
|
|
}
|
2014-06-19 13:51:15 +04:00
|
|
|
|
|
|
|
switch tableType {
|
|
|
|
case PointTable:
|
2015-09-25 14:36:23 +03:00
|
|
|
mappings.addFromMapping(t.TypeMappings.Points, DestTable{Name: name})
|
2014-06-19 13:51:15 +04:00
|
|
|
case LineStringTable:
|
2015-09-25 14:36:23 +03:00
|
|
|
mappings.addFromMapping(t.TypeMappings.LineStrings, DestTable{Name: name})
|
2014-06-19 13:51:15 +04:00
|
|
|
case PolygonTable:
|
2015-09-25 14:36:23 +03:00
|
|
|
mappings.addFromMapping(t.TypeMappings.Polygons, DestTable{Name: name})
|
2014-06-19 13:51:15 +04:00
|
|
|
}
|
2013-05-13 15:58:44 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-12 15:52:20 +03:00
|
|
|
func (m *Mapping) tables(tableType TableType) (map[string]*rowBuilder, error) {
|
|
|
|
var err error
|
2017-05-11 14:32:28 +03:00
|
|
|
result := make(map[string]*rowBuilder)
|
2017-05-11 12:08:06 +03:00
|
|
|
for name, t := range m.Conf.Tables {
|
|
|
|
if TableType(t.Type) == tableType || TableType(t.Type) == GeometryTable {
|
2017-05-12 15:52:20 +03:00
|
|
|
result[name], err = makeRowBuilder(t)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "creating row builder for %s", name)
|
|
|
|
}
|
|
|
|
|
2013-05-14 18:15:35 +04:00
|
|
|
}
|
|
|
|
}
|
2017-05-12 15:52:20 +03:00
|
|
|
return result, nil
|
2013-05-14 18:15:35 +04:00
|
|
|
}
|
|
|
|
|
2017-05-12 15:52:20 +03:00
|
|
|
func makeRowBuilder(tbl *config.Table) (*rowBuilder, error) {
|
2017-05-11 14:32:28 +03:00
|
|
|
result := rowBuilder{}
|
2017-05-11 12:08:06 +03:00
|
|
|
|
|
|
|
for _, mappingColumn := range tbl.Columns {
|
2017-05-11 14:32:28 +03:00
|
|
|
column := valueBuilder{}
|
|
|
|
column.key = Key(mappingColumn.Key)
|
2017-05-11 12:08:06 +03:00
|
|
|
|
2017-05-12 15:52:20 +03:00
|
|
|
columnType, err := MakeColumnType(mappingColumn)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "creating column %s", mappingColumn.Name)
|
2017-05-11 12:08:06 +03:00
|
|
|
}
|
2017-05-12 15:52:20 +03:00
|
|
|
column.colType = *columnType
|
2017-05-11 12:08:06 +03:00
|
|
|
result.columns = append(result.columns, column)
|
|
|
|
}
|
2017-05-12 15:52:20 +03:00
|
|
|
return &result, nil
|
2017-05-11 12:08:06 +03:00
|
|
|
}
|
|
|
|
|
2017-05-12 15:52:20 +03:00
|
|
|
func MakeColumnType(c *config.Column) (*ColumnType, error) {
|
|
|
|
columnType, ok := AvailableColumnTypes[c.Type]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.Errorf("unhandled type %s", c.Type)
|
|
|
|
}
|
|
|
|
|
|
|
|
if columnType.MakeFunc != nil {
|
|
|
|
makeValue, err := columnType.MakeFunc(c.Name, columnType, *c)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2017-05-11 12:08:06 +03:00
|
|
|
}
|
2017-05-12 15:52:20 +03:00
|
|
|
columnType = ColumnType{columnType.Name, columnType.GoType, makeValue, nil, nil, columnType.FromMember}
|
2017-05-11 12:08:06 +03:00
|
|
|
}
|
2017-05-12 15:52:20 +03:00
|
|
|
columnType.FromMember = c.FromMember
|
|
|
|
return &columnType, nil
|
2017-05-11 12:08:06 +03:00
|
|
|
}
|
|
|
|
|
2014-04-30 18:33:07 +04:00
|
|
|
func (m *Mapping) extraTags(tableType TableType, tags map[Key]bool) {
|
2017-05-11 12:08:06 +03:00
|
|
|
for _, t := range m.Conf.Tables {
|
|
|
|
if TableType(t.Type) != tableType && TableType(t.Type) != GeometryTable {
|
2013-05-13 15:58:44 +04:00
|
|
|
continue
|
|
|
|
}
|
2017-05-10 15:23:32 +03:00
|
|
|
|
2017-05-10 17:38:30 +03:00
|
|
|
for _, col := range t.Columns {
|
|
|
|
if col.Key != "" {
|
2017-05-11 12:08:06 +03:00
|
|
|
tags[Key(col.Key)] = true
|
2017-05-10 15:23:32 +03:00
|
|
|
}
|
2017-05-10 17:38:30 +03:00
|
|
|
for _, k := range col.Keys {
|
2017-05-11 12:08:06 +03:00
|
|
|
tags[Key(k)] = true
|
2017-05-10 15:23:32 +03:00
|
|
|
}
|
2013-05-13 15:58:44 +04:00
|
|
|
}
|
2017-05-10 15:23:32 +03:00
|
|
|
|
2013-05-17 17:07:03 +04:00
|
|
|
if t.Filters != nil && t.Filters.ExcludeTags != nil {
|
2013-05-27 13:24:22 +04:00
|
|
|
for _, keyVal := range *t.Filters.ExcludeTags {
|
2014-04-30 18:33:07 +04:00
|
|
|
tags[Key(keyVal[0])] = true
|
2013-05-17 17:07:03 +04:00
|
|
|
}
|
|
|
|
}
|
2017-05-10 15:23:32 +03:00
|
|
|
|
|
|
|
if tableType == PolygonTable || tableType == RelationTable || tableType == RelationMemberTable {
|
|
|
|
if t.RelationTypes != nil {
|
|
|
|
tags["type"] = true
|
|
|
|
}
|
|
|
|
}
|
2013-05-17 17:07:03 +04:00
|
|
|
}
|
2017-05-11 12:08:06 +03:00
|
|
|
for _, k := range m.Conf.Tags.Include {
|
|
|
|
tags[Key(k)] = true
|
2016-11-16 18:25:48 +03:00
|
|
|
}
|
|
|
|
|
2016-11-10 13:00:34 +03:00
|
|
|
// always include area tag for closed-way handling
|
|
|
|
tags["area"] = true
|
2013-05-17 17:07:03 +04:00
|
|
|
}
|
|
|
|
|
2017-05-11 14:32:28 +03:00
|
|
|
type elementFilter func(tags element.Tags, key Key, closed bool) bool
|
|
|
|
|
|
|
|
type tableElementFilters map[string][]elementFilter
|
2016-11-10 13:00:34 +03:00
|
|
|
|
2018-09-29 02:47:19 +03:00
|
|
|
func (m *Mapping) getAreaTags() (map[Key]struct{}, map[Key]struct{}) {
|
2016-11-10 13:00:34 +03:00
|
|
|
var areaTags map[Key]struct{}
|
|
|
|
var linearTags map[Key]struct{}
|
2017-05-11 12:08:06 +03:00
|
|
|
if m.Conf.Areas.AreaTags != nil {
|
2016-11-10 13:00:34 +03:00
|
|
|
areaTags = make(map[Key]struct{})
|
2017-05-11 12:08:06 +03:00
|
|
|
for _, tag := range m.Conf.Areas.AreaTags {
|
|
|
|
areaTags[Key(tag)] = struct{}{}
|
2016-11-10 13:00:34 +03:00
|
|
|
}
|
|
|
|
}
|
2017-05-11 12:08:06 +03:00
|
|
|
if m.Conf.Areas.LinearTags != nil {
|
2016-11-10 13:00:34 +03:00
|
|
|
linearTags = make(map[Key]struct{})
|
2017-05-11 12:08:06 +03:00
|
|
|
for _, tag := range m.Conf.Areas.LinearTags {
|
|
|
|
linearTags[Key(tag)] = struct{}{}
|
2016-11-10 13:00:34 +03:00
|
|
|
}
|
|
|
|
}
|
2018-09-29 02:47:19 +03:00
|
|
|
return areaTags, linearTags
|
2017-05-09 16:55:21 +03:00
|
|
|
}
|
2016-11-10 13:00:34 +03:00
|
|
|
|
2017-05-11 10:37:12 +03:00
|
|
|
func (m *Mapping) addRelationFilters(tableType TableType, filters tableElementFilters) {
|
2017-05-11 12:08:06 +03:00
|
|
|
for name, t := range m.Conf.Tables {
|
2017-05-10 15:23:32 +03:00
|
|
|
if t.RelationTypes != nil {
|
2017-05-10 16:54:03 +03:00
|
|
|
relTypes := t.RelationTypes // copy loop var for closure
|
2017-05-10 15:23:32 +03:00
|
|
|
f := func(tags element.Tags, key Key, closed bool) bool {
|
|
|
|
if v, ok := tags["type"]; ok {
|
2017-05-10 16:54:03 +03:00
|
|
|
for _, rtype := range relTypes {
|
2017-05-10 15:23:32 +03:00
|
|
|
if v == rtype {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
filters[name] = append(filters[name], f)
|
|
|
|
} else {
|
2017-05-11 12:08:06 +03:00
|
|
|
if TableType(t.Type) == PolygonTable {
|
2017-06-03 14:47:22 +03:00
|
|
|
// standard multipolygon handling (boundary and land_area are for backwards compatibility)
|
2017-05-10 15:23:32 +03:00
|
|
|
f := func(tags element.Tags, key Key, closed bool) bool {
|
|
|
|
if v, ok := tags["type"]; ok {
|
|
|
|
if v == "multipolygon" || v == "boundary" || v == "land_area" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
filters[name] = append(filters[name], f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-11 10:37:12 +03:00
|
|
|
func (m *Mapping) addFilters(filters tableElementFilters) {
|
2017-05-11 12:08:06 +03:00
|
|
|
for name, t := range m.Conf.Tables {
|
2013-05-17 17:07:03 +04:00
|
|
|
if t.Filters == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if t.Filters.ExcludeTags != nil {
|
2017-06-03 03:49:45 +03:00
|
|
|
log.Print("warn: exclude_tags filter is deprecated and will be removed. See require and reject filter.")
|
2013-05-27 13:24:22 +04:00
|
|
|
for _, filterKeyVal := range *t.Filters.ExcludeTags {
|
2017-06-03 03:49:45 +03:00
|
|
|
// Convert `exclude_tags`` filter to `reject` filter !
|
2017-11-17 16:18:12 +03:00
|
|
|
keyname := filterKeyVal[0]
|
2017-06-03 03:49:45 +03:00
|
|
|
vararr := []config.OrderedValue{
|
|
|
|
{
|
|
|
|
Value: config.Value(filterKeyVal[1]),
|
|
|
|
Order: 1,
|
|
|
|
},
|
|
|
|
}
|
2017-11-17 16:18:12 +03:00
|
|
|
filters[name] = append(filters[name], makeFiltersFunction(name, false, true, keyname, vararr))
|
2017-06-03 03:49:45 +03:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if t.Filters.Require != nil {
|
|
|
|
for keyname, vararr := range t.Filters.Require {
|
|
|
|
filters[name] = append(filters[name], makeFiltersFunction(name, true, false, string(keyname), vararr))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if t.Filters.Reject != nil {
|
|
|
|
for keyname, vararr := range t.Filters.Reject {
|
|
|
|
filters[name] = append(filters[name], makeFiltersFunction(name, false, true, string(keyname), vararr))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if t.Filters.RequireRegexp != nil {
|
|
|
|
for keyname, regexp := range t.Filters.RequireRegexp {
|
|
|
|
filters[name] = append(filters[name], makeRegexpFiltersFunction(name, true, false, string(keyname), regexp))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if t.Filters.RejectRegexp != nil {
|
|
|
|
for keyname, regexp := range t.Filters.RejectRegexp {
|
|
|
|
filters[name] = append(filters[name], makeRegexpFiltersFunction(name, false, true, string(keyname), regexp))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func findValueInOrderedValue(v config.Value, list []config.OrderedValue) bool {
|
|
|
|
for _, item := range list {
|
|
|
|
if item.Value == v {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-06-03 14:47:22 +03:00
|
|
|
func makeRegexpFiltersFunction(tablename string, virtualTrue bool, virtualFalse bool, vKeyname string, vRegexp string) func(tags element.Tags, key Key, closed bool) bool {
|
2017-06-03 03:49:45 +03:00
|
|
|
// Compile regular expression, if not valid regexp --> panic !
|
2017-06-03 14:47:22 +03:00
|
|
|
r := regexp.MustCompile(vRegexp)
|
2017-06-03 03:49:45 +03:00
|
|
|
return func(tags element.Tags, key Key, closed bool) bool {
|
2017-06-03 14:47:22 +03:00
|
|
|
if v, ok := tags[vKeyname]; ok {
|
2017-06-03 03:49:45 +03:00
|
|
|
if r.MatchString(v) {
|
|
|
|
return virtualTrue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return virtualFalse
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-03 14:47:22 +03:00
|
|
|
func makeFiltersFunction(tablename string, virtualTrue bool, virtualFalse bool, vKeyname string, vVararr []config.OrderedValue) func(tags element.Tags, key Key, closed bool) bool {
|
2017-06-03 03:49:45 +03:00
|
|
|
|
2017-06-03 14:47:22 +03:00
|
|
|
if findValueInOrderedValue("__nil__", vVararr) { // check __nil__
|
2017-06-03 03:49:45 +03:00
|
|
|
log.Print("warn: Filter value '__nil__' is not supported ! (tablename:" + tablename + ")")
|
|
|
|
}
|
|
|
|
|
2017-06-03 14:47:22 +03:00
|
|
|
if findValueInOrderedValue("__any__", vVararr) { // check __any__
|
|
|
|
if len(vVararr) > 1 {
|
2017-06-03 03:49:45 +03:00
|
|
|
log.Print("warn: Multiple filter value with '__any__' keywords is not valid! (tablename:" + tablename + ")")
|
|
|
|
}
|
|
|
|
return func(tags element.Tags, key Key, closed bool) bool {
|
2017-06-03 14:47:22 +03:00
|
|
|
if _, ok := tags[vKeyname]; ok {
|
2017-06-03 03:49:45 +03:00
|
|
|
return virtualTrue
|
|
|
|
}
|
|
|
|
return virtualFalse
|
|
|
|
}
|
2017-06-03 14:47:22 +03:00
|
|
|
} else if len(vVararr) == 1 { // IF 1 parameter THEN we can generate optimal code
|
2017-06-03 03:49:45 +03:00
|
|
|
return func(tags element.Tags, key Key, closed bool) bool {
|
2017-06-03 14:47:22 +03:00
|
|
|
if v, ok := tags[vKeyname]; ok {
|
|
|
|
if config.Value(v) == vVararr[0].Value {
|
2017-06-03 03:49:45 +03:00
|
|
|
return virtualTrue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return virtualFalse
|
|
|
|
}
|
|
|
|
} else { // > 1 parameter - less optimal code
|
|
|
|
return func(tags element.Tags, key Key, closed bool) bool {
|
2017-06-03 14:47:22 +03:00
|
|
|
if v, ok := tags[vKeyname]; ok {
|
|
|
|
if findValueInOrderedValue(config.Value(v), vVararr) {
|
2017-06-03 03:49:45 +03:00
|
|
|
return virtualTrue
|
2013-05-17 17:07:03 +04:00
|
|
|
}
|
|
|
|
}
|
2017-06-03 03:49:45 +03:00
|
|
|
return virtualFalse
|
2013-05-17 17:07:03 +04:00
|
|
|
}
|
2013-05-13 15:58:44 +04:00
|
|
|
}
|
|
|
|
}
|