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