1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | var Node = require('./node');
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | var Query = module.exports = function Query(){
|
21 | Node.call(this);
|
22 | this.nodes = [];
|
23 | this.type = '';
|
24 | this.predicate = '';
|
25 | };
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | Query.prototype.__proto__ = Node.prototype;
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | Query.prototype.clone = function(parent){
|
41 | var clone = new Query;
|
42 | clone.predicate = this.predicate;
|
43 | clone.type = this.type;
|
44 | for (var i = 0, len = this.nodes.length; i < len; ++i) {
|
45 | clone.push(this.nodes[i].clone(parent, clone));
|
46 | }
|
47 | clone.lineno = this.lineno;
|
48 | clone.column = this.column;
|
49 | clone.filename = this.filename;
|
50 | return clone;
|
51 | };
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 | Query.prototype.push = function(feature){
|
61 | this.nodes.push(feature);
|
62 | };
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | Query.prototype.__defineGetter__('resolvedType', function(){
|
72 | if (this.type) {
|
73 | return this.type.nodeName
|
74 | ? this.type.string
|
75 | : this.type;
|
76 | }
|
77 | });
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 | Query.prototype.__defineGetter__('resolvedPredicate', function(){
|
87 | if (this.predicate) {
|
88 | return this.predicate.nodeName
|
89 | ? this.predicate.string
|
90 | : this.predicate;
|
91 | }
|
92 | });
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 | Query.prototype.merge = function(other){
|
103 | var query = new Query
|
104 | , p1 = this.resolvedPredicate
|
105 | , p2 = other.resolvedPredicate
|
106 | , t1 = this.resolvedType
|
107 | , t2 = other.resolvedType
|
108 | , type, pred;
|
109 |
|
110 |
|
111 | t1 = t1 || t2;
|
112 | t2 = t2 || t1;
|
113 | if (('not' == p1) ^ ('not' == p2)) {
|
114 | if (t1 == t2) return;
|
115 | type = ('not' == p1) ? t2 : t1;
|
116 | pred = ('not' == p1) ? p2 : p1;
|
117 | } else if (('not' == p1) && ('not' == p2)) {
|
118 | if (t1 != t2) return;
|
119 | type = t1;
|
120 | pred = 'not';
|
121 | } else if (t1 != t2) {
|
122 | return;
|
123 | } else {
|
124 | type = t1;
|
125 | pred = p1 || p2;
|
126 | }
|
127 | query.predicate = pred;
|
128 | query.type = type;
|
129 | query.nodes = this.nodes.concat(other.nodes);
|
130 | return query;
|
131 | };
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 | Query.prototype.toString = function(){
|
141 | var pred = this.predicate ? this.predicate + ' ' : ''
|
142 | , type = this.type || ''
|
143 | , len = this.nodes.length
|
144 | , str = pred + type;
|
145 | if (len) {
|
146 | str += (type && ' and ') + this.nodes.map(function(expr){
|
147 | return expr.toString();
|
148 | }).join(' and ');
|
149 | }
|
150 | return str;
|
151 | };
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 | Query.prototype.toJSON = function(){
|
161 | return {
|
162 | __type: 'Query',
|
163 | predicate: this.predicate,
|
164 | type: this.type,
|
165 | nodes: this.nodes,
|
166 | lineno: this.lineno,
|
167 | column: this.column,
|
168 | filename: this.filename
|
169 | };
|
170 | };
|