001/** 002 * Copyright 2015 Tampere University of Technology, Pori Department 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 */ 016package core.tut.pori.dao.clause; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.List; 021 022import org.apache.commons.lang3.ArrayUtils; 023 024/** 025 * A simple SQL WHERE AND clause. 026 * 027 * This class will always prefix the clause with AND, and giving multiple values equals to SQL AND IN (?,?,...) 028 * 029 * Passing null object, null array or empty array equals to providing the clause with SQL NULL. An array can also have a null value. 030 */ 031public class AndClause extends WhereClause{ 032 private String _column = null; 033 private SQLType[] _types = null; 034 private Object[] _values = null; 035 private boolean _not = false; 036 private boolean _hasNull = false; 037 038 @Override 039 public SQLType[] getValueTypes() { 040 return _types; 041 } 042 043 @Override 044 public Object[] getValues() { 045 return _values; 046 } 047 048 /** 049 * 050 * @param column 051 * @param values 052 */ 053 public AndClause(String column, int[] values){ 054 _column = column; 055 setValues(ArrayUtils.toObject(values), SQLType.INTEGER); 056 } 057 058 /** 059 * 060 * @param column 061 * @param values 062 */ 063 public AndClause(String column, long[] values){ 064 _column = column; 065 setValues(ArrayUtils.toObject(values), SQLType.LONG); 066 } 067 068 /** 069 * 070 * @param column 071 * @param values 072 */ 073 public AndClause(String column, double[] values){ 074 _column = column; 075 setValues(ArrayUtils.toObject(values), SQLType.DOUBLE); 076 } 077 078 /** 079 * 080 * @param column 081 * @param values 082 */ 083 public AndClause(String column, boolean[] values){ 084 _column = column; 085 setValues(ArrayUtils.toObject(values), SQLType.BOOLEAN); 086 } 087 088 /** 089 * @param column 090 * @param value can be null 091 * @param type type of data 092 */ 093 public AndClause(String column, Object value, SQLType type){ 094 setValues(new Object[]{value}, type); 095 _column = column; 096 } 097 098 /** 099 * 100 * @param column 101 * @param values 102 * @param type 103 */ 104 public AndClause(String column, Collection<? extends Object> values, SQLType type){ 105 _column = column; 106 Object[] o = null; 107 if(values != null){ 108 o = values.toArray(); 109 } 110 setValues(o, type); 111 } 112 113 /** 114 * Note: this does creates an IN () clause based on the list of values, NOT multiple AND clauses 115 * that include all of the given values. This is because no column can have more than a single value, 116 * and thus, creating AND for all of the given values would not make sense. 117 * 118 * @param column 119 * @param values can be null 120 * @param type type of data 121 */ 122 public AndClause(String column, Object[] values, SQLType type){ 123 setValues(values, type); 124 _column = column; 125 } 126 127 /** 128 * 129 * @param values 130 * @param type 131 */ 132 public void setValues(Object[] values, SQLType type){ 133 _values = null; 134 _types = null; 135 if(!ArrayUtils.isEmpty(values)){ 136 List<SQLType> types = new ArrayList<>(values.length); 137 for(int i=0;i<values.length;++i){ 138 if(values[i] == null){ 139 _hasNull = true; 140 values = ArrayUtils.remove(values, i--); // remove the current value and decrease counter 141 continue; 142 } 143 types.add(type); 144 } // for 145 if(!types.isEmpty()){ 146 _values = values; 147 _types = types.toArray(new SQLType[types.size()]); 148 } 149 }else{ 150 _hasNull = true; 151 } 152 } 153 154 @Override 155 public void toSQLString(StringBuilder sql) { 156 sql.append('('); 157 if(_values != null){ 158 sql.append(_column); 159 if(_not){ 160 sql.append(" NOT IN ("); 161 }else{ 162 sql.append(" IN ("); 163 } 164 sql.append('?'); 165 for(int i=1;i<_values.length;++i){ 166 sql.append(",?"); 167 } 168 if(_hasNull){ 169 sql.append(") OR "); 170 }else{ 171 sql.append(')'); 172 } 173 } 174 if(_hasNull){ 175 sql.append(_column); 176 if(_not){ 177 sql.append(" IS NOT NULL"); 178 }else{ 179 sql.append(" IS NULL"); 180 } 181 } 182 sql.append(')'); 183 } 184 185 /** 186 * 187 * @param not set this to be NOT clause on true, remove NOT declaration on false 188 * @return this 189 */ 190 public AndClause setNot(boolean not){ 191 _not = not; 192 return this; 193 } 194 195 @Override 196 public ClauseType getClauseType() { 197 return ClauseType.AND; 198 } 199}