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

de.tsl2.nano.service.util.finder.Finder Maven / Gradle / Ivy

Go to download

TSL2 JEE Service Access (Generic Services for Entity Access, JEE File-System-Connector, Generic Featuring, Job-Scheduling, BeanContainer, Batch, Comfortable Bean Query Definitions, JAAS, Authentification, Authorization, )

The newest version!
/*
 * File: $HeadURL$
 * Id  : $Id$
 * 
 * created by: Thomas Schneider, Thomas Schneider
 * created on: Sep 21, 2012
 * 
 * Copyright: (c) Thomas Schneider 2012, all rights reserved
 */
package de.tsl2.nano.service.util.finder;

import static de.tsl2.nano.service.util.ServiceUtil.getLogInfo;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;

import de.tsl2.nano.bean.BeanContainer;
import de.tsl2.nano.core.ManagedException;
import de.tsl2.nano.core.log.LogFactory;
import de.tsl2.nano.core.util.StringUtil;

/**
 * Finder provider - usable for IQueryService.
 * 
 * @author Thomas Schneider, Thomas Schneider
 * @version $Revision$
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public final class Finder {
    private static Log LOG = LogFactory.getLog(Finder.class);

    public static , T> T findOne(FINDER... finder) {
    	Collection find = find(finder);
    	if (find.size() != 1)
    		throw new IllegalStateException("exptected result of count=1, but was: " + find.size());
    	return find.iterator().next();
    }
    /** convenience, delegating to {@link #createQuery(Collection, Collection, AbstractFinder...)} */
    public static , T> Collection find(FINDER... finder) {
    	List parameter = new LinkedList<>();
    	return BeanContainer.instance().getBeansByQuery(createQuery(parameter, new LinkedList<>(), finder), false, parameter.toArray());
    }

    /**
     * creates the query for the given finders
     * 
     * @param  finder-type
     * @param  result bean type
     * @param parameter parameter collection to be filled by this method
     * @param lazyRelations relation types to be filled by this method
     * @param finder at least one finder
     * @return query string
     */
    public static , T> String createQuery(Collection parameter,
            Collection> lazyRelations,
            FINDER... finder) {
        if (finder.length == 0) {
            throw ManagedException.illegalState("at least one finder must be defined!", parameter);
        } else if (finder[0].getResultType() == null) {
            throw ManagedException.illegalArgument(finder[0], "the first finder must define a resultType!");
        }
        StringBuffer qStr = new StringBuffer();//createStatement(finder[0].getResultType());
        for (int i = 0; i < finder.length; i++) {
            finder[i].addToQuery(i, qStr, parameter, lazyRelations);
            finder[i].getMaxResult();
        }
        arrangeParameterIndexes(qStr, 0, 0);
        LOG.debug(getLogInfo(qStr, parameter));
        return qStr.toString();
    }

    static void arrangeParameterIndexes(StringBuffer qStr, int fromIndex, int parameterIndex) {
		int pi = qStr.indexOf("?", fromIndex);
		if (pi == -1 || qStr.indexOf("?X") == -1)
			return;
		++parameterIndex;
		if (qStr.substring(pi, pi+2).equals("?X"))
			qStr.replace(pi+1, pi+2, String.valueOf(parameterIndex));
		arrangeParameterIndexes(qStr, pi+1, parameterIndex);
	}

	/**
     * creates an or-condition for the given finder
     * @param  finder type
     * @param  result type
     * @param finder finder
     * @return given finder with influenced or-condition
     */
    public static , T> FINDER or(FINDER finder) {
        return finder.setOrConnection();
    }
    /**
     * creates an and-condition (default) for the given finder
     * @param  finder type
     * @param  result type
     * @param finder finder
     * @return given finder with influenced and-condition
     */
    public static , T> FINDER and(FINDER finder) {
        return finder.setAndConnection();
    }
    /**
     * creates an and-not-condition for the given finder
     * @param  finder type
     * @param  result type
     * @param finder finder
     * @return given finder with influenced and-not-condition
     */
    public static , T> FINDER not(FINDER finder) {
        return finder.setNotConnection();
    }
    /**
     * id
     * 
     * @param  result bean type
     * @param id id to search for
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return Id finder expression
     */
    public static  Id id(Class type, Object id, Class... relationsToLoad) {
        return new Id(type, id, relationsToLoad);
    }

    /**
     * all
     * 
     * @param  result bean type
     * @param id id to search for
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return Id finder expression
     */
    public static  All all(Class type, Class... relationsToLoad) {
        return new All(type, relationsToLoad);
    }
    /**
     * between
     * 
     * @param  result bean type
     * @param minObject min object
     * @param maxObject max object
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return Between finder expression
     */
    public static  Between between(T minObject, T maxObject, Class... relationsToLoad) {
        return new Between(minObject, maxObject, relationsToLoad);
    }

    /**
     * example
     * 
     * @param  result bean type
     * @param example example object
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return Example finder expression
     */
    public static  Example example(T example, Class... relationsToLoad) {
        return new Example(example, relationsToLoad);
    }

    public static  Member member(H holder,
            Class beanType,
            Class... relationsToLoad) {
    	return member(holder, beanType, StringUtil.toFirstLower(holder.getClass().getSimpleName()), relationsToLoad);
    }
    /**
     * member
     * 
     * @param  result bean type and holder type
     * @param holder holder object
     * @param beanType member bean type
     * @param attributeName attribute name of bean type
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return Member finder expression
     */
    public static  Member member(H holder,
            Class beanType,
            String attributeName,
            Class... relationsToLoad) {
        return new Member(holder, beanType, attributeName, relationsToLoad);
    }

    public static  Holder holder(T member,
            Class holderType,
            Class... relationsToLoad) {
        return holder(member, holderType, StringUtil.toFirstLower(member.getClass().getSimpleName()), relationsToLoad);
    }

    /**
     * holder
     * 
     * @param  result bean type and holder type
     * @param member member object
     * @param beanType member bean type
     * @param attributeName attribute name of bean type
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return Member finder expression
     */
    public static  Holder holder(T member,
            Class holderType,
            String attributeName,
            Class... relationsToLoad) {
        return new Holder(member, holderType, attributeName, relationsToLoad);
    }

    /**
     * in selection
     * 
     * @param  result bean type
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return InSelection expression
     */
    public static  InSelection inSelection(Class resultType, String attribute, Collection selection, Class... relationsToLoad) {
        return new InSelection(resultType, attribute, selection, relationsToLoad);
    }

    /**
     * expression
     * 
     * @param  result bean type
     * @param expression query expression
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return query finder expression
     */
    public static  Expression expression(Class resultType,
            String queryString,
            boolean asSubSelect,
            Object[] args,
            Class... relationsToLoad) {
        return new Expression(resultType, queryString, asSubSelect, args, relationsToLoad);
    }

    /**
     * order by
     * 
     * @param  result bean type
     * @param attributeNames order by names
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return order by expression
     */
    public static  OrderBy orderBy(Class resultType, String... attributeNames) {
        return new OrderBy(resultType, attributeNames);
    }

    /**
     * group by
     * 
     * @param  result bean type
     * @param attributeNames group by names
     * @param relationsToLoad lazy collections to be preloaded. makes only sense on remote access.
     * @return order by expression
     */
    public static  GroupBy groupBy(Class resultType, String... attributeNames) {
        return new GroupBy(attributeNames);
    }

    /**
     * union
     * 
     * @param  result bean type
     * @return union expression
     */
    public static  Union union(Class resultType) {
        return new Union(resultType);
    }

}