1 16 package org.outerj.daisy.query.model; 17 18 import org.outerj.daisy.repository.Document; 19 import org.outerj.daisy.repository.Version; 20 import org.outerj.daisy.repository.RepositoryException; 21 import org.outerj.daisy.repository.VariantKey; 22 import org.outerj.daisy.repository.query.QueryException; 23 import org.outerj.daisy.repository.query.EvaluationContext; 24 import org.outerj.daisy.query.QueryContext; 25 import org.outerj.daisy.util.Constants; 26 27 import java.math.BigDecimal ; 28 import java.text.SimpleDateFormat ; 29 import java.text.ParseException ; 30 import java.util.Date ; 31 import java.util.Locale ; 32 import java.util.regex.Matcher ; 33 import java.sql.PreparedStatement ; 34 import java.sql.SQLException ; 35 import java.sql.Timestamp ; 36 37 public final class Literal implements ValueExpr { 38 private final String stringValue; 39 private final String originalToken; 40 private QueryContext queryContext; 41 private int line = -1; 42 private int column = -1; 43 44 public Literal(final String value, final String originalToken) { 45 this.stringValue = value; 46 this.originalToken = originalToken; 47 } 48 49 public void setLocation(int line, int column) { 50 this.line = line; 51 this.column = column; 52 } 53 54 public String getLocation() { 55 if (line == -1 && column == -1) 56 return "(location unknown)"; 57 else 58 return "line " + line + ", column " + column; 59 } 60 61 public int getLine() { 62 return line; 63 } 64 65 public int getColumn() { 66 return column; 67 } 68 69 public Object evaluate(QValueType valueType, EvaluationContext evaluationContext) throws QueryException { 70 return evaluate(valueType); 71 } 72 73 public Object evaluate(QValueType valueType) throws QueryException { 74 if (valueType == QValueType.STRING) { 75 return stringValue; 76 } else if (valueType == QValueType.LONG) { 77 long longValue; 78 try { 79 longValue = Long.parseLong(stringValue); 80 } catch (NumberFormatException e) { 81 throw new QueryException("Invalid long value: \"" + stringValue + "\".", e); 82 } 83 return new Long (longValue); 84 } else if (valueType == QValueType.DOUBLE) { 85 double doubleValue; 86 try { 87 doubleValue = Double.parseDouble(stringValue); 88 } catch (NumberFormatException e) { 89 throw new QueryException("Invalid double value: \"" + stringValue + "\".", e); 90 } 91 return new Double (doubleValue); 92 } else if (valueType == QValueType.DECIMAL) { 93 return new BigDecimal (stringValue); 94 } else if (valueType == QValueType.DATE) { 95 SimpleDateFormat dateFormat = new SimpleDateFormat ("yyyy-MM-dd"); 96 dateFormat.setLenient(false); 97 Date dateValue; 98 try { 99 dateValue = dateFormat.parse(stringValue); 100 } catch (ParseException e) { 101 throw new QueryException("Invalid date value: \"" + stringValue + "\".", e); 102 } 103 return dateValue; 104 } else if (valueType == QValueType.DATETIME) { 105 SimpleDateFormat dateTimeFormat = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); 106 dateTimeFormat.setLenient(false); 107 Date dateTimeValue; 108 try { 109 dateTimeValue = dateTimeFormat.parse(stringValue); 110 } catch (ParseException e) { 111 throw new QueryException("Invalid datetime value: \"" + stringValue + "\".", e); 112 } 113 return dateTimeValue; 114 } else if (valueType == QValueType.BOOLEAN) { 115 if (stringValue.equalsIgnoreCase("true")) 116 return Boolean.TRUE; 117 else if (stringValue.equalsIgnoreCase("false")) 118 return Boolean.FALSE; 119 else 120 throw new QueryException("Invalid boolean value: \"" + stringValue + "\" (should be 'true' or 'false')."); 121 } else if (valueType == QValueType.LINK) { 122 Matcher matcher = Constants.DAISY_LINK_PATTERN.matcher(stringValue); 126 if (!matcher.matches()) 127 throw new QueryException("Invalid link: \"" + stringValue + "\". Should be of the form daisy:docid@branch:lang"); 128 129 String docId = matcher.group(1); 130 String branch = matcher.group(3); 131 String language = matcher.group(5); 132 133 if (branch == null || branch.length() == 0) 134 branch = "1"; 135 if (language == null || language.length() == 0) 136 language = "1"; 137 138 if (!Character.isDigit(branch.charAt(0))) { 139 try { 140 branch = String.valueOf(queryContext.getBranchByName(branch).getId()); 141 } catch (RepositoryException e) { 142 throw new QueryException("Problem with branch in link \"" + stringValue + "\".", e); 143 } 144 } 145 146 if (!Character.isDigit(language.charAt(0))) { 147 try { 148 language = String.valueOf(queryContext.getLanguageByName(language).getId()); 149 } catch (RepositoryException e) { 150 throw new QueryException("Problem with language in link \"" + stringValue + "\".", e); 151 } 152 } 153 154 return docId + "@" + branch + ":" + language; 155 } else { 156 throw new QueryException("Unsupported value type: " + valueType); 157 } 158 } 159 160 public Object evaluate(QValueType valueType, Document document, Version version, EvaluationContext evaluationContext) throws QueryException { 161 return evaluate(valueType); 162 } 163 164 public boolean isMultiValue() { 165 return false; 166 } 167 168 public void prepare(QueryContext context) { 169 this.queryContext = context; 170 } 171 172 public boolean isOutputOnly() { 173 return false; 174 } 175 176 public AclConditionViolation isAclAllowed() { 177 return null; 178 } 179 180 public String getSqlPreConditions(SqlGenerationContext context) { 181 return null; 182 } 183 184 public void generateSqlValueExpr(StringBuffer sql, SqlGenerationContext context) { 185 sql.append(" ? "); 186 } 187 188 public int bindPreConditions(PreparedStatement stmt, int bindPos) { 189 return bindPos; 190 } 191 192 public int bindValueExpr(PreparedStatement stmt, int bindPos, QValueType valueType, 193 EvaluationContext evaluationContext) throws SQLException , QueryException { 194 if (valueType == null || valueType == QValueType.UNDEFINED) 195 stmt.setString(bindPos, (String )evaluate(valueType)); 196 else if (valueType == QValueType.LONG) 197 stmt.setLong(bindPos, ((Long )evaluate(valueType)).longValue()); 198 else if (valueType == QValueType.STRING) 199 stmt.setString(bindPos, (String )evaluate(valueType)); 200 else if (valueType == QValueType.DATE) 201 stmt.setDate(bindPos, new java.sql.Date (((Date )evaluate(valueType)).getTime())); 202 else if (valueType == QValueType.DATETIME) 203 stmt.setTimestamp(bindPos, new Timestamp (((Date )evaluate(valueType)).getTime())); 204 else if (valueType == QValueType.DECIMAL) 205 stmt.setBigDecimal(bindPos, (BigDecimal )evaluate(valueType)); 206 else if (valueType == QValueType.DOUBLE) 207 stmt.setDouble(bindPos, ((Double )evaluate(valueType)).doubleValue()); 208 else if (valueType == QValueType.BOOLEAN) 209 stmt.setBoolean(bindPos, ((Boolean )evaluate(valueType)).booleanValue()); 210 else if (valueType == QValueType.LINK) 211 stmt.setString(bindPos, (String )evaluate(valueType)); 212 else 213 throw new RuntimeException ("Unrecognized valuetype: " + valueType); 214 215 return ++bindPos; 216 } 217 218 221 public static int bindLiteral(PreparedStatement stmt, int bindPos, QValueType valueType, Object value) throws SQLException { 222 if (value == null) { 223 stmt.setObject(bindPos, null); 224 } else if (valueType == QValueType.LONG) 225 stmt.setLong(bindPos, ((Long )value).longValue()); 226 else if (valueType == QValueType.STRING) 227 stmt.setString(bindPos, (String )value); 228 else if (valueType == QValueType.DATE) 229 stmt.setDate(bindPos, new java.sql.Date (((Date )value).getTime())); 230 else if (valueType == QValueType.DATETIME) 231 stmt.setTimestamp(bindPos, new Timestamp (((Date )value).getTime())); 232 else if (valueType == QValueType.DECIMAL) 233 stmt.setBigDecimal(bindPos, (BigDecimal )value); 234 else if (valueType == QValueType.DOUBLE) 235 stmt.setDouble(bindPos, ((Double )value).doubleValue()); 236 else if (valueType == QValueType.BOOLEAN) 237 stmt.setBoolean(bindPos, ((Boolean )value).booleanValue()); 238 else if (valueType == QValueType.LINK) { 239 VariantKey variantKey = (VariantKey)value; 240 String link = variantKey.getDocumentId() + "@" + variantKey.getBranchId() + ":" + variantKey.getLanguageId(); 241 stmt.setString(bindPos, link); 242 } else 243 throw new RuntimeException ("Unrecognized valuetype: " + valueType); 244 245 return ++bindPos; 246 } 247 248 public QValueType getValueType() { 249 return QValueType.UNDEFINED; 250 } 251 252 public boolean isSymbolicIdentifier() { 253 return false; 254 } 255 256 public Object translateSymbolic(ValueExpr valueExpr, EvaluationContext evaluationContext) throws QueryException { 257 throw new QueryException("translateSymbolic should not be called if isSymbolic returns false"); 258 } 259 260 public String getTitle(Locale locale) { 261 return "(literal)"; 262 } 263 264 public String getExpression() { 265 return originalToken; 266 } 267 268 public QValueType getOutputValueType() { 269 return QValueType.STRING; 271 } 272 273 public Object getOutputValue(Document document, Version version, EvaluationContext evaluationContext) { 274 return stringValue; 276 } 277 278 public boolean canTestAppliesTo() { 279 return true; 280 } 281 } 282 | Popular Tags |