001    package org.apache.ojb.broker.query;
002    
003    /* Copyright 2002-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import java.util.List;
019    import java.util.Map;
020    
021    /**
022     * abstract baseclass of all criteria classes, can't be instantiated.
023     * 
024     * This code is based on stuff from 
025     * COBRA - Java Object Persistence Layer
026     * Copyright (C) 1997, 1998    DB Harvey-George
027     * eMail: cobra@lowrent.org
028    
029     * @author DB Harvey-George
030     * @author Thomas Mahler
031     * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
032     * @version $Id: SelectionCriteria.java,v 1.1 2007-08-24 22:17:36 ewestfal Exp $
033     */
034    public abstract class SelectionCriteria implements java.io.Serializable
035    {
036            static final long serialVersionUID = -5194901539702756536L;    protected static final String EQUAL = " = ";
037        protected static final String NOT_EQUAL = " <> ";
038        protected static final String GREATER = " > ";
039        protected static final String NOT_GREATER = " <= ";
040        protected static final String LESS = " < ";
041        protected static final String NOT_LESS = " >= ";
042        protected static final String LIKE = " LIKE ";
043        protected static final String NOT_LIKE = " NOT LIKE ";
044        protected static final String IS_NULL = " IS NULL ";
045        protected static final String NOT_IS_NULL = " IS NOT NULL ";
046        protected static final String BETWEEN = " BETWEEN ";
047        protected static final String NOT_BETWEEN = " NOT BETWEEN ";
048        protected static final String IN = " IN ";
049        protected static final String NOT_IN = " NOT IN ";
050    
051            private Object m_attribute;
052            private Object m_value;
053    
054    
055            // BRJ: true if criterion is bound
056            private boolean m_bound = false;
057    
058            // BRJ: the criterion must be bound for the main class and for all extents
059            private int m_numberOfExtentsToBind = 0; 
060    
061            private String m_alias = null;
062            private UserAlias m_userAlias = null;
063                
064        // BRJ: indicate whether attribute name should be translated into column name
065        private boolean m_translateAttribute = true;
066    
067        private Criteria m_criteria;
068        
069            /**
070             * Constructor declaration
071             *
072             * @param anAttribute  column- or fieldName or a Query
073             * @param aValue  the value to compare with
074             * @param negative  criteria is negated (ie NOT LIKE instead of LIKE)
075             * @param alias  use alias to link anAttribute to
076             */
077            SelectionCriteria(Object anAttribute, Object aValue, String alias)
078            {
079                    if (!(anAttribute instanceof String || anAttribute instanceof Query))
080                    {
081                            throw new IllegalArgumentException("An attribute must be a String or a Query !");
082                    }    
083                
084                    m_attribute = anAttribute;
085                    m_value = aValue;
086                    this.m_bound = !isBindable();
087                    this.m_alias = alias;
088                    this.m_userAlias  = m_alias == null ? null : new UserAlias(m_alias, (String)getAttribute(), true);
089            }
090    
091            /**
092             * Constructor declaration
093             *
094             * @param anAttribute  column- or fieldName or a Query
095             * @param aValue  the value to compare with
096             * @param aUserAlias  userAlias to link anAttribute to
097             */
098            SelectionCriteria(Object anAttribute, Object aValue, UserAlias aUserAlias)
099            {
100                    if (!(anAttribute instanceof String || anAttribute instanceof Query))
101                    {
102                            throw new IllegalArgumentException("An attribute must be a String or a Query !");
103                    }
104    
105                    m_attribute = anAttribute;
106                    m_value = aValue;
107                    this.m_bound = !isBindable();
108                    this.m_userAlias = aUserAlias;
109                    this.m_alias = m_userAlias == null ? null : m_userAlias.getName();
110            }
111    
112            /**
113             * Answer the SQL compare-clause for this criteria
114             */
115            abstract public String getClause();
116    
117            /**
118             * sets the value of the criteria to newValue. Used by the ODMG OQLQuery.bind() operation
119             */
120            public void bind(Object newValue)
121            {
122                    setValue(newValue);
123                    setBound(true);
124            }
125    
126            /**
127             * Answer the value
128             */
129            public Object getValue()
130            {
131                    return m_value;
132            }
133    
134            /**
135             * Answer the attribute
136             */
137            public Object getAttribute()
138            {
139                    return m_attribute;
140            }
141    
142            /**
143             * String representation
144             */
145            public String toString()
146            {
147                    return m_attribute + getClause() + m_value;
148            }
149    
150            /**
151             * BRJ : Used by the ODMG OQLQuery.bind() operation
152             * @return Returns a boolean indicator
153             */
154            public boolean isBound()
155            {
156                    return m_bound;
157            }
158    
159            /**
160             * Sets the bound.
161             * @param bound The bound to set
162             */
163            protected void setBound(boolean bound)
164            {
165                    this.m_bound = bound;
166            }
167    
168            /**
169             * Sets the value.
170             * @param value The value to set
171             */
172            protected void setValue(Object value)
173            {
174                    this.m_value = value;
175            }
176    
177            /**
178             * answer true if the selection criteria is bindable 
179             * BRJ: value null is bindable
180             */
181            protected boolean isBindable()
182            {
183                    return (getValue() == null);
184            }
185            /**
186             * Returns the numberOfExtentsToBind.
187             * @return int
188             */
189            public int getNumberOfExtentsToBind()
190            {
191                    return m_numberOfExtentsToBind;
192            }
193    
194            /**
195             * Sets the numberOfExtentsToBind.
196             * @param numberOfExtentsToBind The numberOfExtentsToBind to set
197             */
198            public void setNumberOfExtentsToBind(int numberOfExtentsToBind)
199            {
200                    this.m_numberOfExtentsToBind = numberOfExtentsToBind;
201            }
202    
203            /**
204             * @return String
205             */
206            public String getAlias()
207            {
208                    return m_alias;
209            }
210    
211            /**
212             * Sets the alias. By default the entire attribute path participates in the alias
213             * @param alias The name of the alias to set
214             */
215            public void setAlias(String alias)
216            {
217                    m_alias = alias;
218                    String attributePath = (String)getAttribute();
219                    boolean allPathsAliased = true;
220                    m_userAlias = new UserAlias(alias, attributePath, allPathsAliased);
221                    
222            }
223    
224            /**
225             * Sets the alias. 
226             * @param alias The alias to set
227             */
228            public void setAlias(String alias, String aliasPath)
229            {
230                    m_alias = alias;
231                    m_userAlias = new UserAlias(alias, (String)getAttribute(), aliasPath);
232            }
233            
234            /**
235             * Sets the alias using a userAlias object. 
236             * @param userAlias The alias to set
237             */
238            public void setAlias(UserAlias userAlias)
239            {
240                    m_alias = userAlias.getName();
241                    m_userAlias = userAlias;
242            }
243    
244            public UserAlias getUserAlias()
245            {
246                    return m_userAlias;
247            }
248            /**
249             * @return true if attribute name should be translated into column name
250             */
251            public boolean isTranslateAttribute()
252            {
253                    return m_translateAttribute;
254            }
255    
256            /**
257             * @param b
258             */
259            void setTranslateAttribute(boolean b)
260            {
261                    m_translateAttribute = b;
262            }
263    
264            /**
265             * @return
266             */
267            public Criteria getCriteria()
268            {
269                    return m_criteria;
270            }
271    
272            /**
273             * @param criteria
274             */
275            void setCriteria(Criteria criteria)
276            {
277                    m_criteria = criteria;
278            }
279    
280        public QueryByCriteria getQuery()
281        {
282            if (getCriteria() != null)
283            {
284                return getCriteria().getQuery();
285            }
286            else
287            {
288                return null;
289            }
290        }
291        
292            /**
293             * Gets the pathClasses from the parent Criteria.
294             * A Map containing hints about what Class to be used for what path segment
295             * @return Returns a Map
296             */
297            public Map getPathClasses()
298            {
299                    return getCriteria().getPathClasses();
300            }
301    
302            /**
303             * Get the a List of Class objects used as hints for a path
304             *
305             * @param aPath the path segment ie: allArticlesInGroup
306             * @return a List o Class objects to be used in SqlStatment
307             * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
308             */
309            public List getClassesForPath(String aPath)
310            {
311                    return getCriteria().getClassesForPath(aPath);
312            }
313    }