package main import ( "fmt" "sort" ) type indexType int type doer interface { do(subdoc []interface{}, q *docType) []interface{} } const ( cmp__gt = iota collect__attributes__cat collect__attributes__graad collect__attributes__index collect__attributes__lemma collect__attributes__pt collect__child__node collect__descendant__or__self__node collect__descendant__or__self__type__node equal__is function__count__1__args function__not__1__args ) var ( nTRUE = []interface{}{true} nFALSE = []interface{}{} ) type dAnd struct { arg1 doer arg2 doer } func (d *dAnd) do(subdoc []interface{}, q *docType) []interface{} { for _, a := range []doer{d.arg1, d.arg2} { if r := a.do(subdoc, q); len(r) == 0 { return nFALSE } } return nTRUE } type dArg struct { arg1 doer arg2 doer } func (d *dArg) do(subdoc []interface{}, q *docType) []interface{} { result := []interface{}{} for i, a := range []doer{d.arg1, d.arg2} { if i == 0 || a != nil { // TODO: waarom flatten? result = append(result, flatten(a.do(subdoc, q))) } } return result } type dCmp struct { ARG int arg1 doer arg2 doer } func (d *dCmp) do(subdoc []interface{}, q *docType) []interface{} { arg1 := d.arg1.do(subdoc, q) arg2 := d.arg2.do(subdoc, q) switch d.ARG { case cmp__gt: // > result := make([]interface{}, 0) for _, a1 := range arg1 { for _, a2 := range arg2 { switch a1t := a1.(type) { case int: if a1t > a2.(int) { result = append(result, true) } case string: if a1t > a2.(string) { result = append(result, true) } default: panic(fmt.Sprintf("Cmp>: Missing case for type %T in %s", a1, q.Filename)) } } } return result default: panic("Cmp: Missing case in " + q.Filename) } } type dCollect struct { ARG int arg1 doer arg2 doer } func (d *dCollect) do(subdoc []interface{}, q *docType) []interface{} { lists := [][]interface{}{} result1 := []interface{}{} for _, r := range d.arg1.do(subdoc, q) { switch d.ARG { case collect__attributes__cat: if i := r.(*NodeType).Cat; i != "" { result1 = append(result1, i) } case collect__attributes__graad: if i := r.(*NodeType).Graad; i != "" { result1 = append(result1, i) } case collect__attributes__index: if i := r.(*NodeType).Index; i > 0 { result1 = append(result1, i) } case collect__attributes__lemma: if i := r.(*NodeType).Lemma; i != "" { result1 = append(result1, i) } case collect__attributes__pt: if i := r.(*NodeType).Pt; i != "" { result1 = append(result1, i) } case collect__child__node: lists = append(lists, r.(*NodeType).AxChildren) case collect__descendant__or__self__type__node, collect__descendant__or__self__node: lists = append(lists, r.(*NodeType).AxDescendantsOrSelf) default: panic("Collect: Missing case in " + q.Filename) } } if d.arg2 == nil { for _, list := range lists { result1 = append(result1, list...) } return result1 } if len(result1) > 0 { l := [][]interface{}{result1} lists = append(l, lists...) } result2 := []interface{}{} for _, list := range lists { for _, e := range list { for _, r2 := range d.arg2.do([]interface{}{e}, q) { if idx, ok := r2.(indexType); ok { switch idx { case 1: result2 = append(result2, list[0]) case -1: result2 = append(result2, list[len(list)-1]) default: panic("Collect: Missing case for plain index in " + q.Filename) } continue } result2 = append(result2, e) } } } return result2 } type dElem struct { DATA []interface{} arg1 doer } func (d *dElem) do(subdoc []interface{}, q *docType) []interface{} { if d.arg1 == nil { return d.DATA } /* TODO: arg1 negeren: klopt dat? zie bijvoorbeeld: foo[@a + 10 = @b] Waarvoor dient arg1 dan? SORT COLLECT 'child' 'name' 'node' foo NODE PREDICATE EQUAL = PLUS + COLLECT 'attributes' 'name' 'node' a NODE ELEM Object is a number : 10 COLLECT 'attributes' 'name' 'node' a NODE COLLECT 'attributes' 'name' 'node' b NODE */ return d.DATA } type dEqual struct { ARG int arg1 doer arg2 doer } func (d *dEqual) do(subdoc []interface{}, q *docType) []interface{} { result := make([]interface{}, 0) switch d.ARG { case equal__is: a1 := d.arg1.do(subdoc, q) a2 := d.arg2.do(subdoc, q) for _, aa1 := range a1 { for _, aa2 := range a2 { if aa1 == aa2 { result = append(result, true) } } } return result default: panic("Equal: Missing case in " + q.Filename) } } type dFunction struct { ARG int arg1 doer } func (d *dFunction) do(subdoc []interface{}, q *docType) []interface{} { var r []interface{} if d.arg1 != nil { r = d.arg1.do(subdoc, q) } switch d.ARG { case function__count__1__args: return []interface{}{len(r[0].([]interface{}))} case function__not__1__args: if len(r[0].([]interface{})) == 0 { return nTRUE } return nFALSE default: panic("Function: Missing case in " + q.Filename) } } type dNode struct{} func (d *dNode) do(subdoc []interface{}, q *docType) []interface{} { return subdoc } type dOr struct { arg1 doer arg2 doer } func (d *dOr) do(subdoc []interface{}, q *docType) []interface{} { for _, a := range []doer{d.arg1, d.arg2} { if r := a.do(subdoc, q); len(r) > 0 { return nTRUE } } return nFALSE } type dPredicate struct { arg1 doer arg2 doer } func (d *dPredicate) do(subdoc []interface{}, q *docType) []interface{} { result := d.arg1.do(subdoc, q) if d.arg2 == nil || len(result) == 0 { return result } idx := d.arg2.do(result, q)[0].(indexType) // TODO: altijd een index? switch idx { case 1: return []interface{}{result[0]} case -1: return []interface{}{result[len(result)-1]} default: panic(fmt.Sprintf("Predicate arg2: Missing case for index %d in %s", int(idx), q.Filename)) } } type dRoot struct{} func (d *dRoot) do(subdoc []interface{}, q *docType) []interface{} { return q.Varroot } type dSort struct { arg1 doer } func (d *dSort) do(subdoc []interface{}, q *docType) []interface{} { result := d.arg1.do(subdoc, q) if len(result) < 2 { return result } if _, ok := result[0].([]interface{}); ok { res := make([]interface{}, 0) for _, r := range result { res = append(res, r.([]interface{})...) } result = res if len(result) < 2 { return result } } switch result[0].(type) { case *NodeType: sort.Slice(result, func(i, j int) bool { return result[i].(*NodeType).ID < result[j].(*NodeType).ID }) for i := 1; i < len(result); i++ { if result[i].(*NodeType) == result[i-1].(*NodeType) { result = append(result[:i], result[i+1:]...) i-- } } case bool: result = result[:1] case string: sort.Slice(result, func(i, j int) bool { return result[i].(string) < result[j].(string) }) for i := 1; i < len(result); i++ { if result[i].(string) == result[i-1].(string) { result = append(result[:i], result[i+1:]...) i-- } } case int: sort.Slice(result, func(i, j int) bool { return result[i].(int) < result[j].(int) }) for i := 1; i < len(result); i++ { if result[i].(int) == result[i-1].(int) { result = append(result[:i], result[i+1:]...) i-- } } default: panic(fmt.Sprintf("Sort: Missing case for type %T in %s", result[0], q.Filename)) } return result } type dVariable struct { VAR interface{} } func (d *dVariable) do(subdoc []interface{}, q *docType) []interface{} { switch t := d.VAR.(type) { case []interface{}: return t case *NodeType: return []interface{}{t} case []*NodeType: ii := make([]interface{}, len(t)) for i, v := range t { ii[i] = v } return ii case int: return []interface{}{t} case string: return []interface{}{t} default: panic(fmt.Sprintf("Variable: Missing case for type %T in %s", t, q.Filename)) } } type xPath struct { arg1 doer } func (d *xPath) do(q *docType) []interface{} { return d.arg1.do([]interface{}{}, q) } //////////////////////////////////////////////////////////////// func test(q *docType, xpath *xPath) bool { return len(xpath.do(q)) > 0 } func find(q *docType, xpath *xPath) []interface{} { return xpath.do(q) } func flatten(aa []interface{}) []interface{} { result := make([]interface{}, 0) for _, a := range aa { switch t := a.(type) { case []interface{}: result = append(result, flatten(t)...) default: result = append(result, a) } } return result }