001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Bogdan Stefanescu
018 *     Florent Guillaume
019 */
020
021package org.nuxeo.ecm.core.query.sql.model;
022
023import java.io.Serializable;
024import java.security.Principal;
025
026/**
027 * @author Bogdan Stefanescu
028 * @author Florent Guillaume
029 */
030public class SQLQuery implements ASTNode {
031
032    private static final long serialVersionUID = 6383829486216039408L;
033
034    private String queryString;
035
036    public SelectClause select;
037
038    public final FromClause from;
039
040    public final WhereClause where;
041
042    public OrderByClause orderBy;
043
044    public final GroupByClause groupBy;
045
046    public final HavingClause having;
047
048    public long limit = 0;
049
050    public long offset = 0;
051
052    public SQLQuery() {
053        this(new SelectClause(), new FromClause(), null, null, null, null);
054    }
055
056    public SQLQuery(SelectClause select, FromClause from) {
057        this(select, from, null, null, null, null);
058    }
059
060    public SQLQuery(SelectClause select, FromClause from, WhereClause where) {
061        this(select, from, where, null, null, null);
062    }
063
064    public SQLQuery(SelectClause select, FromClause from, WhereClause where, OrderByClause orderBy) {
065        this(select, from, where, null, null, orderBy);
066    }
067
068    public SQLQuery(SelectClause select, FromClause from, WhereClause where, GroupByClause groupBy,
069            HavingClause having, OrderByClause orderBy) {
070        assert select != null && from != null;
071        this.select = select;
072        this.from = from;
073        this.where = where;
074        this.groupBy = groupBy;
075        this.having = having;
076        this.orderBy = orderBy;
077    }
078
079    public SQLQuery(SelectClause select, FromClause from, WhereClause where, GroupByClause groupBy,
080            HavingClause having, OrderByClause orderBy, long limit, long offset) {
081        assert select != null && from != null;
082        this.select = select;
083        this.from = from;
084        this.where = where;
085        this.groupBy = groupBy;
086        this.having = having;
087        this.orderBy = orderBy;
088        this.limit = limit;
089        this.offset = offset;
090    }
091
092    /**
093     * Copying constructor. Does not deep-copy the clauses though.
094     */
095    public SQLQuery(SQLQuery other) {
096        select = other.select;
097        from = other.from;
098        where = other.where;
099        orderBy = other.orderBy;
100        groupBy = other.groupBy;
101        having = other.having;
102        limit = other.limit;
103        offset = other.offset;
104    }
105
106    public SelectClause getSelectClause() {
107        return select;
108    }
109
110    public FromClause getFromClause() {
111        return from;
112    }
113
114    public WhereClause getWhereClause() {
115        return where;
116    }
117
118    public OrderByClause getOrderByClause() {
119        return orderBy;
120    }
121
122    @Override
123    public void accept(IVisitor visitor) {
124        visitor.visitQuery(this);
125    }
126
127    @Override
128    // FIXME: not finished
129    public String toString() {
130        if (queryString != null) {
131            return queryString;
132        }
133        StringBuilder buf = new StringBuilder();
134        buf.append("SELECT ").append(select).append(" FROM ").append(from);
135        if (where != null) {
136            buf.append(" WHERE ").append(where);
137        }
138        if (orderBy != null) {
139            buf.append(" ORDER BY ").append(orderBy);
140        }
141        return buf.toString();
142    }
143
144    public void setLimit(long limit) {
145        this.limit = limit;
146    }
147
148    public void setOffset(long offset) {
149        this.offset = offset;
150    }
151
152    public long getLimit() {
153        return limit;
154    }
155
156    public long getOffset() {
157        return offset;
158    }
159
160    public String getQueryString() {
161        return queryString;
162    }
163
164    public void setQueryString(String queryString) {
165        this.queryString = queryString;
166    }
167
168    @Override
169    public boolean equals(Object obj) {
170        if (this == obj) {
171            return true;
172        }
173        if (obj == null) {
174            return false;
175        }
176        if (getClass() != obj.getClass()) {
177            return false;
178        }
179        SQLQuery other = (SQLQuery) obj;
180        if (select == null) {
181            if (other.select != null) {
182                return false;
183            }
184        } else if (!select.equals(other.select)) {
185            return false;
186        }
187        if (from == null) {
188            if (other.from != null) {
189                return false;
190            }
191        } else if (!from.equals(other.from)) {
192            return false;
193        }
194        if (where == null) {
195            if (other.where != null) {
196                return false;
197            }
198        } else if (!where.equals(other.where)) {
199            return false;
200        }
201        if (orderBy == null) {
202            if (other.orderBy != null) {
203                return false;
204            }
205        } else if (!orderBy.equals(other.orderBy)) {
206            return false;
207        }
208        if (groupBy == null) {
209            if (other.groupBy != null) {
210                return false;
211            }
212        } else if (!groupBy.equals(other.groupBy)) {
213            return false;
214        }
215        if (having == null) {
216            if (other.having != null) {
217                return false;
218            }
219        } else if (!having.equals(other.having)) {
220            return false;
221        }
222        if (limit != other.limit) {
223            return false;
224        }
225        if (offset != other.offset) {
226            return false;
227        }
228        return true;
229    }
230
231    @Override
232    public int hashCode() {
233        final int prime = 31;
234        int result = 1;
235        result = prime * result + (select == null ? 0 : select.hashCode());
236        result = prime * result + (from == null ? 0 : from.hashCode());
237        result = prime * result + (where == null ? 0 : where.hashCode());
238        result = prime * result + (orderBy == null ? 0 : orderBy.hashCode());
239        result = prime * result + (groupBy == null ? 0 : groupBy.hashCode());
240        result = prime * result + (having == null ? 0 : having.hashCode());
241        result = prime * result + (int) (limit ^ (limit >>> 32));
242        result = prime * result + (int) (offset ^ (offset >>> 32));
243        return result;
244    }
245
246    /**
247     * Interface for a class that can transform a {@link SQLQuery} into another.
248     */
249    public interface Transformer extends Serializable {
250
251        Transformer IDENTITY = new IdentityTransformer();
252
253        SQLQuery transform(Principal principal, SQLQuery query);
254    }
255
256    public static class IdentityTransformer implements Transformer {
257        private static final long serialVersionUID = 1L;
258
259        @Override
260        public SQLQuery transform(Principal principal, SQLQuery query) {
261            return query;
262        }
263    }
264
265}