1 /*
2  * Copyright 2015-2018 HuntLabs.cn
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 module hunt.sql.ast.expr.SQLCaseExpr;
17 
18 
19 import hunt.sql.SQLUtils;
20 import hunt.sql.ast;
21 import hunt.sql.visitor.SQLASTOutputVisitor;
22 import hunt.sql.visitor.SQLASTVisitor;
23 import hunt.collection;
24 import hunt.util.StringBuilder;
25 
26 public class SQLCaseExpr : SQLExprImpl , SQLReplaceable//, Serializable 
27 {
28 
29     private  List!Item  items;
30     private SQLExpr           valueExpr;
31     private SQLExpr           elseExpr;
32 
33     public this(){
34         items            = new ArrayList!Item();
35     }
36 
37     public SQLExpr getValueExpr() {
38         return this.valueExpr;
39     }
40 
41     public void setValueExpr(SQLExpr valueExpr) {
42         if (valueExpr !is null) {
43             valueExpr.setParent(this);
44         }
45         this.valueExpr = valueExpr;
46     }
47 
48     public SQLExpr getElseExpr() {
49         return this.elseExpr;
50     }
51 
52     public void setElseExpr(SQLExpr elseExpr) {
53         if (elseExpr !is null) {
54             elseExpr.setParent(this);
55         }
56         this.elseExpr = elseExpr;
57     }
58 
59     public List!Item getItems() {
60         return this.items;
61     }
62 
63     public void addItem(Item item) {
64         if (item !is null) {
65             item.setParent(this);
66             this.items.add(item);
67         }
68     }
69 
70     override  protected void accept0(SQLASTVisitor visitor) {
71         if (visitor.visit(this)) {
72             acceptChild(visitor, this.valueExpr);
73             acceptChild!(SQLCaseExpr.Item)(visitor, this.items);
74             acceptChild(visitor, this.elseExpr);
75         }
76         visitor.endVisit(this);
77     }
78 
79    override
80     public List!SQLObject getChildren() {
81         List!SQLObject children = new ArrayList!SQLObject();
82         if (valueExpr !is null) {
83             children.add(this.valueExpr);
84         }
85         children.addAll(cast(List!SQLObject)(this.items));
86         if (elseExpr !is null) {
87             children.add(this.elseExpr);
88         }
89         return children;
90     }
91 
92    override
93     public bool replace(SQLExpr expr, SQLExpr target) {
94         if (valueExpr == expr) {
95             setValueExpr(target);
96             return true;
97         }
98 
99         if (elseExpr == expr) {
100             setElseExpr(target);
101             return true;
102         }
103 
104         return false;
105     }
106 
107     public static class Item : SQLObjectImpl , SQLReplaceable//, Serializable 
108     {
109         private SQLExpr           conditionExpr;
110         private SQLExpr           valueExpr;
111 
112         public this(){
113 
114         }
115 
116         public this(SQLExpr conditionExpr, SQLExpr valueExpr){
117 
118             setConditionExpr(conditionExpr);
119             setValueExpr(valueExpr);
120         }
121 
122         public SQLExpr getConditionExpr() {
123             return this.conditionExpr;
124         }
125 
126         public void setConditionExpr(SQLExpr conditionExpr) {
127             if (conditionExpr !is null) {
128                 conditionExpr.setParent(this);
129             }
130             this.conditionExpr = conditionExpr;
131         }
132 
133         public SQLExpr getValueExpr() {
134             return this.valueExpr;
135         }
136 
137         public void setValueExpr(SQLExpr valueExpr) {
138             if (valueExpr !is null) {
139                 valueExpr.setParent(this);
140             }
141             this.valueExpr = valueExpr;
142         }
143 
144         override  protected void accept0(SQLASTVisitor visitor) {
145             if (visitor.visit(this)) {
146                 acceptChild(visitor, this.conditionExpr);
147                 acceptChild(visitor, this.valueExpr);
148             }
149             visitor.endVisit(this);
150         }
151 
152        override
153         public size_t toHash() @trusted nothrow {
154              int prime = 31;
155             size_t result = 1;
156             result = prime * result + ((conditionExpr is null) ? 0 : (cast(Object)conditionExpr).toHash());
157             result = prime * result + ((valueExpr is null) ? 0 : (cast(Object)valueExpr).toHash());
158             return result;
159         }
160 
161        override
162         public bool opEquals(Object obj) {
163             if (this is obj) return true;
164             if (obj is null) return false;
165             if (typeid(this) != typeid(obj)) return false;
166             Item other = cast(Item) obj;
167             if (conditionExpr is null) {
168                 if (other.conditionExpr !is null) return false;
169             } else if (!(cast(Object)(conditionExpr)).opEquals(cast(Object)(other.conditionExpr))) return false;
170             if (valueExpr is null) {
171                 if (other.valueExpr !is null) return false;
172             } else if (!(cast(Object)(valueExpr)).opEquals(cast(Object)(other.valueExpr))) return false;
173             return true;
174         }
175 
176 
177         override public Item clone() {
178             Item x = new Item();
179             if (conditionExpr !is null) {
180                 x.setConditionExpr(conditionExpr.clone());
181             }
182             if (valueExpr !is null) {
183                 x.setValueExpr(valueExpr.clone());
184             }
185             return x;
186         }
187 
188         override public void output(StringBuilder buf) {
189             new SQLASTOutputVisitor(buf).visit(this);
190         }
191 
192        override
193         public bool replace(SQLExpr expr, SQLExpr target) {
194             if (valueExpr == expr) {
195                 setValueExpr(target);
196                 return true;
197             }
198 
199             if (conditionExpr == expr) {
200                 setConditionExpr(target);
201                 return true;
202             }
203 
204             return false;
205         }
206     }
207 
208    override
209     public size_t toHash() @trusted nothrow {
210          int prime = 31;
211         size_t result = 1;
212         result = prime * result + ((elseExpr is null) ? 0 : (cast(Object)elseExpr).toHash());
213         result = prime * result + ((items is null) ? 0 : (cast(Object)items).toHash());
214         result = prime * result + ((valueExpr is null) ? 0 : (cast(Object)valueExpr).toHash());
215         return result;
216     }
217 
218    override
219     public bool opEquals(Object obj) {
220         if (this is obj) {
221             return true;
222         }
223         if (obj is null) {
224             return false;
225         }
226         if (typeid(this) != typeid(obj)) {
227             return false;
228         }
229         SQLCaseExpr other = cast(SQLCaseExpr) obj;
230         if (elseExpr is null) {
231             if (other.elseExpr !is null) {
232                 return false;
233             }
234         } else if (!(cast(Object)(elseExpr)).opEquals(cast(Object)(other.elseExpr))) {
235             return false;
236         }
237         if (items is null) {
238             if (other.items !is null) {
239                 return false;
240             }
241         } else if (!(cast(Object)(items)).opEquals(cast(Object)(other.items))) {
242             return false;
243         }
244         if (valueExpr is null) {
245             if (other.valueExpr !is null) {
246                 return false;
247             }
248         } else if (!(cast(Object)(valueExpr)).opEquals(cast(Object)(other.valueExpr))) {
249             return false;
250         }
251         return true;
252     }
253 
254 
255     override public SQLCaseExpr clone() {
256         SQLCaseExpr x = new SQLCaseExpr();
257 
258         foreach (Item item ; items) {
259             x.addItem(item.clone());
260         }
261 
262         if (valueExpr !is null) {
263             x.setValueExpr(valueExpr.clone());
264         }
265 
266         if (elseExpr !is null) {
267             x.setElseExpr(elseExpr.clone());
268         }
269 
270         return x;
271     }
272 
273     override public SQLDataType computeDataType() {
274         foreach (Item item ; items) {
275             SQLExpr expr = item.getValueExpr();
276             if (expr !is null) {
277                 SQLDataType dataType = expr.computeDataType();
278                 if (dataType !is null) {
279                     return dataType;
280                 }
281             }
282         }
283 
284         if(elseExpr !is null) {
285             return elseExpr.computeDataType();
286         }
287 
288         return null;
289     }
290 
291     override public string toString() {
292         return SQLUtils.toSQLString(this, null);
293     }
294 }