All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.amattioli.dominate.hibernate.specifications.HqlAssembler Maven / Gradle / Ivy

The newest version!
package it.amattioli.dominate.hibernate.specifications;

import it.amattioli.dominate.repositories.Order;
import it.amattioli.dominate.specifications.Assembler;
import it.amattioli.dominate.specifications.dflt.PredicateAssembler;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Stack;

import org.apache.commons.collections.Predicate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HqlAssembler implements Assembler {
	private static final Logger logger = LoggerFactory.getLogger(HqlAssembler.class);
	private static final String WHERE = " where ";
	private static final String AND = " and ";
	private static final String OR = " or ";
	private static final String ALIAS = "entity_alias";
	private String initialHqlQuery;
	private StringBuilder joinsBuilder;
	private Stack stackedJunctions = new Stack();
	private String currentJunction = AND;
	private Collection paramSetters = new ArrayList();
	private PredicateAssembler additional;
	private List toBeAppended = new ArrayList();
	private Stack stackedPositions = new Stack();
	private List orders = new ArrayList();
	private boolean useAlias;
	
	public HqlAssembler(String hqlQuery, List orders) {
		this(hqlQuery,orders,true);
	}
	
	public HqlAssembler(String hqlQuery, List orders, boolean useAlias) {
		initialHqlQuery = hqlQuery;
		joinsBuilder = new StringBuilder("");
//		whereClauseBuilder = new StringBuilder("");
		this.orders = orders;
		this.useAlias = useAlias;
	}
	
	public void addAdditionalPredicate(Predicate pred) {
		if (!hasAdditionalPredicate()) {
			additional = new PredicateAssembler();
		}
		additional.addAssembledPredicate(pred);
	}
	
	public Predicate additionalPredicate() {
		if (!hasAdditionalPredicate()) {
			return null;
		}
		return additional.assembledPredicate();
	}

	public boolean hasAdditionalPredicate() {
		return additional != null;
	}
	
	private void push(String junction) {
		toBeAppended.add("(");
		stackedJunctions.push(currentJunction);
		currentJunction = junction;
		stackedPositions.push(toBeAppended.size()-1);
	}
	
	private void pop() {
		if (!nothingToAppend()) {
			toBeAppended.add(")");
		} else {
			int lastPosition = stackedPositions.peek();
			while(toBeAppended.size() > lastPosition) {
				toBeAppended.remove(toBeAppended.size() - 1);
			}
		}
		stackedPositions.pop();
		currentJunction = stackedJunctions.pop();
		removeUnneeded();
	}

	private boolean nothingToAppend() {
		int lastPosition = stackedPositions.peek();
		for (String curr: toBeAppended.subList(lastPosition, toBeAppended.size())) {
			if (!"(".equals(curr) && !" not ".equals(curr)) {
				return false;
			}
		}
		return true;
	}
	
	@Override
	public void startNegation() {
		newCriteria();
		toBeAppended.add(" not ");
		push("");
		stackedPositions.push(stackedPositions.pop() - 1);
	}
	
	@Override
	public void endNegation() {
		pop();
	}

	@Override
	public void startConjunction() {
		newCriteria();
		push(AND);
	}
	
	@Override
	public void endConjunction() {
		pop();
	}
	
	@Override
	public void startDisjunction() {
		newCriteria();
		push(OR);
	}
	
	@Override
	public void endDisjunction() {
		pop();
	}

	public void newCriteria() {
		if (toBeAppended.isEmpty()) {
			toBeAppended.add(WHERE);
        } else if (!nothingToAppend()) {
        	toBeAppended.add(currentJunction);
        }
	}
	
	public HqlAssembler append(String hqlFragment) {
		toBeAppended.add(hqlFragment);
		return this;
	}
	
	public void addParameter(final String name, final Object value) {
		paramSetters.add(new ParameterSetter() {

			@Override
			public void setParameter(Query query) {
				query.setParameter(name, value);
			}
			
		});
	}
	
	public void addParameter(ParameterSetter setter) {
		paramSetters.add(setter);
	}
	
	public String assembledHqlQueryString() {
		StringBuilder result = new StringBuilder("");
		if (joinsBuilder.length() != 0) {
			result.append("select ").append(getAlias()).append(" ");
		}
		result.append(initialHqlQuery);
		if (useAlias) {
			result.append(" ").append(getAlias()).append(" ");
		}
		if (joinsBuilder.length() != 0) {
			result.append(joinsBuilder.toString()).append(" ");
		}
		appendWhereAndOrder(result);
		logger.debug("Assembled HQL query: ",result);
		return result.toString();
	}
	
	private void appendWhereAndOrder(StringBuilder result) {
		removeUnneeded();
		StringBuilder whereClauseBuilder = new StringBuilder();
		for (String curr: toBeAppended) {
			whereClauseBuilder.append(curr);
		}
		result.append(whereClauseBuilder.toString()).append(getOrderClause());
	}

	private void removeUnneeded() {
		ArrayList toBeRemoved = new ArrayList() {{ add(currentJunction); add(WHERE);}};
		if (!toBeAppended.isEmpty() && toBeRemoved.contains(toBeAppended.get(toBeAppended.size() - 1))) {
			toBeAppended.remove(toBeAppended.size() - 1);
		}
	}
	
	private String assembledHqlWhereAndOrder() {
		StringBuilder result = new StringBuilder("");
		appendWhereAndOrder(result);
		logger.debug("Assembled HQL query: ",result);
		return result.toString();
	}
	
	public Query assembledHqlQuery(Session session) {
		Query result = session.createQuery(assembledHqlQueryString());
		for (ParameterSetter setter : paramSetters) {
			setter.setParameter(result);
		}
		return result;
	}
	
	public Query assembledHqlFilter(Session session, Collection content) {
		Query result = session.createFilter(content, assembledHqlWhereAndOrder());
		for (ParameterSetter setter : paramSetters) {
			setter.setParameter(result);
		}
		return result;
	}
	
	@Override
	public void noResults() {
		newCriteria();
		append("0 = 1");
	}

	public static interface ParameterSetter {
		public void setParameter(Query query);
	}

	public String getAlias() {
		return ALIAS;
	}
	
	public void addJoin(String join) {
		if (joinsBuilder.length() != 0) {
			joinsBuilder.append(" ");
		}
		joinsBuilder.append(join);
	}
	
	public String getAliasPrefix() {
		return useAlias ? getAlias() + "." : "";
	}
	
	private String getOrderClause() {
		StringBuilder builder = new StringBuilder("");
		for (Order order: orders) {
			if (builder.length() > 0) {
				builder.append(", ");
			} else {
				builder.append("order by ");
			}
			builder.append(getAliasPrefix() + order.getProperty() + (order.isReverse() ? " desc" : " asc"));
		}
		return builder.toString();
    }
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy