com.blazebit.persistence.view.EntityViewSetting Maven / Gradle / Ivy
/*
* Copyright 2014 - 2019 Blazebit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.blazebit.persistence.view;
import com.blazebit.persistence.CriteriaBuilder;
import com.blazebit.persistence.KeysetPage;
import com.blazebit.persistence.PaginatedCriteriaBuilder;
import com.blazebit.persistence.FullQueryBuilder;
import com.blazebit.persistence.view.metamodel.Attribute;
import com.blazebit.persistence.view.metamodel.MethodAttribute;
import java.util.*;
/**
* A {@linkplain EntityViewSetting} is a set of filters and sorters that can be
* applied to a {@link CriteriaBuilder}. Filters and sorters are added for
* entity view attribute names. It also supports pagination and optional
* parameters. Optional parameters are only set on a criteria builder if they
* are needed but not satisfied.
*
* @param The type of the entity view
* @param {@linkplain PaginatedCriteriaBuilder} if paginated, {@linkplain CriteriaBuilder} otherwise
* @author Christian Beikov
* @author Moritz Becker
* @since 1.0.0
*/
public final class EntityViewSetting> implements SubGraph {
private final Class entityViewClass;
private final String viewConstructorName;
private final Object entityId;
private final int firstResult;
private final int maxResults;
private final boolean paginated;
private final Set viewNamedFilters;
private final Map attributeSorters;
private final Map attributeFilters;
private final Map optionalParameters;
private final Map properties;
private final List fetches;
private KeysetPage keysetPage;
private boolean keysetPaginated;
private EntityViewSetting(Class entityViewClass, Object entityId, int maxResults, boolean paginate, String viewConstructorName) {
this.entityViewClass = entityViewClass;
this.viewConstructorName = viewConstructorName;
this.entityId = entityId;
this.firstResult = -1;
this.maxResults = maxResults;
this.paginated = paginate;
this.viewNamedFilters = new LinkedHashSet<>();
this.attributeSorters = new LinkedHashMap<>();
this.attributeFilters = new LinkedHashMap<>();
this.optionalParameters = new HashMap<>();
this.properties = new HashMap<>();
this.fetches = new ArrayList<>();
}
private EntityViewSetting(Class entityViewClass, int firstResult, int maxResults, boolean paginate, String viewConstructorName) {
if (firstResult < 0) {
throw new IllegalArgumentException("Invalid negative value for firstResult");
}
this.entityViewClass = entityViewClass;
this.viewConstructorName = viewConstructorName;
this.entityId = null;
this.firstResult = firstResult;
this.maxResults = maxResults;
this.paginated = paginate;
this.viewNamedFilters = new LinkedHashSet<>();
this.attributeSorters = new LinkedHashMap<>();
this.attributeFilters = new LinkedHashMap<>();
this.optionalParameters = new HashMap<>();
this.properties = new HashMap<>();
this.fetches = new ArrayList<>();
}
private EntityViewSetting(EntityViewSetting super T, ?> original, Class subtype) {
this.entityViewClass = subtype;
this.viewConstructorName = original.viewConstructorName;
this.entityId = original.entityId;
this.firstResult = original.firstResult;
this.maxResults = original.maxResults;
this.paginated = original.paginated;
this.keysetPage = original.keysetPage;
this.keysetPaginated = original.keysetPaginated;
this.viewNamedFilters = new LinkedHashSet<>(original.viewNamedFilters);
this.attributeSorters = new LinkedHashMap<>(original.attributeSorters);
this.attributeFilters = new LinkedHashMap<>(original.attributeFilters);
this.optionalParameters = new HashMap<>(original.optionalParameters);
this.properties = new HashMap<>(original.properties);
this.fetches = new ArrayList<>(original.fetches);
}
/**
* Like {@link EntityViewSetting#create(java.lang.Class, java.lang.String)} but with the viewConstructorname
set to null.
*
* @param entityViewClass The entity view class that should be used for the object builder
* @param The type of the entity view
* @return A new entity view setting
*/
public static EntityViewSetting> create(Class entityViewClass) {
return new EntityViewSetting>(entityViewClass, 0, Integer.MAX_VALUE, false, null);
}
/**
* Creates a new {@linkplain EntityViewSetting} that can be applied on
* criteria builders.
*
* @param entityViewClass The entity view class that should be used for the object builder
* @param viewConstructorName The name of the view constructor
* @param The type of the entity view
* @return A new entity view setting
*/
public static EntityViewSetting> create(Class entityViewClass, String viewConstructorName) {
return new EntityViewSetting>(entityViewClass, 0, Integer.MAX_VALUE, false, viewConstructorName);
}
/**
* Like {@link EntityViewSetting#create(java.lang.Class, int, int, java.lang.String)} but with the viewConstructorname
set to null.
*
* @param entityViewClass The entity view class that should be used for the object builder
* @param firstResult The position of the first result to retrieve, numbered from 0
* @param maxResults The maximum number of results to retrieve
* @param The type of the entity view
* @return A new entity view setting
*/
public static EntityViewSetting> create(Class entityViewClass, int firstResult, int maxResults) {
return new EntityViewSetting>(entityViewClass, firstResult, maxResults, true, null);
}
/**
* Like {@link EntityViewSetting#create(java.lang.Class, java.lang.Object, int, java.lang.String)} but with the viewConstructorname
set to null.
*
* @param entityViewClass The entity view class that should be used for the object builder
* @param entityId The id of the entity which should be located on a page
* @param maxResults The maximum number of results to retrieve
* @param The type of the entity view
* @return A new entity view setting
*/
public static EntityViewSetting> create(Class entityViewClass, Object entityId, int maxResults) {
return new EntityViewSetting>(entityViewClass, entityId, maxResults, true, null);
}
/**
* Creates a new {@linkplain EntityViewSetting} that can be applied on
* criteria builders.
*
* @param entityViewClass The entity view class that should be used for the object builder
* @param firstResult The position of the first result to retrieve, numbered from 0
* @param maxResults The maximum number of results to retrieve
* @param viewConstructorName The name of the view constructor
* @param The type of the entity view
* @return A new entity view setting
*/
public static EntityViewSetting> create(Class entityViewClass, int firstResult, int maxResults, String viewConstructorName) {
return new EntityViewSetting>(entityViewClass, firstResult, maxResults, true, viewConstructorName);
}
/**
* Creates a new {@linkplain EntityViewSetting} that can be applied on
* criteria builders.
*
* @param entityViewClass The entity view class that should be used for the object builder
* @param entityId The id of the entity which should be located on a page
* @param maxResults The maximum number of results to retrieve
* @param viewConstructorName The name of the view constructor
* @param The type of the entity view
* @return A new entity view setting
*/
public static EntityViewSetting> create(Class entityViewClass, Object entityId, int maxResults, String viewConstructorName) {
return new EntityViewSetting>(entityViewClass, entityId, maxResults, true, viewConstructorName);
}
/**
* Creates a copy of this
{@linkplain EntityViewSetting} for the given entity view subtype.
*
* @param subtype The entity view subtype
* @param Entity view subtype
* @param The query builder type
* @return A copy for the given subtype
*/
public > EntityViewSetting forSubtype(Class subtype) {
return new EntityViewSetting<>(this, subtype);
}
/**
* Returns the entity view class.
*
* @return The entity view class
*/
public Class getEntityViewClass() {
return entityViewClass;
}
/**
* Returns the entity view constructor name.
*
* @return The entity view constructor name
*/
public String getViewConstructorName() {
return viewConstructorName;
}
/**
* The id of the entity which should be located on the page returned result.
* Returns null
if no pagination or a absolute first result will be applied.
*
* @return The id of the entity which should be located on a page
* @see FullQueryBuilder#pageAndNavigate(java.lang.Object, int)
*/
public Object getEntityId() {
return entityId;
}
/**
* The first result that the criteria builder should return. Returns 0 if no
* pagination will be applied. Returns -1 if an entity id was supplied.
*
* @return The first result
* @see FullQueryBuilder#page(int, int)
*/
public int getFirstResult() {
return firstResult;
}
/**
* The maximum number of results that the criteria builder should return.
* Returns {@linkplain java.lang.Integer#MAX_VALUE} if no pagination will be
* applied.
*
* @return The maximum number of results
* @see FullQueryBuilder#page(int, int)
*/
public int getMaxResults() {
return maxResults;
}
/**
* Returns true if this entiy view setting applies pagination, false otherwise.
*
* @return True if this entiy view setting applies pagination, false otherwise
*/
public boolean isPaginated() {
return paginated;
}
/**
* Returns the key set of this setting.
*
* @return The key set of this setting
*/
public KeysetPage getKeysetPage() {
return keysetPage;
}
/**
* Sets the key set of this setting.
*
* @param keysetPage the new key set
* @return this setting for chaining
*/
public EntityViewSetting withKeysetPage(KeysetPage keysetPage) {
this.keysetPage = keysetPage;
this.keysetPaginated = true;
return this;
}
/**
* Returns true if this setting is key set paginated.
*
* @return true if this setting is key set paginated
*/
public boolean isKeysetPaginated() {
return keysetPaginated;
}
/**
* Adds the given attribute sorters to the attribute sorters of this
* setting. Note that the attribute sorter order is retained.
*
* @param attributeSorters The attribute sorters to add
*/
public void addAttributeSorters(Map attributeSorters) {
this.attributeSorters.putAll(attributeSorters);
}
/**
* Adds the given attribute sorter to the attribute sorters of this setting.
* Note that the attribute sorter order is retained.
*
* @param attributeName The name of the attribute sorter
* @param sorter The sorter for the attribute sorter
*/
public void addAttributeSorter(String attributeName, Sorter sorter) {
this.attributeSorters.put(attributeName, sorter);
}
/**
* Adds the given attribute sorter to the attribute sorters of this setting.
* Note that the attribute sorter order is retained.
*
* @param attributeName The name of the attribute sorter
* @param sorter The sorter for the attribute sorter
* @return this
for method chaining
* @since 1.3.0
*/
public EntityViewSetting withAttributeSorter(String attributeName, Sorter sorter) {
addAttributeSorter(attributeName, sorter);
return this;
}
/**
* Returns true if sorters have been added, otherwise false.
*
* @return true if sorters have been added, otherwise false
*/
public boolean hasAttributeSorters() {
return !attributeSorters.isEmpty();
}
/**
* Returns a copy of the attribute sorters that have been added.
*
* @return The attribute sorters
*/
public Map getAttributeSorters() {
return attributeSorters;
}
/**
* Adds the given attribute filters to the attribute filters of this
* setting.
*
* @param attributeFilters The attribute filters to add
*/
public void addAttributeFilters(Map attributeFilters) {
for (Map.Entry attributeFilterEntry : attributeFilters.entrySet()) {
addAttributeFilter(attributeFilterEntry.getKey(), attributeFilterEntry.getValue());
}
}
/**
* Adds the attribute's default attribute filter to the attribute filters of this setting
* or overwrites the filter value of an existing default attribute filter.
*
* @param attributeName The name of the attribute filter
* @param filterValue The filter value for the attribute filter
*/
public void addAttributeFilter(String attributeName, Object filterValue) {
checkExistingFiltersForAttribute(attributeName, AttributeFilter.DEFAULT_NAME);
this.attributeFilters.put(attributeName, new AttributeFilterActivation(filterValue));
}
/**
* Adds the attribute's default attribute filter to the attribute filters of this setting
* or overwrites the filter value of an existing default attribute filter.
*
* @param attributeName The name of the attribute filter
* @param filterValue The filter value for the attribute filter
* @return this
for method chaining
* @since 1.3.0
*/
public EntityViewSetting withAttributeFilter(String attributeName, Object filterValue) {
addAttributeFilter(attributeName, filterValue);
return this;
}
/**
* Adds the attribute's attribute filter with the given name to the attribute filters of this setting
* or overwrites the filter value of an existing attribute filter with the same attribute name and filter name.
*
* @param attributeName The attribute name
* @param filterName The filter name
* @param filterValue The filter value for the attribute filter
*/
public void addAttributeFilter(String attributeName, String filterName, Object filterValue) {
checkExistingFiltersForAttribute(attributeName, filterName);
this.attributeFilters.put(attributeName, new AttributeFilterActivation(filterName, filterValue));
}
/**
* Adds the attribute's attribute filter with the given name to the attribute filters of this setting
* or overwrites the filter value of an existing attribute filter with the same attribute name and filter name.
*
* @param attributeName The attribute name
* @param filterName The filter name
* @param filterValue The filter value for the attribute filter
* @return this
for method chaining
* @since 1.3.0
*/
public EntityViewSetting withAttributeFilter(String attributeName, String filterName, Object filterValue) {
addAttributeFilter(attributeName, filterName, filterValue);
return this;
}
private void checkExistingFiltersForAttribute(String attributeName, String attributeFilterName) {
AttributeFilterActivation attributeFilterActivation = this.attributeFilters.get(attributeName);
if (attributeFilterActivation != null) {
if (!attributeFilterActivation.getAttributeFilterName().equals(attributeFilterName)) {
throw new IllegalArgumentException("At most one active attribute filter per attribute is allowed! attributeName = '" + attributeName + "'");
}
}
}
/**
* Returns true if filters have been added, otherwise false.
*
* @return true if filters have been added, otherwise false
*/
public boolean hasAttributeFilters() {
return !attributeFilters.isEmpty() ;
}
/**
* Returns a copy of the attribute filters that have been added.
*
* @return The attribute filters
*/
public Map getAttributeFilters() {
return attributeFilters;
}
/**
* Enables and adds the view filter with the given name in this setting.
*
* @param filterName The name of the view filter
*/
public void addViewFilter(String filterName) {
this.viewNamedFilters.add(filterName);
}
/**
* Enables and adds the view filter with the given name in this setting.
*
* @param filterName The name of the view filter
* @return this
for method chaining
* @since 1.3.0
*/
public EntityViewSetting withViewFilter(String filterName) {
addViewFilter(filterName);
return this;
}
/**
* Returns true if named filters for the view have been added, otherwise false.
*
* @return true if named filters for the view have been added, otherwise false
*/
public boolean hasViewFilters() {
return !viewNamedFilters.isEmpty();
}
/**
* Returns a copy of the named filters for the view that have been added.
*
* @return The named filters for the view
*/
public Set getViewFilters() {
return viewNamedFilters;
}
/**
* Adds the given optional parameters to the optional parameters of this
* setting.
*
* @param optionalParameters The optional parameters to add
*/
public void addOptionalParameters(Map optionalParameters) {
this.optionalParameters.putAll(optionalParameters);
}
/**
* Adds the given optional parameter to the optional parameters of this
* setting.
*
* @param parameterName The name of the optional parameter
* @param value The value of the optional parameter
*/
public void addOptionalParameter(String parameterName, Object value) {
this.optionalParameters.put(parameterName, value);
}
/**
* Adds the given optional parameter to the optional parameters of this
* setting.
*
* @param parameterName The name of the optional parameter
* @param value The value of the optional parameter
* @return this
for method chaining
* @since 1.3.0
*/
public EntityViewSetting withOptionalParameter(String parameterName, Object value) {
addOptionalParameter(parameterName, value);
return this;
}
/**
* Returns true if optional parameters have been added, otherwise false.
*
* @return true if optional parameters have been added, otherwise false
*/
public boolean hasOptionalParameters() {
return !optionalParameters.isEmpty();
}
/**
* Returns a copy of the optional parameters that have been added.
*
* @return The optional parameters
*/
public Map getOptionalParameters() {
return optionalParameters;
}
/**
* Set a entity view property or hint.
* If a property or hint is not recognized, it is silently ignored.
* @param propertyName name of property or hint
* @param value value for property or hint
* @since 1.2.0
*/
public void setProperty(String propertyName, Object value) {
properties.put(propertyName, value);
}
/**
* Set a entity view property or hint.
* If a property or hint is not recognized, it is silently ignored.
* @param propertyName name of property or hint
* @param value value for property or hint
* @return this
for method chaining
* @since 1.3.0
*/
public EntityViewSetting withProperty(String propertyName, Object value) {
setProperty(propertyName, value);
return this;
}
/**
* Get the properties and hints and associated values that are in effect
* for the entity view setting.
* @return map of properties and hints in effect for entity view stting
* @since 1.2.0
*/
public Map getProperties() {
return Collections.unmodifiableMap(properties);
}
@Override
public SubGraph fetch(String path) {
fetches.add(path);
return new SubGraphImpl<>(path);
}
@Override
public SubGraph fetch(Attribute attribute) {
return fetch(((MethodAttribute, ?>) attribute).getName());
}
/**
* Returns the attributes that should be fetched or an empty collection if all should be fetched.
*
* @return the attributes that should be fetched or an empty collection if all should be fetched
* @since 1.4.0
*/
public Collection getFetches() {
return Collections.unmodifiableList(fetches);
}
/**
* The activation of a filter.
*
* @author Moritz Becker
* @since 1.2.0
*/
public static class AttributeFilterActivation {
private final String attributeFilterName;
private final Object filterValue;
private AttributeFilterActivation(Object filterValue) {
this(AttributeFilter.DEFAULT_NAME, filterValue);
}
private AttributeFilterActivation(String attributeFilterName, Object filterValue) {
this.attributeFilterName = attributeFilterName;
this.filterValue = filterValue;
}
public String getAttributeFilterName() {
return attributeFilterName;
}
public Object getFilterValue() {
return filterValue;
}
}
/**
* A simple subgraph.
*
* @author Christian Beikov
* @since 1.4.0
*/
private class SubGraphImpl implements SubGraph {
private final String parent;
private SubGraphImpl(String parent) {
this.parent = parent;
}
@Override
public SubGraph fetch(String path) {
String newParent = parent + "." + path;
return EntityViewSetting.this.fetch(newParent);
}
@Override
public SubGraph fetch(Attribute attribute) {
return fetch(((MethodAttribute, ?>) attribute).getName());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy