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

com.ivanceras.db.api.Query Maven / Gradle / Ivy

There is a newer version: 0.1.2
Show newest version
package com.ivanceras.db.api;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.ivanceras.db.model.ModelMetaData;
import com.ivanceras.db.shared.DAO;
import com.ivanceras.db.shared.Filter;
import com.ivanceras.db.shared.Order;
import com.ivanceras.db.shared.exception.DatabaseException;

/**
 * 
 * @author lee
 *
 */
public class Query {

	private List involvedModels = new ArrayList();
	private List joinPairs = new LinkedList() ;
	private List orders = new LinkedList();
	private List filters = new LinkedList();
	private Integer page;
	private Integer itemsPerPage;
	private Boolean selectAllColumns = false;
	private boolean enumerateColumns = true;
	private Boolean distinct;
	private List distinctColumns = new ArrayList();
	/**
	 * Ignore column feature when updating objects
	 */
	private List excludedColumns = new ArrayList();
	private Boolean keysOnly;
	private List aggregate = new ArrayList();
	private List groupedColumns = new ArrayList();
	private ModelMetaData meta = null;
	private EntityManager em = null;
	private Map columnSubQuery = new HashMap();
	private Query baseQuery = null;
	private String queryString = null;
	private List combinedQuery = new ArrayList();
	private String baseQueryName;
	private Map declaredQuery = new LinkedHashMap();
	private List windowFunctions = new ArrayList();
	private QueryAnalysis analyzer;

	public Query(EntityManager em, Class daoClass) throws DatabaseException{
		this.em = em;
		ModelDef model = em.getDefinition(daoClass);
		meta = em.getDB().getModelMetaDataDefinition();
		analyzer = new QueryAnalysis(this); 
		involve(model);
	}

	public Query(ModelDef model){
		analyzer = new QueryAnalysis(this); 
		involve(model);
	}

	public Query(ModelMetaData meta, Class daoClass) throws DatabaseException{
		this.meta = meta;
		analyzer = new QueryAnalysis(this); 
		ModelDef model = meta.getDefinition(daoClass);
		involve(model);
	}

	public Query(String queryString){
		this.setQueryString(queryString);
		analyzer = new QueryAnalysis(this); 
	}

	public Query addAggregate(Aggregate... aggregate) {
		if(aggregate != null && aggregate.length > 0){
			this.enumerateColumns = false; // do not enumerate when there is an aggregate
			String[] column1 = new String[aggregate.length];
			String[] column2 = new String[aggregate.length];
			for(int i = 0; i < aggregate.length; i++){
				Aggregate aggr = aggregate[i];
				column1[i] = aggr.getColumn();
				column2[i] = aggr.getAsColumn();
				this.aggregate.add(aggr);

			}
		}
		return this;
	}

	public Query addColumnSubQuery(String column, Query subquery) {
		columnSubQuery.put(column, subquery);
		return this;
	}


	//	public Query(ModelMetaData meta, Class daoClass, TreeRecursion tree) throws DatabaseException{
	//		this.meta = meta;
	//		ModelDef model = meta.getDefinition(daoClass);
	//		analyzer = new QueryAnalysis(this); 
	//
	//		String declaration = "child";
	//		Query query1 = new Query(meta, daoClass);
	//		Filter[] startingFilter = tree.getFilters();
	//		query1.addFilter(startingFilter);
	//		Query query2 = new Query(meta, daoClass);
	//		ModelDef childModel = new ModelDef();
	//
	//		childModel.setModelName(declaration);
	//		involve(childModel);//First Involved Model is the Table to be Queried, So child is the first involved Model
	//		involve(model);//Then put in the rest
	//
	//		query2.addJoinPair(new JoinPair(meta.getDefinition(daoClass), childModel, new ColumnPair(tree.parentColumn, tree.column), Join.INNER));
	//		query1.combine(query2, Combine.UNION, false);
	//
	//		declare(declaration, null, query1, true);
	//		setSelectAllColumns();
	//
	//	}

	//	public Query(EntityManager em, Class daoClass, TreeRecursion tree) throws DatabaseException{
	//		this(em.getDB().getModelMetaDataDefinition(), daoClass, tree);
	//		this.em = em;
	//		analyzer = new QueryAnalysis(this); 
	//}

	public Query addFilter(Filter... filters) {
		if(filters != null){
			for(Filter f : filters){
				this.filters.add(f);
			}
		}
		return this;
	}

	public Query addGroupedColumns(String modelName, String groupedColumn, String function) {
		StringBuffer colC = new StringBuffer();
		if(function != null){
			colC.append(function+"(");
		}
		if(modelName != null){
			colC.append(modelName+".");
		}
		colC.append(groupedColumn);
		if(function != null){
			colC.append(")");
		}
		this.groupedColumns.add(colC.toString());
		return this;
	}

	public Query addGroupedColumns(String modelName, String[] groupedColumns) {
		for(String col : groupedColumns){
			StringBuffer colC = new StringBuffer();
			if(modelName != null){
				colC.append(modelName+".");
			}
			colC.append(col);
			this.groupedColumns.add(colC.toString());
		}
		return this;
	}

	public Query addJoinPair(JoinPair... joinPairs) {
		if(joinPairs != null && joinPairs.length > 0){
			for(JoinPair j : joinPairs){
				this.joinPairs.add(j);
				ModelDef model1 = j.getModel1();
				ModelDef model2 = j.getModel2();
				if(model1 != null){
					involve(model1);
				}
				if(model2 != null){
					involve(model2);
				}
			}
		}
		return this;
	}

	public Query addOrder(Order... orders) {
		if(orders != null && orders.length > 0){
			for(Order o : orders){
				this.orders.add(o);
			}
		}
		return this;
	}

	public Query addWindowFunctions(WindowFunction windowFunctions) {
		this.windowFunctions.add(windowFunctions);
		return this;
	}

	public Query ascending(String... columns) {
		for(String c : columns){
			addOrder(new Order(c, Order.ASCENDING));
		}
		return this;
	}

	public Query combine(Query query, String combineType, boolean all){
		String combineModifier = null;
		if(all){
			combineModifier = Combine.ALL;
		}
		combinedQuery.add(new CombinedQuery(query, combineType, combineModifier));
		return this;
	}

	public Query copy(){

		Query copy = new Query(getModel());
		copy.involvedModels = involvedModels;
		copy.joinPairs = joinPairs;
		copy.orders = orders;
		copy.filters = filters;
		copy.page = page;
		copy.itemsPerPage = itemsPerPage;
		copy.selectAllColumns = selectAllColumns;
		copy.enumerateColumns = enumerateColumns;
		copy.distinct = distinct;
		copy.distinctColumns = distinctColumns;
		copy.keysOnly = keysOnly;
		copy.aggregate = aggregate;
		copy.groupedColumns = groupedColumns;
		copy.meta = meta;
		copy.em = em;
		copy.columnSubQuery = columnSubQuery;
		copy.baseQuery = baseQuery;
		copy.queryString = queryString;
		copy.combinedQuery = combinedQuery;
		copy.baseQueryName = baseQueryName;
		copy.declaredQuery = declaredQuery;
		copy.windowFunctions = windowFunctions;

		return copy;
	}

	/**
	 * When there is a need to have an inner query, 
	 * this will be using with query in postgresql http://www.postgresql.org/docs/9.1/static/queries-with.html
	 * @param name
	 * @param columns
	 * @param query
	 * @param recursive
	 */
	public Query declare(String name, String[] columns, Query query, boolean recursive){
		if(columns == null){//select all columns when no columns is specified
			query.setSelectAllColumns();
		}
		declaredQuery.put(name, new DeclaredQuery(name, columns, query, recursive));
		return this;
	}

	public Query descending(String... columns) {
		for(String c : columns){
			addOrder(new Order(c, Order.DESCENDING));
		}
		return this;
	}

	public Query excludeColumns(String... excludeColumns) {
		if(excludeColumns != null){
			for(String c : excludeColumns){
				this.excludedColumns.add(c);
			}
		}
		return this;
	}

	public Query filter(String column, String operator, Object value) {
		filters.add(new Filter(column, operator, value));
		return this;
	}

	public Aggregate[] getAggregate() {
		return aggregate.toArray(new Aggregate[aggregate.size()]);
	}

	public Query getBaseQuery() {
		return baseQuery;
	}

	public String getBaseQueryName() {
		return baseQueryName;
	}

	public Map getColumnSubQuery(){
		return columnSubQuery;
	}

	public CombinedQuery[] getCombinedQuery(){
		return combinedQuery.toArray(new CombinedQuery[combinedQuery.size()]);
	}

	public Map getDeclaredQueries(){
		if(declaredQuery.size() == 0){
			return null;
		}
		return declaredQuery;
	}

	public DeclaredQuery getDeclaredQuery(String name){
		return declaredQuery.get(name);
	}

	public Boolean getDistinct() {
		return distinct;
	}

	public String[] getDistinctColumns() {
		if(distinctColumns.size() == 0 ){
			return null;
		}
		return distinctColumns.toArray(new String[distinctColumns.size()]);
	}

	public String[] getExcludedColumns() {
		return excludedColumns.toArray(new String[excludedColumns.size()]);
	} 


	public Filter[] getFilters() {
		if(filters.size() == 0 ){
			return null;
		}
		return filters.toArray(new Filter[filters.size()]);
	}

	public String[] getGroupedColumns() {
		if(groupedColumns.size() == 0 ){
			return null;
		}
		return groupedColumns.toArray(new String[groupedColumns.size()]);
	}

	public ModelDef[] getInvolvedModels(){
		return involvedModels.toArray(new ModelDef[involvedModels.size()]);
	}

	public Integer getItemsPerPage() {
		return itemsPerPage;
	}

	public JoinPair[] getJoinPairs() {
		if(joinPairs.size() == 0 ){
			return null;
		}
		return joinPairs.toArray(new JoinPair[joinPairs.size()]);
	}

	public Boolean getKeysOnly() {
		return keysOnly;
	}

	public Integer getLimit(){
		return itemsPerPage;
	}

	public ModelDef getModel(){
		if(involvedModels.size() > 0){
			return involvedModels.get(0);
		}
		return null;
	}

	public Long getOffset(){
		if(page == null){
			return null;
		}
		else if(page != null && page <= 0){
			String msg = "Page shoud be positive integer starting from 1";
			System.err.println(msg);
		}
		else if(itemsPerPage != null){
			Long offset = (long) (((long)page -1) * (long)itemsPerPage); 
			return offset;
		}
		return null;
	}

	public Order[] getOrders() {
		if(orders.size() == 0 ){
			return null;
		}
		return orders.toArray(new Order[orders.size()]);
	}

	public Integer getPage() {
		return page;
	}

	public String getQueryString() {
		return queryString;
	}

	public String getRenamed(ModelDef model, String column){
		return analyzer.getRenamed(model, column);
	}

	public Map getRenamedColumnPairs(){
		return analyzer.getRenamedColumnPairs();
	}

	public Boolean getSelectAllColumns() {
		return selectAllColumns;
	}

	public List getWindowFunctions() {
		return windowFunctions;
	}

	private void involve(ModelDef model){
		if(!involvedModels.contains(model)){
			analyzer.determineConflictingColumns(model);
			involvedModels.add(model);
		}
	}

	public boolean isEnumerateColumns() {
		return enumerateColumns;
	}

	public void rename(Class daoClass, String column, String asColumn){
		ModelDef model = meta.getDefinition(daoClass);
		analyzer.rename(model, column, asColumn);
	}

	public Query setBaseQuery(Query baseQuery, String baseQueryName) {
		this.baseQuery = baseQuery;
		this.baseQueryName = baseQueryName;
		return this;
	}

	public void setBaseQueryName(String baseQueryName) {
		this.baseQueryName = baseQueryName;
	}

	public Query setDistinct() {
		this.distinct = true;
		return this;
	}


	public Query setDistinct(Boolean distinct) {
		this.distinct = distinct;
		return this;
	}


	public Query setDistinctColumns(String... distinctColumns) {
		if(distinctColumns != null && distinctColumns.length > 0){
			for(String col : distinctColumns){
				this.distinctColumns.add(col);
			}
			this.distinct = true;
		}
		return this;
	}

	public Query setEnumerateColumns(boolean enumerateColumns) {
		this.enumerateColumns = enumerateColumns;
		return this;
	}

	public Query setItemsPerPage(Integer itemsPerPage) {
		this.itemsPerPage = itemsPerPage;
		return this;
	}

	public Query setKeysOnly() {
		this.keysOnly = true;
		return this;
	}

	public Query setKeysOnly(Boolean keysOnly) {
		this.keysOnly = keysOnly;
		return this;
	}

	public Query setLimit(Integer limit){
		itemsPerPage = limit;
		return this;
	}

	//	private void setMeta(ModelMetaData meta){
	//		this.meta = meta;
	//		analyzer = new QueryAnalysis(this); 
	//	}

	public Query setPage(Integer page) {
		this.page = page;
		return this;
	}

	public void setQueryString(String queryString) {
		this.queryString = queryString;
	}

	public Query setSelectAllColumns() {
		this.selectAllColumns = true;
		this.enumerateColumns = false;
		return this;
	}

	public Query setSelectAllColumns(Boolean selectAllColumns) {
		this.selectAllColumns = selectAllColumns;
		return this;
	}

	public boolean hasConflictedColumn(String column) {
		return analyzer.hasConflictedColumn(column);
	}

	public  T[] execute() throws DatabaseException {
		return em.retrieveRecords(this);
	}


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy