package main import ( "fmt" "sort" ) const ( collect__attributes__name = iota collect__child__animals collect__child__chimp collect__child__food collect__child__type__text__text equal__is function__nth2__0__args ) type indexType int type doer interface { do(subdoc []interface{}, doc *docType) []interface{} } type xPath struct { arg1 doer } func (d *xPath) do(doc *docType) []interface{} { return d.arg1.do([]interface{}{}, doc) } type dCollect struct { ARG int arg1 doer arg2 doer } func (d *dCollect) do(subdoc []interface{}, doc *docType) []interface{} { lists := [][]interface{}{} result := []interface{}{} for _, r := range d.arg1.do(subdoc, doc) { switch d.ARG { case collect__attributes__name: if rr, ok := r.(*animalType); ok { result = append(result, rr.Name) } case collect__child__animals: lists = append(lists, []interface{}{doc.animals}) case collect__child__chimp: if rr, ok := r.(*animalsType); ok { if rr.Chimp != nil { chimps := make([]interface{}, len(rr.Chimp)) for i, ch := range rr.Chimp { chimps[i] = ch } lists = append(lists, chimps) } } case collect__child__food: if rr, ok := r.(*animalType); ok { result = append(result, &rr.Food) } case collect__child__type__text__text: if rr, ok := r.(*foodType); ok { result = append(result, rr.Text) } default: panic("Collect: Missing case") } } if d.arg2 == nil { for _, list := range lists { result = append(result, list...) } return result } if len(result) > 0 { l := [][]interface{}{result} lists = append(l, lists...) } result2 := []interface{}{} for _, list := range lists { for _, e := range list { for _, r2 := range d.arg2.do([]interface{}{e}, doc) { if idx, ok := r2.(indexType); ok { i := int(idx) if i > 0 && i <= len(list) { result2 = append(result2, list[i-1]) } else if i < 0 && len(list)+i >= 0 { result2 = append(result2, list[len(list)+i]) } break // als r2 een indexType is is het altijd dezelfde } result2 = append(result2, e) break // r2 met lengte groter dan 0 is true } } } return result2 } type dElem struct { DATA []interface{} arg1 doer } func (d *dElem) do(subdoc []interface{}, doc *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{}, doc *docType) []interface{} { result := make([]interface{}, 0) switch d.ARG { case equal__is: a1 := d.arg1.do(subdoc, doc) if len(a1) == 0 { return result } a2 := d.arg2.do(subdoc, doc) for _, aa1 := range a1 { for _, aa2 := range a2 { if aa1 == aa2 { result = append(result, true) } } } default: panic("Equal: Missing case") } return result } type dFunction struct { ARG int } func (d *dFunction) do(subdoc []interface{}, doc *docType) []interface{} { switch d.ARG { case function__nth2__0__args: return []interface{}{indexType(2)} default: panic("Function: Missing case") } } type dNode struct{} func (d *dNode) do(subdoc []interface{}, doc *docType) []interface{} { return subdoc } type dPredicate struct { arg1 doer } func (d *dPredicate) do(subdoc []interface{}, doc *docType) []interface{} { result := d.arg1.do(subdoc, doc) return result } type dRoot struct{} func (d *dRoot) do(subdoc []interface{}, doc *docType) []interface{} { return []interface{}{doc.animals} } type dSort struct { arg1 doer } func (d *dSort) do(subdoc []interface{}, doc *docType) []interface{} { result := d.arg1.do(subdoc, doc) 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 *animalsType: seen := make(map[*animalsType]bool) seen[result[0].(*animalsType)] = true for i := 1; i < len(result); i++ { if seen[result[i].(*animalsType)] { result = append(result[:i], result[i+1:]...) i-- } else { seen[result[i].(*animalsType)] = true } } case *animalType: seen := make(map[*animalType]bool) seen[result[0].(*animalType)] = true for i := 1; i < len(result); i++ { if seen[result[i].(*animalType)] { result = append(result[:i], result[i+1:]...) i-- } else { seen[result[i].(*animalType)] = true } } 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-- } } default: panic(fmt.Sprintf("Sort: Missing case for type %T", result[0])) } return result }