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        this.select = select;
071        this.from = from;
072        this.where = where;
073        this.groupBy = groupBy;
074        this.having = having;
075        this.orderBy = orderBy;
076    }
077
078    public SQLQuery(SelectClause select, FromClause from, WhereClause where, GroupByClause groupBy,
079            HavingClause having, OrderByClause orderBy, long limit, long offset) {
080        this.select = select;
081        this.from = from;
082        this.where = where;
083        this.groupBy = groupBy;
084        this.having = having;
085        this.orderBy = orderBy;
086        this.limit = limit;
087        this.offset = offset;
088    }
089
090    /**
091     * Copying constructor. Does not deep-copy the clauses though.
092     */
093    public SQLQuery(SQLQuery other) {
094        select = other.select;
095        from = other.from;
096        where = other.where;
097        orderBy = other.orderBy;
098        groupBy = other.groupBy;
099        having = other.having;
100        limit = other.limit;
101        offset = other.offset;
102    }
103
104    public SQLQuery withWhereExpression(Expression whereExpression) {
105        return new SQLQuery(select, from, new WhereClause(whereExpression), groupBy, having, orderBy, limit, offset);
106    }
107
108    public SelectClause getSelectClause() {
109        return select;
110    }
111
112    public FromClause getFromClause() {
113        return from;
114    }
115
116    public WhereClause getWhereClause() {
117        return where;
118    }
119
120    public OrderByClause getOrderByClause() {
121        return orderBy;
122    }
123
124    @Override
125    public void accept(IVisitor visitor) {
126        visitor.visitQuery(this);
127    }
128
129    @Override
130    // FIXME: not finished
131    public String toString() {
132        if (queryString != null) {
133            return queryString;
134        }
135        StringBuilder buf = new StringBuilder();
136        buf.append("SELECT ").append(select).append(" FROM ").append(from);
137        if (where != null) {
138            buf.append(" WHERE ").append(where);
139        }
140        if (orderBy != null) {
141            buf.append(" ORDER BY ").append(orderBy);
142        }
143        return buf.toString();
144    }
145
146    public void setLimit(long limit) {
147        this.limit = limit;
148    }
149
150    public void setOffset(long offset) {
151        this.offset = offset;
152    }
153
154    public long getLimit() {
155        return limit;
156    }
157
158    public long getOffset() {
159        return offset;
160    }
161
162    public String getQueryString() {
163        return queryString;
164    }
165
166    public void setQueryString(String queryString) {
167        this.queryString = queryString;
168    }
169
170    @Override
171    public boolean equals(Object obj) {
172        if (this == obj) {
173            return true;
174        }
175        if (obj == null) {
176            return false;
177        }
178        if (getClass() != obj.getClass()) {
179            return false;
180        }
181        SQLQuery other = (SQLQuery) obj;
182        if (select == null) {
183            if (other.select != null) {
184                return false;
185            }
186        } else if (!select.equals(other.select)) {
187            return false;
188        }
189        if (from == null) {
190            if (other.from != null) {
191                return false;
192            }
193        } else if (!from.equals(other.from)) {
194            return false;
195        }
196        if (where == null) {
197            if (other.where != null) {
198                return false;
199            }
200        } else if (!where.equals(other.where)) {
201            return false;
202        }
203        if (orderBy == null) {
204            if (other.orderBy != null) {
205                return false;
206            }
207        } else if (!orderBy.equals(other.orderBy)) {
208            return false;
209        }
210        if (groupBy == null) {
211            if (other.groupBy != null) {
212                return false;
213            }
214        } else if (!groupBy.equals(other.groupBy)) {
215            return false;
216        }
217        if (having == null) {
218            if (other.having != null) {
219                return false;
220            }
221        } else if (!having.equals(other.having)) {
222            return false;
223        }
224        if (limit != other.limit) {
225            return false;
226        }
227        if (offset != other.offset) {
228            return false;
229        }
230        return true;
231    }
232
233    @Override
234    public int hashCode() {
235        final int prime = 31;
236        int result = 1;
237        result = prime * result + (select == null ? 0 : select.hashCode());
238        result = prime * result + (from == null ? 0 : from.hashCode());
239        result = prime * result + (where == null ? 0 : where.hashCode());
240        result = prime * result + (orderBy == null ? 0 : orderBy.hashCode());
241        result = prime * result + (groupBy == null ? 0 : groupBy.hashCode());
242        result = prime * result + (having == null ? 0 : having.hashCode());
243        result = prime * result + (int) (limit ^ (limit >>> 32));
244        result = prime * result + (int) (offset ^ (offset >>> 32));
245        return result;
246    }
247
248    /**
249     * Interface for a class that can transform a {@link SQLQuery} into another.
250     */
251    public interface Transformer extends Serializable {
252
253        Transformer IDENTITY = new IdentityTransformer();
254
255        SQLQuery transform(Principal principal, SQLQuery query);
256    }
257
258    public static class IdentityTransformer implements Transformer {
259        private static final long serialVersionUID = 1L;
260
261        @Override
262        public SQLQuery transform(Principal principal, SQLQuery query) {
263            return query;
264        }
265    }
266
267}