1 16 package org.outerj.daisy.query.model; 17 18 import org.outerj.daisy.query.QueryContext; 19 import org.outerj.daisy.repository.query.QueryException; 20 import org.outerj.daisy.repository.query.EvaluationContext; 21 import org.outerj.daisy.repository.Document; 22 import org.outerj.daisy.repository.Version; 23 24 import java.sql.PreparedStatement ; 25 import java.sql.SQLException ; 26 27 public abstract class UnaryPredicateExpr extends AbstractPredicateExpr { 28 protected final ValueExpr valueExpr1; 29 protected final ValueExpr valueExpr2; 30 31 public UnaryPredicateExpr(ValueExpr valueExpr1, ValueExpr valueExpr2) { 32 this.valueExpr1 = valueExpr1; 33 this.valueExpr2 = valueExpr2; 34 } 35 36 public void prepare(QueryContext context) throws QueryException { 37 valueExpr1.prepare(context); 38 valueExpr2.prepare(context); 39 40 if (valueExpr1.isSymbolicIdentifier() && valueExpr2.isSymbolicIdentifier()) 41 throw new QueryException("Two symbolic identifiers cannot be compared with each other: \"" + valueExpr1.getExpression() + "\" and \"" + valueExpr2.getExpression() + "\"."); 42 43 if ( (valueExpr1.isSymbolicIdentifier() && (valueExpr2.getValueType() == null || valueExpr2.getValueType() == QValueType.STRING)) 44 || (valueExpr2.isSymbolicIdentifier() && (valueExpr1.getValueType() == null || valueExpr1.getValueType() == QValueType.STRING))) { 45 } else if (!valueExpr1.getValueType().isCompatible(valueExpr2.getValueType())) { 47 throw new QueryException("Cannot use a comparison operator on two different types of data: expression \"" + valueExpr1.getExpression() + "\" is of type " + valueExpr1.getValueType() + " and expression \"" + valueExpr2.getExpression() + "\" is of type " + valueExpr2.getValueType()); 48 } 49 50 if ( (valueExpr1.getValueType() == QValueType.BOOLEAN || valueExpr2.getValueType() == QValueType.BOOLEAN 51 || valueExpr1.isSymbolicIdentifier() || valueExpr2.isSymbolicIdentifier() 52 || valueExpr1.isMultiValue() || valueExpr2.isMultiValue()) 53 && !makesSenseForNonOrderedValues()) { 54 throw new QueryException("The operator \"" + getOperatorSqlSymbol() + "\" is used between expressions that have no order-relation: \"" + valueExpr1.getExpression() + "\" and \"" + valueExpr2.getExpression() + "\"."); 55 } 56 } 57 58 protected boolean makesSenseForNonOrderedValues() { 59 return false; 60 } 61 62 public void generateSql(StringBuffer sql, SqlGenerationContext context) throws QueryException { 63 sql.append(" ("); 64 65 String valueExpr1PreCond = valueExpr1.getSqlPreConditions(context); 66 String valueExpr2PreCond = valueExpr2.getSqlPreConditions(context); 67 68 if (valueExpr1PreCond != null) 69 sql.append(' ').append(valueExpr1PreCond); 70 if (valueExpr2PreCond != null) { 71 if (valueExpr1PreCond != null) 72 sql.append(" and "); 73 sql.append(' ').append(valueExpr2PreCond); 74 } 75 76 if (valueExpr1PreCond != null || valueExpr2PreCond != null) 77 sql.append(" and "); 78 79 valueExpr1.generateSqlValueExpr(sql, context); 80 sql.append(getOperatorSqlSymbol()); 81 valueExpr2.generateSqlValueExpr(sql, context); 82 83 sql.append(")"); 84 } 85 86 protected abstract String getOperatorSqlSymbol(); 87 88 public int bindSql(PreparedStatement stmt, int bindPos, EvaluationContext evaluationContext) throws SQLException , QueryException { 89 bindPos = valueExpr1.bindPreConditions(stmt, bindPos); 90 bindPos = valueExpr2.bindPreConditions(stmt, bindPos); 91 92 QValueType valueType = determineValueType(); 93 94 if (valueExpr1.isSymbolicIdentifier() && valueExpr2.isSymbolicIdentifier()) { 95 throw new QueryException("Assertion error: cannot compare two symbolic identifiers: \"" + valueExpr1.getExpression() + "\" and \"" + valueExpr2.getExpression() + "\"."); 97 } else if (valueExpr1.isSymbolicIdentifier()) { 98 bindPos = valueExpr1.bindValueExpr(stmt, bindPos, valueType, evaluationContext); 99 bindPos = Literal.bindLiteral(stmt, bindPos, valueType, valueExpr1.translateSymbolic(valueExpr2, evaluationContext)); 100 } else if (valueExpr2.isSymbolicIdentifier()) { 101 bindPos = Literal.bindLiteral(stmt, bindPos, valueType, valueExpr2.translateSymbolic(valueExpr1, evaluationContext)); 102 bindPos = valueExpr2.bindValueExpr(stmt, bindPos, valueType, evaluationContext); 103 } else if (valueExpr1.isSymbolicIdentifier() && valueExpr2.isSymbolicIdentifier()) { 104 bindPos = Literal.bindLiteral(stmt, bindPos, valueType, valueExpr2.translateSymbolic(valueExpr1, evaluationContext)); 106 bindPos = Literal.bindLiteral(stmt, bindPos, valueType, valueExpr1.translateSymbolic(valueExpr2, evaluationContext)); 107 } else { 108 bindPos = valueExpr1.bindValueExpr(stmt, bindPos, valueType, evaluationContext); 109 bindPos = valueExpr2.bindValueExpr(stmt, bindPos, valueType, evaluationContext); 110 } 111 112 return bindPos; 113 } 114 115 private QValueType determineValueType() throws QueryException { 116 QValueType valueType; 117 if (valueExpr1.getValueType() == QValueType.UNDEFINED && valueExpr2.getValueType() == QValueType.UNDEFINED) { 118 valueType = QValueType.STRING; 121 } else if (valueExpr1.getValueType() == QValueType.UNDEFINED || valueExpr2.isSymbolicIdentifier()) { 122 valueType = valueExpr2.getValueType(); 123 } else if (valueExpr2.getValueType() == QValueType.UNDEFINED || valueExpr1.isSymbolicIdentifier()) { 124 valueType = valueExpr1.getValueType(); 125 } else { 126 if (valueExpr1.getValueType() != valueExpr2.getValueType()) 128 throw new QueryException("Assertion error: value types not the same."); 129 valueType = valueExpr1.getValueType(); 130 } 131 return valueType; 132 } 133 134 public AclConditionViolation isAclAllowed() { 135 AclConditionViolation violation = valueExpr1.isAclAllowed(); 136 if (violation != null) 137 return violation; 138 else 139 return valueExpr2.isAclAllowed(); 140 } 141 142 private boolean evaluateInt(Object value1, Object value2) { 143 if (value1 instanceof Object [] || value2 instanceof Object []) { 144 Object [] values1 = assureArray(value1); 146 Object [] values2 = assureArray(value2); 147 for (int i = 0; i < values1.length; i++) { 148 for (int j = 0; j < values2.length; j++) { 149 if (evaluate(values1[i], values2[j])) 150 return true; 151 } 152 } 153 return false; 154 } else { 155 return evaluate(value1, value2); 156 } 157 } 158 159 private Object [] assureArray(Object value) { 160 if (value instanceof Object []) { 161 return (Object [])value; 162 } else { 163 return new Object [] { value }; 164 } 165 } 166 167 protected abstract boolean evaluate(Object value1, Object value2); 168 169 public boolean evaluate(Document document, Version version, EvaluationContext evaluationContext) throws QueryException { 170 QValueType valueType = determineValueType(); 171 Object value1, value2; 172 if (valueExpr1.isSymbolicIdentifier() && valueExpr2.isSymbolicIdentifier()) { 173 throw new QueryException("Assertion error: cannot compare two symbolic identifiers: \"" + valueExpr1.getExpression() + "\" and \"" + valueExpr2.getExpression() + "\"."); 175 } else if (valueExpr1.isSymbolicIdentifier()) { 176 value1 = valueExpr1.evaluate(valueType, document, version, evaluationContext); 177 value2 = valueExpr1.translateSymbolic(valueExpr2, evaluationContext); 178 } else if (valueExpr2.isSymbolicIdentifier()) { 179 value1 = valueExpr2.translateSymbolic(valueExpr1, evaluationContext); 180 value2 = valueExpr2.evaluate(valueType, document, version, evaluationContext); 181 } else { 182 value1 = valueExpr1.evaluate(valueType, document, version, evaluationContext); 183 value2 = valueExpr2.evaluate(valueType, document, version, evaluationContext); 184 } 185 186 if (value1 == null || value2 == null) 187 return false; 188 189 return evaluateInt(value1, value2); 190 } 191 192 public Tristate appliesTo(Document document) throws QueryException { 193 if (valueExpr1.canTestAppliesTo() && valueExpr2.canTestAppliesTo()) { 194 return evaluate(document, null, new EvaluationContext()) ? Tristate.YES : Tristate.NO; 195 } else { 196 return Tristate.MAYBE; 197 } 198 } 199 } 200 | Popular Tags |