package com.idega.block.dataquery.data.xml; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import com.idega.util.StringHandler; import com.idega.xml.XMLElement; /** * <p>Title: idegaWeb</p> * <p>Description: </p> * <p>Copyright: Copyright (c) 2003</p> * <p>Company: idega Software</p> * @author <a href="thomas@idega.is">Thomas Hilbig</a> * @version 1.0 * Created on Nov 19, 2003 */ public class QueryBooleanExpressionPart implements QueryPart { private static final List booleanOperators; static { booleanOperators = new ArrayList(); booleanOperators.add("AND"); booleanOperators.add("OR"); booleanOperators.add("("); booleanOperators.add(")"); booleanOperators.add("NOT"); } private static final String WHITESPACE = " "; private static final String AND = "AND"; // do not choose prefix and suffix that are similar to the allowed operators! private static final String INVALID_ID_PREFIX = "["; private static final String INVALID_ID_SUFFIX = "]"; // trivial case or default case: // trivial case (no conditions) <=> expressionElements is empty, badSyntaxBooleanExpression is null, booleanExpressionIsValid is true // following states are allowed: // bad syntax <=> expressionElements is empty, badSyntaxBooleanExpression is not empty, booleanExpressionIsValid is false // syntax okay but not valid <=> expressionElements is not empty, badSyntaxBooleanExpression is null, booleanExpressionIsValid is false // valid <=> expressionElements is not empty, badSyntaxBooleanExpression is null, booleanExpressionIsValid is true private List expressionElements = new ArrayList(); private String badSyntaxBooleanExpression = null; private boolean booleanExpressionIsValid = true; private Set validIds = new HashSet(); private Set invalidIds = new HashSet(); public QueryBooleanExpressionPart() { } public QueryBooleanExpressionPart(XMLElement xml) { this(xml.getTextTrim()); } public QueryBooleanExpressionPart(String encoded) { StringTokenizer tokenizer = new StringTokenizer(encoded); while (tokenizer.hasMoreTokens()) { this.expressionElements.add(tokenizer.nextToken()); } } public static QueryBooleanExpressionPart decode(String encoded) { return new QueryBooleanExpressionPart(encoded); } /* (non-Javadoc) * @see com.idega.block.dataquery.data.xml.QueryPart#getQueryElement() */ public XMLElement getQueryElement() { XMLElement el = new XMLElement(QueryXMLConstants.BOOLEAN_EXPRESSION); el.setText(getBooleanExpression()); return el; } /* (non-Javadoc) * @see com.idega.block.dataquery.data.xml.QueryPart#encode() */ public String encode() { return getBooleanExpression(); } /* (non-Javadoc) * @see com.idega.block.dataquery.data.xml.QueryPart#isLocked() */ public boolean isLocked() { // TODO Auto-generated method stub return false; } /* (non-Javadoc) * @see com.idega.block.dataquery.data.xml.QueryPart#setLocked(boolean) */ public void setLocked(boolean locked) { // TODO Auto-generated method stub } public String updateConditions(List conditionParts, String newBooleanExpression) { if (conditionParts == null) { conditionParts = new ArrayList(0); } // move all valid ids to the list of invalid ids this.invalidIds.addAll(this.validIds); this.validIds.clear(); Iterator iteratorConditions = conditionParts.iterator(); while (iteratorConditions.hasNext()) { QueryConditionPart conditionPart = (QueryConditionPart) iteratorConditions.next(); String id = conditionPart.getId().toUpperCase(); this.validIds.add(id); this.invalidIds.remove(id); } // prepare list of allowed elements List allowedElements = new ArrayList(); allowedElements.addAll(QueryBooleanExpressionPart.booleanOperators); allowedElements.addAll(this.validIds); allowedElements.addAll(this.invalidIds); Iterator invalidElements = this.invalidIds.iterator(); while (invalidElements.hasNext()) { StringBuffer buffer = new StringBuffer(QueryBooleanExpressionPart.INVALID_ID_PREFIX).append((String)invalidElements.next()); buffer.append(QueryBooleanExpressionPart.INVALID_ID_SUFFIX); allowedElements.add(buffer.toString()); } this.expressionElements = StringHandler.getElementsIgnoreCase(newBooleanExpression, allowedElements); // represents the newBooleanExpression a valid expression? if (this.expressionElements == null) { // store the invalid boolean expression this.badSyntaxBooleanExpression = newBooleanExpression; // clear expressionElements this.expressionElements = new ArrayList(); // set invalid this.booleanExpressionIsValid = false; return null; } else { this.badSyntaxBooleanExpression = null; this.booleanExpressionIsValid = true; } int size = this.expressionElements.size(); // change invalid elements for (int i = 0; i < size; i++) { String element = (String) this.expressionElements.get(i); if (this.invalidIds.contains(element)) { // okay: syntax is okay but it contains invalid ids this.booleanExpressionIsValid = false; StringBuffer buffer = new StringBuffer(QueryBooleanExpressionPart.INVALID_ID_PREFIX).append(element); buffer.append(QueryBooleanExpressionPart.INVALID_ID_SUFFIX); this.expressionElements.set(i, buffer.toString()); } // there are already invalid elements else if (element.startsWith(INVALID_ID_PREFIX)) { this.booleanExpressionIsValid = false; } } // add new valids elements Iterator iterator = this.validIds.iterator(); while (iterator.hasNext()) { String element = (String) iterator.next(); if (! this.expressionElements.contains(element)) { if (! this.expressionElements.isEmpty()) { this.expressionElements.add(QueryBooleanExpressionPart.AND); } this.expressionElements.add(element); } } // return the new boolean expression return getBooleanExpression(); } public String getBadSyntaxBooleanExpression() { return this.badSyntaxBooleanExpression; } public String getBooleanExpression() { StringBuffer buffer = new StringBuffer(); Iterator iterator = this.expressionElements.iterator(); String whiteSpace = ""; while (iterator.hasNext()) { buffer.append(whiteSpace).append((String) iterator.next()); whiteSpace = QueryBooleanExpressionPart.WHITESPACE; } return buffer.toString(); } public boolean isBooleanExpressionValid() { return this.booleanExpressionIsValid; } public boolean isSyntaxOfBooleanExpressionOkay() { return this.badSyntaxBooleanExpression == null; } }