View Javadoc

1   /*
2   Copyright (c) 2008 Health Market Science, Inc.
3   
4   This library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License.
8   
9   This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  Lesser General Public License for more details.
13  
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17  USA
18  
19  You can contact Health Market Science at info@healthmarketscience.com
20  or at the following address:
21  
22  Health Market Science
23  2700 Horizon Drive
24  Suite 200
25  King of Prussia, PA 19406
26  */
27  
28  package com.healthmarketscience.sqlbuilder;
29  
30  import com.healthmarketscience.common.util.AppendableExt;
31  
32  /**
33   * Object which maintains context for the sqlbuilder classes when a SQL
34   * statement is being generated.  The object is passed from one SqlObject to
35   * another via the {@link com.healthmarketscience.common.util.AppendableExt#setContext}
36   * and {@link com.healthmarketscience.common.util.AppendableExt#getContext} methods.
37   * This class enables the various SqlObject SQL generation methods to behave
38   * differently depending on where they are being used in a query.
39   *
40   * Note, users of the sqlbuilder classes may extend this context to pass
41   * through more information as any copying of SqlContexts is done via cloning.
42   * The custom context may be introduced to the current SQL generation context
43   * via the {@link SqlObject#toString(int,SqlContext)} method call.
44   *
45   * @author James Ahlborn
46   */
47  public class SqlContext implements Cloneable
48  {
49  
50    /** Previous context replaced by this context, if any */
51    private SqlContext _parent;
52  
53    /** flag indicating whether or not table aliases should be used in the
54        current SQL generation context */
55    private boolean _useTableAliases = true;
56  
57    /** flag indicating whether constraints apply to a column or a table */
58    private boolean _useTableConstraints = true;
59  
60    /** handle to the immediate wrapping query */
61    private Query<?> _query;
62    
63    public SqlContext() {
64    }
65  
66    /**
67     * Gets the SqlContext which was in effect before this SqlContext was
68     * "pushed" onto the context stack.
69     */
70    public SqlContext getParent() {
71      return _parent;
72    }
73  
74    /**
75     * Sets the SqlContext which was in effect before this SqlContext was
76     * "pushed" onto the context stack.  Used by {@link #pushContext}.
77     */
78    private void setParent(SqlContext newParentContext) {
79      _parent = newParentContext;
80    }
81  
82    /**
83     * @return the flag indicating whether or not table aliases should be used
84     *         in the current SQL generation context.
85     */
86    public boolean getUseTableAliases() {
87      return _useTableAliases;
88    }
89  
90    /**
91     * Sets flag indicating whether or not table aliases should be used in the
92     * current SQL generation context.
93     */
94    public void setUseTableAliases(boolean newUseTableAliases) {
95      _useTableAliases = newUseTableAliases;
96    }
97  
98    /**
99     * @return the flag indicating whether or not table constraints should be
100    *         used in the current SQL generation context.
101    */
102   public boolean getUseTableConstraints() {
103     return _useTableConstraints;
104   }
105 
106   /**
107    * Sets flag indicating whether or not table constraints should be used in
108    * the current SQL generation context.
109    */
110   public void setUseTableConstraints(boolean newUseTableConstraints) {
111     _useTableConstraints = newUseTableConstraints;
112   }
113 
114   /**
115    * Gets the handle to the immediate wrapping query
116    */
117   public Query<?> getQuery() {
118     return _query;
119   }
120 
121   /**
122    * Sets the handle to the immediate wrapping query
123    */
124   public void setQuery(Query<?> newQuery) {
125     _query = newQuery;
126   }
127   
128   @Override
129   public SqlContext clone() {
130     try {
131       return (SqlContext)super.clone();
132     } catch(CloneNotSupportedException e) {
133       throw new RuntimeException("should never get here", e);
134     }
135   }
136 
137   /**
138    * Gets the current SqlContext from the given AppendableExt, creating one if
139    * necessary.  Should be used by any subclasses of SqlObject wishing to
140    * retrieve the current context.
141    */
142   public static SqlContext getContext(AppendableExt app)
143   {
144     SqlContext context = (SqlContext)app.getContext();
145     if(context == null) {
146       context = new SqlContext();
147       app.setContext(context);
148     }
149     return context;
150   }
151 
152   /**
153    * Creates a new SqlContext (cloning current one if available), replaces the
154    * current SqlContext with the new SqlContext, and returns the new
155    * SqlContext.  All <code>pushContext</code> calls should have a
156    * corresponding {@link #popContext} call.
157    */
158   public static final SqlContext pushContext(AppendableExt app)
159   {
160     SqlContext parentContext = (SqlContext)app.getContext();
161     SqlContext context = null;
162     if(parentContext != null) {
163       context = parentContext.clone();
164       context.setParent(parentContext);
165     } else {
166       context = new SqlContext();
167     }
168     app.setContext(context);
169     return context;
170   }
171 
172   /**
173    * Replaces the current SqlContext (checking it against the given
174    * SqlContext) with the parent SqlContext (stored within the new one).  All
175    * <code>popContext</code> calls should come after a corresponding
176    * {@link #pushContext} call.
177    */
178   public static void popContext(AppendableExt app, SqlContext context)
179   {
180     if(app.getContext() != context) {
181       throw new IllegalStateException("Mismatched push/pop SqlContext");
182     }
183     app.setContext((context != null) ? context.getParent() : null);
184   }
185 
186   
187 }