1package xpath
2
3import (
4	"reflect"
5)
6
7type iterator interface {
8	Current() NodeNavigator
9}
10
11// An XPath query interface.
12type query interface {
13	// Select traversing iterator returns a query matched node NodeNavigator.
14	Select(iterator) NodeNavigator
15
16	// Evaluate evaluates query and returns values of the current query.
17	Evaluate(iterator) interface{}
18
19	Clone() query
20}
21
22// contextQuery is returns current node on the iterator object query.
23type contextQuery struct {
24	count int
25	Root  bool // Moving to root-level node in the current context iterator.
26}
27
28func (c *contextQuery) Select(t iterator) (n NodeNavigator) {
29	if c.count == 0 {
30		c.count++
31		n = t.Current().Copy()
32		if c.Root {
33			n.MoveToRoot()
34		}
35	}
36	return n
37}
38
39func (c *contextQuery) Evaluate(iterator) interface{} {
40	c.count = 0
41	return c
42}
43
44func (c *contextQuery) Clone() query {
45	return &contextQuery{count: 0, Root: c.Root}
46}
47
48// ancestorQuery is an XPath ancestor node query.(ancestor::*|ancestor-self::*)
49type ancestorQuery struct {
50	iterator func() NodeNavigator
51
52	Self      bool
53	Input     query
54	Predicate func(NodeNavigator) bool
55}
56
57func (a *ancestorQuery) Select(t iterator) NodeNavigator {
58	for {
59		if a.iterator == nil {
60			node := a.Input.Select(t)
61			if node == nil {
62				return nil
63			}
64			first := true
65			a.iterator = func() NodeNavigator {
66				if first && a.Self {
67					first = false
68					if a.Predicate(node) {
69						return node
70					}
71				}
72				for node.MoveToParent() {
73					if !a.Predicate(node) {
74						continue
75					}
76					return node
77				}
78				return nil
79			}
80		}
81
82		if node := a.iterator(); node != nil {
83			return node
84		}
85		a.iterator = nil
86	}
87}
88
89func (a *ancestorQuery) Evaluate(t iterator) interface{} {
90	a.Input.Evaluate(t)
91	a.iterator = nil
92	return a
93}
94
95func (a *ancestorQuery) Test(n NodeNavigator) bool {
96	return a.Predicate(n)
97}
98
99func (a *ancestorQuery) Clone() query {
100	return &ancestorQuery{Self: a.Self, Input: a.Input.Clone(), Predicate: a.Predicate}
101}
102
103// attributeQuery is an XPath attribute node query.(@*)
104type attributeQuery struct {
105	iterator func() NodeNavigator
106
107	Input     query
108	Predicate func(NodeNavigator) bool
109}
110
111func (a *attributeQuery) Select(t iterator) NodeNavigator {
112	for {
113		if a.iterator == nil {
114			node := a.Input.Select(t)
115			if node == nil {
116				return nil
117			}
118			node = node.Copy()
119			a.iterator = func() NodeNavigator {
120				for {
121					onAttr := node.MoveToNextAttribute()
122					if !onAttr {
123						return nil
124					}
125					if a.Predicate(node) {
126						return node
127					}
128				}
129			}
130		}
131
132		if node := a.iterator(); node != nil {
133			return node
134		}
135		a.iterator = nil
136	}
137}
138
139func (a *attributeQuery) Evaluate(t iterator) interface{} {
140	a.Input.Evaluate(t)
141	a.iterator = nil
142	return a
143}
144
145func (a *attributeQuery) Test(n NodeNavigator) bool {
146	return a.Predicate(n)
147}
148
149func (a *attributeQuery) Clone() query {
150	return &attributeQuery{Input: a.Input.Clone(), Predicate: a.Predicate}
151}
152
153// childQuery is an XPath child node query.(child::*)
154type childQuery struct {
155	posit    int
156	iterator func() NodeNavigator
157
158	Input     query
159	Predicate func(NodeNavigator) bool
160}
161
162func (c *childQuery) Select(t iterator) NodeNavigator {
163	for {
164		if c.iterator == nil {
165			c.posit = 0
166			node := c.Input.Select(t)
167			if node == nil {
168				return nil
169			}
170			node = node.Copy()
171			first := true
172			c.iterator = func() NodeNavigator {
173				for {
174					if (first && !node.MoveToChild()) || (!first && !node.MoveToNext()) {
175						return nil
176					}
177					first = false
178					if c.Predicate(node) {
179						return node
180					}
181				}
182			}
183		}
184
185		if node := c.iterator(); node != nil {
186			c.posit++
187			return node
188		}
189		c.iterator = nil
190	}
191}
192
193func (c *childQuery) Evaluate(t iterator) interface{} {
194	c.Input.Evaluate(t)
195	c.iterator = nil
196	return c
197}
198
199func (c *childQuery) Test(n NodeNavigator) bool {
200	return c.Predicate(n)
201}
202
203func (c *childQuery) Clone() query {
204	return &childQuery{Input: c.Input.Clone(), Predicate: c.Predicate}
205}
206
207// position returns a position of current NodeNavigator.
208func (c *childQuery) position() int {
209	return c.posit
210}
211
212// descendantQuery is an XPath descendant node query.(descendant::* | descendant-or-self::*)
213type descendantQuery struct {
214	iterator func() NodeNavigator
215	posit    int
216
217	Self      bool
218	Input     query
219	Predicate func(NodeNavigator) bool
220}
221
222func (d *descendantQuery) Select(t iterator) NodeNavigator {
223	for {
224		if d.iterator == nil {
225			d.posit = 0
226			node := d.Input.Select(t)
227			if node == nil {
228				return nil
229			}
230			node = node.Copy()
231			level := 0
232			first := true
233			d.iterator = func() NodeNavigator {
234				if first && d.Self {
235					first = false
236					if d.Predicate(node) {
237						return node
238					}
239				}
240
241				for {
242					if node.MoveToChild() {
243						level++
244					} else {
245						for {
246							if level == 0 {
247								return nil
248							}
249							if node.MoveToNext() {
250								break
251							}
252							node.MoveToParent()
253							level--
254						}
255					}
256					if d.Predicate(node) {
257						return node
258					}
259				}
260			}
261		}
262
263		if node := d.iterator(); node != nil {
264			d.posit++
265			return node
266		}
267		d.iterator = nil
268	}
269}
270
271func (d *descendantQuery) Evaluate(t iterator) interface{} {
272	d.Input.Evaluate(t)
273	d.iterator = nil
274	return d
275}
276
277func (d *descendantQuery) Test(n NodeNavigator) bool {
278	return d.Predicate(n)
279}
280
281// position returns a position of current NodeNavigator.
282func (d *descendantQuery) position() int {
283	return d.posit
284}
285
286func (d *descendantQuery) Clone() query {
287	return &descendantQuery{Self: d.Self, Input: d.Input.Clone(), Predicate: d.Predicate}
288}
289
290// followingQuery is an XPath following node query.(following::*|following-sibling::*)
291type followingQuery struct {
292	iterator func() NodeNavigator
293
294	Input     query
295	Sibling   bool // The matching sibling node of current node.
296	Predicate func(NodeNavigator) bool
297}
298
299func (f *followingQuery) Select(t iterator) NodeNavigator {
300	for {
301		if f.iterator == nil {
302			node := f.Input.Select(t)
303			if node == nil {
304				return nil
305			}
306			node = node.Copy()
307			if f.Sibling {
308				f.iterator = func() NodeNavigator {
309					for {
310						if !node.MoveToNext() {
311							return nil
312						}
313						if f.Predicate(node) {
314							return node
315						}
316					}
317				}
318			} else {
319				var q query // descendant query
320				f.iterator = func() NodeNavigator {
321					for {
322						if q == nil {
323							for !node.MoveToNext() {
324								if !node.MoveToParent() {
325									return nil
326								}
327							}
328							q = &descendantQuery{
329								Self:      true,
330								Input:     &contextQuery{},
331								Predicate: f.Predicate,
332							}
333							t.Current().MoveTo(node)
334						}
335						if node := q.Select(t); node != nil {
336							return node
337						}
338						q = nil
339					}
340				}
341			}
342		}
343
344		if node := f.iterator(); node != nil {
345			return node
346		}
347		f.iterator = nil
348	}
349}
350
351func (f *followingQuery) Evaluate(t iterator) interface{} {
352	f.Input.Evaluate(t)
353	return f
354}
355
356func (f *followingQuery) Test(n NodeNavigator) bool {
357	return f.Predicate(n)
358}
359
360func (f *followingQuery) Clone() query {
361	return &followingQuery{Input: f.Input.Clone(), Sibling: f.Sibling, Predicate: f.Predicate}
362}
363
364// precedingQuery is an XPath preceding node query.(preceding::*)
365type precedingQuery struct {
366	iterator  func() NodeNavigator
367	Input     query
368	Sibling   bool // The matching sibling node of current node.
369	Predicate func(NodeNavigator) bool
370}
371
372func (p *precedingQuery) Select(t iterator) NodeNavigator {
373	for {
374		if p.iterator == nil {
375			node := p.Input.Select(t)
376			if node == nil {
377				return nil
378			}
379			node = node.Copy()
380			if p.Sibling {
381				p.iterator = func() NodeNavigator {
382					for {
383						for !node.MoveToPrevious() {
384							return nil
385						}
386						if p.Predicate(node) {
387							return node
388						}
389					}
390				}
391			} else {
392				var q query
393				p.iterator = func() NodeNavigator {
394					for {
395						if q == nil {
396							for !node.MoveToPrevious() {
397								if !node.MoveToParent() {
398									return nil
399								}
400							}
401							q = &descendantQuery{
402								Self:      true,
403								Input:     &contextQuery{},
404								Predicate: p.Predicate,
405							}
406							t.Current().MoveTo(node)
407						}
408						if node := q.Select(t); node != nil {
409							return node
410						}
411						q = nil
412					}
413				}
414			}
415		}
416		if node := p.iterator(); node != nil {
417			return node
418		}
419		p.iterator = nil
420	}
421}
422
423func (p *precedingQuery) Evaluate(t iterator) interface{} {
424	p.Input.Evaluate(t)
425	return p
426}
427
428func (p *precedingQuery) Test(n NodeNavigator) bool {
429	return p.Predicate(n)
430}
431
432func (p *precedingQuery) Clone() query {
433	return &precedingQuery{Input: p.Input.Clone(), Sibling: p.Sibling, Predicate: p.Predicate}
434}
435
436// parentQuery is an XPath parent node query.(parent::*)
437type parentQuery struct {
438	Input     query
439	Predicate func(NodeNavigator) bool
440}
441
442func (p *parentQuery) Select(t iterator) NodeNavigator {
443	for {
444		node := p.Input.Select(t)
445		if node == nil {
446			return nil
447		}
448		node = node.Copy()
449		if node.MoveToParent() && p.Predicate(node) {
450			return node
451		}
452	}
453}
454
455func (p *parentQuery) Evaluate(t iterator) interface{} {
456	p.Input.Evaluate(t)
457	return p
458}
459
460func (p *parentQuery) Clone() query {
461	return &parentQuery{Input: p.Input.Clone(), Predicate: p.Predicate}
462}
463
464func (p *parentQuery) Test(n NodeNavigator) bool {
465	return p.Predicate(n)
466}
467
468// selfQuery is an Self node query.(self::*)
469type selfQuery struct {
470	Input     query
471	Predicate func(NodeNavigator) bool
472}
473
474func (s *selfQuery) Select(t iterator) NodeNavigator {
475	for {
476		node := s.Input.Select(t)
477		if node == nil {
478			return nil
479		}
480
481		if s.Predicate(node) {
482			return node
483		}
484	}
485}
486
487func (s *selfQuery) Evaluate(t iterator) interface{} {
488	s.Input.Evaluate(t)
489	return s
490}
491
492func (s *selfQuery) Test(n NodeNavigator) bool {
493	return s.Predicate(n)
494}
495
496func (s *selfQuery) Clone() query {
497	return &selfQuery{Input: s.Input.Clone(), Predicate: s.Predicate}
498}
499
500// filterQuery is an XPath query for predicate filter.
501type filterQuery struct {
502	Input     query
503	Predicate query
504}
505
506func (f *filterQuery) do(t iterator) bool {
507	val := reflect.ValueOf(f.Predicate.Evaluate(t))
508	switch val.Kind() {
509	case reflect.Bool:
510		return val.Bool()
511	case reflect.String:
512		return len(val.String()) > 0
513	case reflect.Float64:
514		pt := float64(getNodePosition(f.Input))
515		return int(val.Float()) == int(pt)
516	default:
517		if q, ok := f.Predicate.(query); ok {
518			return q.Select(t) != nil
519		}
520	}
521	return false
522}
523
524func (f *filterQuery) Select(t iterator) NodeNavigator {
525	for {
526		node := f.Input.Select(t)
527		if node == nil {
528			return node
529		}
530		node = node.Copy()
531		//fmt.Println(node.LocalName())
532
533		t.Current().MoveTo(node)
534		if f.do(t) {
535			return node
536		}
537	}
538}
539
540func (f *filterQuery) Evaluate(t iterator) interface{} {
541	f.Input.Evaluate(t)
542	return f
543}
544
545func (f *filterQuery) Clone() query {
546	return &filterQuery{Input: f.Input.Clone(), Predicate: f.Predicate.Clone()}
547}
548
549// functionQuery is an XPath function that call a function to returns
550// value of current NodeNavigator node.
551type functionQuery struct {
552	Input query                             // Node Set
553	Func  func(query, iterator) interface{} // The xpath function.
554}
555
556func (f *functionQuery) Select(t iterator) NodeNavigator {
557	return nil
558}
559
560// Evaluate call a specified function that will returns the
561// following value type: number,string,boolean.
562func (f *functionQuery) Evaluate(t iterator) interface{} {
563	return f.Func(f.Input, t)
564}
565
566func (f *functionQuery) Clone() query {
567	return &functionQuery{Input: f.Input.Clone(), Func: f.Func}
568}
569
570// constantQuery is an XPath constant operand.
571type constantQuery struct {
572	Val interface{}
573}
574
575func (c *constantQuery) Select(t iterator) NodeNavigator {
576	return nil
577}
578
579func (c *constantQuery) Evaluate(t iterator) interface{} {
580	return c.Val
581}
582
583func (c *constantQuery) Clone() query {
584	return c
585}
586
587// logicalQuery is an XPath logical expression.
588type logicalQuery struct {
589	Left, Right query
590
591	Do func(iterator, interface{}, interface{}) interface{}
592}
593
594func (l *logicalQuery) Select(t iterator) NodeNavigator {
595	// When a XPath expr is logical expression.
596	node := t.Current().Copy()
597	val := l.Evaluate(t)
598	switch val.(type) {
599	case bool:
600		if val.(bool) == true {
601			return node
602		}
603	}
604	return nil
605}
606
607func (l *logicalQuery) Evaluate(t iterator) interface{} {
608	m := l.Left.Evaluate(t)
609	n := l.Right.Evaluate(t)
610	return l.Do(t, m, n)
611}
612
613func (l *logicalQuery) Clone() query {
614	return &logicalQuery{Left: l.Left.Clone(), Right: l.Right.Clone(), Do: l.Do}
615}
616
617// numericQuery is an XPath numeric operator expression.
618type numericQuery struct {
619	Left, Right query
620
621	Do func(interface{}, interface{}) interface{}
622}
623
624func (n *numericQuery) Select(t iterator) NodeNavigator {
625	return nil
626}
627
628func (n *numericQuery) Evaluate(t iterator) interface{} {
629	m := n.Left.Evaluate(t)
630	k := n.Right.Evaluate(t)
631	return n.Do(m, k)
632}
633
634func (n *numericQuery) Clone() query {
635	return &numericQuery{Left: n.Left.Clone(), Right: n.Right.Clone(), Do: n.Do}
636}
637
638type booleanQuery struct {
639	IsOr        bool
640	Left, Right query
641	iterator    func() NodeNavigator
642}
643
644func (b *booleanQuery) Select(t iterator) NodeNavigator {
645	if b.iterator == nil {
646		var list []NodeNavigator
647		i := 0
648		root := t.Current().Copy()
649		if b.IsOr {
650			for {
651				node := b.Left.Select(t)
652				if node == nil {
653					break
654				}
655				node = node.Copy()
656				list = append(list, node)
657			}
658			t.Current().MoveTo(root)
659			for {
660				node := b.Right.Select(t)
661				if node == nil {
662					break
663				}
664				node = node.Copy()
665				list = append(list, node)
666			}
667		} else {
668			var m []NodeNavigator
669			var n []NodeNavigator
670			for {
671				node := b.Left.Select(t)
672				if node == nil {
673					break
674				}
675				node = node.Copy()
676				list = append(m, node)
677			}
678			t.Current().MoveTo(root)
679			for {
680				node := b.Right.Select(t)
681				if node == nil {
682					break
683				}
684				node = node.Copy()
685				list = append(n, node)
686			}
687			for _, k := range m {
688				for _, j := range n {
689					if k == j {
690						list = append(list, k)
691					}
692				}
693			}
694		}
695
696		b.iterator = func() NodeNavigator {
697			if i >= len(list) {
698				return nil
699			}
700			node := list[i]
701			i++
702			return node
703		}
704	}
705	return b.iterator()
706}
707
708func (b *booleanQuery) Evaluate(t iterator) interface{} {
709	m := b.Left.Evaluate(t)
710	left := asBool(t, m)
711	if b.IsOr && left {
712		return true
713	} else if !b.IsOr && !left {
714		return false
715	}
716	m = b.Right.Evaluate(t)
717	return asBool(t, m)
718}
719
720func (b *booleanQuery) Clone() query {
721	return &booleanQuery{IsOr: b.IsOr, Left: b.Left.Clone(), Right: b.Right.Clone()}
722}
723
724type unionQuery struct {
725	Left, Right query
726	iterator    func() NodeNavigator
727}
728
729func (u *unionQuery) Select(t iterator) NodeNavigator {
730	if u.iterator == nil {
731		var list []NodeNavigator
732		var i int
733		root := t.Current().Copy()
734		for {
735			node := u.Left.Select(t)
736			if node == nil {
737				break
738			}
739			node = node.Copy()
740			list = append(list, node)
741		}
742		t.Current().MoveTo(root)
743		for {
744			node := u.Right.Select(t)
745			if node == nil {
746				break
747			}
748			node = node.Copy()
749			var exists bool
750			for _, x := range list {
751				if reflect.DeepEqual(x, node) {
752					exists = true
753					break
754				}
755			}
756			if !exists {
757				list = append(list, node)
758			}
759		}
760		u.iterator = func() NodeNavigator {
761			if i >= len(list) {
762				return nil
763			}
764			node := list[i]
765			i++
766			return node
767		}
768	}
769	return u.iterator()
770}
771
772func (u *unionQuery) Evaluate(t iterator) interface{} {
773	u.iterator = nil
774	u.Left.Evaluate(t)
775	u.Right.Evaluate(t)
776	return u
777}
778
779func (u *unionQuery) Clone() query {
780	return &unionQuery{Left: u.Left.Clone(), Right: u.Right.Clone()}
781}
782
783func getNodePosition(q query) int {
784	type Position interface {
785		position() int
786	}
787	if count, ok := q.(Position); ok {
788		return count.position()
789	}
790	return 1
791}
792