1//  Copyright (c) 2014 Couchbase, Inc.
2//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
3//  except in compliance with the License. You may obtain a copy of the License at
4//    http://www.apache.org/licenses/LICENSE-2.0
5//  Unless required by applicable law or agreed to in writing, software distributed under the
6//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
7//  either express or implied. See the License for the specific language governing permissions
8//  and limitations under the License.
9
10package plan
11
12import (
13	"encoding/json"
14
15	"github.com/couchbase/query/datastore"
16	"github.com/couchbase/query/expression"
17	"github.com/couchbase/query/expression/parser"
18)
19
20type Ranges2 []*Range2
21
22type Range2 struct {
23	Low       expression.Expression
24	High      expression.Expression
25	Inclusion datastore.Inclusion
26}
27
28func NewRange2(low, high expression.Expression, incl datastore.Inclusion) *Range2 {
29	return &Range2{
30		Low:       low,
31		High:      high,
32		Inclusion: incl,
33	}
34}
35
36func (this *Range2) Copy() *Range2 {
37	return &Range2{
38		Low:       expression.Copy(this.Low),
39		High:      expression.Copy(this.High),
40		Inclusion: this.Inclusion,
41	}
42}
43
44func (this *Range2) EquivalentTo(other *Range2) bool {
45	return this == other || (this.Inclusion == other.Inclusion &&
46		expression.Equivalent(this.Low, other.Low) &&
47		expression.Equivalent(this.High, other.High))
48}
49
50func (this *Range2) EqualRange() bool {
51	return (this.Inclusion == datastore.BOTH) && (this.Low != nil && this.High != nil && (this.Low == this.High || this.Low.EquivalentTo(this.High)))
52}
53
54func (this *Range2) MarshalJSON() ([]byte, error) {
55	return json.Marshal(this.MarshalBase(nil))
56}
57
58func (this *Range2) MarshalBase(f func(map[string]interface{})) map[string]interface{} {
59	r := map[string]interface{}{
60		"inclusion": this.Inclusion,
61	}
62
63	if this.Low != nil {
64		r["low"] = this.Low
65	}
66
67	if this.High != nil {
68		r["high"] = this.High
69	}
70
71	if f != nil {
72		f(r)
73	}
74	return r
75}
76
77func (this *Range2) UnmarshalJSON(body []byte) error {
78	var _unmarshalled struct {
79		Low       string              `json:"low"`
80		High      string              `json:"high"`
81		Inclusion datastore.Inclusion `json:"inclusion"`
82	}
83
84	err := json.Unmarshal(body, &_unmarshalled)
85	if err != nil {
86		return err
87	}
88
89	if _unmarshalled.Low != "" {
90		this.Low, err = parser.Parse(_unmarshalled.Low)
91		if err != nil {
92			return err
93		}
94	}
95
96	if _unmarshalled.High != "" {
97		this.High, err = parser.Parse(_unmarshalled.High)
98		if err != nil {
99			return err
100		}
101	}
102
103	this.Inclusion = _unmarshalled.Inclusion
104	return nil
105}
106
107func (this Ranges2) Copy() Ranges2 {
108	ranges := make(Ranges2, len(this))
109	for i, r := range this {
110		if r != nil {
111			ranges[i] = r.Copy()
112		}
113	}
114
115	return ranges
116}
117
118func (this Ranges2) EquivalentTo(other Ranges2) bool {
119
120	if len(this) != len(other) {
121		return false
122	}
123
124	for i := 0; i < len(this); i++ {
125		if this[i] == other[i] {
126			continue
127		}
128
129		if this[i] == nil || other[i] == nil {
130			return false
131		}
132
133		if !this[i].EquivalentTo(other[i]) {
134			return false
135		}
136	}
137
138	return true
139}
140
141func (this *Range2) String() string {
142	bytes, _ := this.MarshalJSON()
143	return string(bytes)
144}
145
146type Spans2 []*Span2
147
148type Span2 struct {
149	Seek   expression.Expressions
150	Ranges Ranges2
151	Exact  bool
152}
153
154func NewSpan2(seek expression.Expressions, ranges Ranges2, exact bool) *Span2 {
155	return &Span2{
156		Seek:   seek,
157		Ranges: ranges,
158		Exact:  exact,
159	}
160}
161
162func (this *Span2) Copy() *Span2 {
163	return &Span2{
164		Seek:   expression.CopyExpressions(this.Seek),
165		Ranges: this.Ranges.Copy(),
166		Exact:  this.Exact,
167	}
168}
169
170func (this *Span2) EquivalentTo(other *Span2) bool {
171	return this == other || (this.Exact == other.Exact &&
172		expression.Equivalents(this.Seek, other.Seek) &&
173		this.Ranges.EquivalentTo(other.Ranges))
174}
175
176func (this *Span2) Empty() bool {
177	for i := 0; i < len(this.Ranges); i++ {
178		r := this.Ranges[i]
179		if (r.Inclusion&datastore.BOTH) != datastore.BOTH && r.Low != nil {
180			if r.Low == r.High || (r.High != nil && r.Low.EquivalentTo(r.High)) {
181				return true
182			}
183		}
184
185		if r.Low == nil || r.High == nil {
186			continue
187		}
188
189		lv := r.Low.Value()
190		hv := r.High.Value()
191		if lv == nil || hv == nil {
192			continue
193		}
194
195		c := lv.Collate(hv)
196		if c == 0 {
197			if (r.Inclusion & datastore.BOTH) != datastore.BOTH {
198				return true
199			}
200			continue
201		}
202		return c > 0
203	}
204
205	return false
206}
207
208func (this *Span2) MarshalJSON() ([]byte, error) {
209	return json.Marshal(this.MarshalBase(nil))
210}
211
212func (this *Span2) MarshalBase(f func(map[string]interface{})) map[string]interface{} {
213	r := map[string]interface{}{
214		"range": this.Ranges,
215	}
216
217	if this.Seek != nil && isNotNull(this.Seek) {
218		r["Seek"] = this.Seek
219	}
220
221	if this.Exact {
222		r["exact"] = this.Exact
223	}
224
225	if f != nil {
226		f(r)
227	}
228	return r
229}
230
231func (this *Span2) UnmarshalJSON(body []byte) error {
232	var _unmarshalled struct {
233		Seek   []string          `json:"seek"`
234		Ranges []json.RawMessage `json:"range"`
235		Exact  bool              `json:"exact"`
236	}
237
238	err := json.Unmarshal(body, &_unmarshalled)
239	if err != nil {
240		return err
241	}
242
243	this.Ranges = make(Ranges2, 0, len(_unmarshalled.Ranges))
244	for _, s := range _unmarshalled.Ranges {
245		r := &Range2{}
246		err = r.UnmarshalJSON(s)
247		if err != nil {
248			return err
249		}
250		this.Ranges = append(this.Ranges, r)
251	}
252
253	if _unmarshalled.Seek != nil {
254		this.Seek = make(expression.Expressions, len(_unmarshalled.Seek))
255		for j, seekExpr := range _unmarshalled.Seek {
256			this.Seek[j], err = parser.Parse(seekExpr)
257			if err != nil {
258				return err
259			}
260		}
261	}
262
263	this.Exact = _unmarshalled.Exact
264
265	return nil
266}
267
268func (this *Span2) String() string {
269	bytes, _ := this.MarshalJSON()
270	return string(bytes)
271}
272
273func (this Spans2) Copy() Spans2 {
274	spans := make(Spans2, len(this))
275	for i, s := range this {
276		if s != nil {
277			spans[i] = s.Copy()
278		}
279	}
280
281	return spans
282}
283
284func (this Spans2) EquivalentTo(other Spans2) bool {
285
286	if len(this) != len(other) {
287		return false
288	}
289
290	for i := 0; i < len(this); i++ {
291		if this[i] == other[i] {
292			continue
293		}
294
295		if this[i] == nil || other[i] == nil {
296			return false
297		}
298
299		if !this[i].EquivalentTo(other[i]) {
300			return false
301		}
302	}
303
304	return true
305}
306