View Javadoc

1   package org.apache.torque.sql.whereclausebuilder;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.commons.lang.StringUtils;
26  import org.apache.torque.TorqueException;
27  import org.apache.torque.adapter.Adapter;
28  import org.apache.torque.criteria.Criteria;
29  import org.apache.torque.criteria.Criterion;
30  import org.apache.torque.criteria.PreparedStatementPart;
31  import org.apache.torque.criteria.SqlEnum;
32  import org.apache.torque.sql.WhereClauseExpression;
33  
34  /**
35   * Builds a PreparedStatementPart from a WhereClauseExpression containing
36   * a Like operator.
37   *
38   * @version $Id: InBuilder.java 1377555 2012-08-27 02:52:28Z tfischer $
39   */
40  public class InBuilder extends AbstractWhereClausePsPartBuilder
41  {
42      /**
43       * Takes a columnName and criteria and
44       * builds a SQL 'IN' expression taking into account the ignoreCase
45       * flag.
46       *
47       * @param whereClausePart the part of the where clause to build.
48       *        Can be modified in this method.
49       * @param ignoreCase If true and columns represent Strings, the appropriate
50       *        function defined for the database will be used to ignore
51       *        differences in case.
52       * @param adapter The adapter for the database for which the SQL
53       *        should be created, not null.
54       */
55      public PreparedStatementPart buildPs(
56                  WhereClauseExpression whereClausePart,
57                  boolean ignoreCase,
58                  Adapter adapter)
59              throws TorqueException
60      {
61          PreparedStatementPart result = new PreparedStatementPart();
62  
63          boolean ignoreCaseApplied = false;
64          List<String> inClause = new ArrayList<String>();
65          boolean nullContained = false;
66          if (whereClausePart.getRValue() instanceof Iterable)
67          {
68              for (Object listValue : (Iterable<?>) whereClausePart.getRValue())
69              {
70                  if (listValue == null)
71                  {
72                      nullContained = true;
73                      continue;
74                  }
75                  result.getPreparedStatementReplacements().add(listValue);
76                  if (ignoreCase && listValue instanceof String)
77                  {
78                      inClause.add(adapter.ignoreCase("?"));
79                      ignoreCaseApplied = true;
80                  }
81                  else
82                  {
83                      inClause.add("?");
84                  }
85              }
86          }
87          else if (whereClausePart.getRValue().getClass().isArray())
88          {
89              for (Object arrayValue : (Object[]) whereClausePart.getRValue())
90              {
91                  if (arrayValue == null)
92                  {
93                      nullContained = true;
94                      continue;
95                  }
96                  result.getPreparedStatementReplacements().add(arrayValue);
97                  if (ignoreCase && arrayValue instanceof String)
98                  {
99                      inClause.add(adapter.ignoreCase("?"));
100                     ignoreCaseApplied = true;
101                 }
102                 else
103                 {
104                     inClause.add("?");
105                 }
106             }
107         }
108         else
109         {
110             throw new IllegalArgumentException(
111                     "Unknown rValue type "
112                     + whereClausePart.getRValue().getClass().getName()
113                     + ". rValue must be an instance of "
114                     + " Iterable or Array");
115         }
116 
117         if (nullContained)
118         {
119             result.getSql().append('(');
120         }
121 
122         result.append(getObjectOrColumnPsPartBuilder().buildPs(
123                 whereClausePart.getLValue(),
124                 ignoreCaseApplied,
125                 adapter));
126 
127         result.getSql().append(whereClausePart.getOperator())
128                 .append('(')
129                 .append(StringUtils.join(inClause.iterator(), ","))
130                 .append(')');
131         if (nullContained)
132         {
133             if (whereClausePart.getOperator() == SqlEnum.IN)
134             {
135                 result.getSql().append(Criterion.OR);
136                 result.append(getObjectOrColumnPsPartBuilder().buildPs(
137                         whereClausePart.getLValue(),
138                         false,
139                         adapter));
140                 result.getSql().append(SqlEnum.ISNULL);
141             }
142             else if (whereClausePart.getOperator() == SqlEnum.NOT_IN)
143             {
144                 result.getSql().append(Criterion.AND);
145                 result.append(getObjectOrColumnPsPartBuilder().buildPs(
146                         whereClausePart.getLValue(),
147                         false,
148                         adapter));
149                 result.getSql().append(SqlEnum.ISNOTNULL);
150             }
151             result.getSql().append(')');
152         }
153         return result;
154     }
155 
156     /**
157      * {@inheritDoc}
158      */
159     public boolean isApplicable(
160             WhereClauseExpression whereClauseExpression,
161             Adapter adapter)
162     {
163         if (whereClauseExpression.getOperator().equals(Criteria.IN)
164                 || whereClauseExpression.getOperator().equals(Criteria.NOT_IN))
165         {
166             if (!(whereClauseExpression.getRValue() instanceof Criteria))
167             {
168                 return true;
169             }
170         }
171         return false;
172     }
173 }