package jpasearch.repository.query.builder;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SingularAttribute;
import jpasearch.repository.query.OrderByDirection;
import jpasearch.repository.query.Path;
import jpasearch.repository.query.SearchParameters;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* @author speralta
*/
public class SearchBuilder<FROM> implements Serializable {
private static final long serialVersionUID = 201403271745L;
private final PaginationBuilder<FROM> paginationBuilder;
private final OrdersByBuilder<FROM> ordersByBuilder;
private final FetchesBuilder<FROM> fetchesBuilder;
private final RootSelectorsBuilder<FROM> rootSelectorsBuilder;
// extra parameters
private final Map<String, Object> extraParameters;
private boolean useDistinct;
public SearchBuilder() {
paginationBuilder = new PaginationBuilder<>(this);
ordersByBuilder = new OrdersByBuilder<>(this);
fetchesBuilder = new FetchesBuilder<>(this);
rootSelectorsBuilder = new RootSelectorsBuilder<>(this);
extraParameters = new HashMap<>();
useDistinct = false;
}
public SearchBuilder(SearchParameters<FROM> searchParameters) {
paginationBuilder = new PaginationBuilder<>(this, searchParameters.getFirstResult(), searchParameters.getMaxResults());
ordersByBuilder = new OrdersByBuilder<>(this, searchParameters.getOrders());
fetchesBuilder = new FetchesBuilder<>(this, searchParameters.getFetches());
rootSelectorsBuilder = new RootSelectorsBuilder<>(this, searchParameters.getSelectors());
extraParameters = new HashMap<>(searchParameters.getExtraParameters());
useDistinct = searchParameters.isUseDistinct();
}
public SearchParameters<FROM> build() {
return new SearchParameters<FROM>(paginationBuilder.getFirstResult(), //
paginationBuilder.getMaxResults(), //
rootSelectorsBuilder.getSelectors(), //
fetchesBuilder.getFetches(), //
ordersByBuilder.getOrders(), //
extraParameters, //
useDistinct);
}
// -----------------------------------
// Order by support
// -----------------------------------
public <TO> OrderByBuilder<FROM, FROM, TO> orderBy(SingularAttribute<? super FROM, TO> attribute) {
return ordersByBuilder.by(attribute);
}
public <TO> OrderByBuilder<FROM, FROM, TO> orderBy(PluralAttribute<? super FROM, ?, TO> attribute) {
return ordersByBuilder.by(attribute);
}
public SearchBuilder<FROM> orderBy(OrderByDirection direction, String path, Class<FROM> from) {
ordersByBuilder.orderBy(direction, path, from);
return this;
}
// -------------------------------------
// SearchParameters by selectors support
// -------------------------------------
public <TO> RangeBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>> range(SingularAttribute<? super FROM, TO> attribute) {
return new RangeBuilder<>(rootSelectorsBuilder, attribute);
}
public <TO> RangeBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>> range(PluralAttribute<? super FROM, ?, TO> attribute) {
return new RangeBuilder<>(rootSelectorsBuilder, attribute);
}
public <TO extends Comparable<? super TO>> RangeFinalBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>> rangeOn(SingularAttribute<? super FROM, TO> attribute) {
return new RangeFinalBuilder<>(rootSelectorsBuilder, attribute);
}
public <TO extends Comparable<? super TO>> RangeFinalBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>> rangeOn(PluralAttribute<? super FROM, ?, TO> attribute) {
return new RangeFinalBuilder<>(rootSelectorsBuilder, attribute);
}
public <TO> TermSelectorPathBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>, SearchBuilder<FROM>> fullText(SingularAttribute<? super FROM, TO> attribute) {
return new TermSelectorBuilder<>(rootSelectorsBuilder).on(attribute);
}
public <TO> TermSelectorPathBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>, SearchBuilder<FROM>> fullText(PluralAttribute<? super FROM, ?, TO> attribute) {
return new TermSelectorBuilder<>(rootSelectorsBuilder).on(attribute);
}
public <TO> SelectorBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>> on(Path<FROM, TO> path) {
return rootSelectorsBuilder.on(path);
}
public <TO> SelectorBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>> on(SingularAttribute<? super FROM, TO> attribute) {
return rootSelectorsBuilder.on(attribute);
}
public <TO> SelectorBuilder<FROM, FROM, TO, RootSelectorsBuilder<FROM>> on(PluralAttribute<? super FROM, ?, TO> attribute) {
return rootSelectorsBuilder.on(attribute);
}
public DisjunctionSelectorsBuilder<FROM, RootSelectorsBuilder<FROM>> disjunction() {
return rootSelectorsBuilder.disjunction();
}
// -----------------------------------
// Pagination support
// -----------------------------------
public SearchBuilder<FROM> paginate(int first, int count) {
paginationBuilder.firstResult(first).maxResult(count);
return this;
}
// -----------------------------------------
// Fetch associated entity using a LEFT Join
// -----------------------------------------
public <TO> FetchBuilder<FROM, FROM, TO> fetch(SingularAttribute<? super FROM, TO> attribute) {
return fetchesBuilder.fetch(attribute);
}
public <TO> FetchBuilder<FROM, FROM, TO> fetch(PluralAttribute<? super FROM, ?, TO> attribute) {
return fetchesBuilder.fetch(attribute);
}
// -----------------------------------
// Extra parameters
// -----------------------------------
/**
* add additionnal parameter.
*/
public SearchBuilder<FROM> addExtraParameter(String key, Object o) {
extraParameters.put(checkNotNull(key), o);
return this;
}
// -----------------------------------
// Distinct
// -----------------------------------
public SearchBuilder<FROM> distinct() {
useDistinct = true;
return this;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}