/*
* Copyright (c) 2010-2014 Evolveum
*
* 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.evolveum.midpoint.prism.query;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
public class ObjectPaging implements DebugDumpable, Serializable {
private Integer offset;
private Integer maxSize;
private List<ObjectOrdering> ordering = new ArrayList<>();
private String cookie;
protected ObjectPaging() {
}
ObjectPaging(Integer offset, Integer maxSize) {
this.offset = offset;
this.maxSize = maxSize;
}
ObjectPaging(ItemPath orderBy, OrderDirection direction) {
setOrdering(orderBy, direction);
}
ObjectPaging(Integer offset, Integer maxSize, ItemPath orderBy, OrderDirection direction) {
this.offset = offset;
this.maxSize = maxSize;
setOrdering(orderBy, direction);
}
public static ObjectPaging createPaging(Integer offset, Integer maxSize){
return new ObjectPaging(offset, maxSize);
}
public static ObjectPaging createPaging(Integer offset, Integer maxSize, QName orderBy, OrderDirection direction) {
return new ObjectPaging(offset, maxSize, new ItemPath(orderBy), direction);
}
public static ObjectPaging createPaging(Integer offset, Integer maxSize, ItemPath orderBy, OrderDirection direction) {
return new ObjectPaging(offset, maxSize, orderBy, direction);
}
public static ObjectPaging createPaging(Integer offset, Integer maxSize, List<ObjectOrdering> orderings) {
ObjectPaging paging = new ObjectPaging(offset, maxSize);
paging.setOrdering(orderings);
return paging;
}
public static ObjectPaging createPaging(ItemPath orderBy, OrderDirection direction) {
return new ObjectPaging(orderBy, direction);
}
public static ObjectPaging createPaging(QName orderBy, OrderDirection direction) {
return new ObjectPaging(new ItemPath(orderBy), direction);
}
public static ObjectPaging createEmptyPaging(){
return new ObjectPaging();
}
// TODO rename to getPrimaryOrderingDirection
public OrderDirection getDirection() {
ObjectOrdering primary = getPrimaryOrdering();
return primary != null ? primary.getDirection() : null;
}
// TODO rename to getPrimaryOrderingPath
public ItemPath getOrderBy() {
ObjectOrdering primary = getPrimaryOrdering();
return primary != null ? primary.getOrderBy() : null;
}
public ObjectOrdering getPrimaryOrdering() {
if (hasOrdering()) {
return ordering.get(0);
} else {
return null;
}
}
// TODO name?
public List<ObjectOrdering> getOrderingInstructions() {
return ordering;
}
public boolean hasOrdering() {
return ordering != null && !ordering.isEmpty(); // first is just for sure
}
public void setOrdering(ItemPath orderBy, OrderDirection direction) {
this.ordering = new ArrayList<>();
addOrderingInstruction(orderBy, direction);
}
public void addOrderingInstruction(ItemPath orderBy, OrderDirection direction) {
this.ordering.add(new ObjectOrdering(orderBy, direction));
}
public void addOrderingInstruction(QName orderBy, OrderDirection direction) {
addOrderingInstruction(new ItemPath(orderBy), direction);
}
public void setOrdering(ObjectOrdering... orderings) {
this.ordering = new ArrayList<>(Arrays.asList(orderings));
}
public void setOrdering(Collection<ObjectOrdering> orderings) {
this.ordering = orderings != null ? new ArrayList<>(orderings) : new ArrayList<>();
}
public Integer getOffset() {
return offset;
}
public void setOffset(Integer offset) {
this.offset = offset;
}
public Integer getMaxSize() {
return maxSize;
}
public void setMaxSize(Integer maxSize) {
this.maxSize = maxSize;
}
/**
* Returns the paging cookie. The paging cookie is used for optimization of paged searches.
* The presence of the cookie may allow the data store to correlate queries and associate
* them with the same server-side context. This may allow the data store to reuse the same
* pre-computed data. We want this as the sorted and paged searches may be quite expensive.
* It is expected that the cookie returned from the search will be passed back in the options
* when the next page of the same search is requested.
*
* It is OK to initialize a search without any cookie. If the datastore utilizes a re-usable
* context it will return a cookie in a search response.
*/
public String getCookie() {
return cookie;
}
/**
* Sets paging cookie. The paging cookie is used for optimization of paged searches.
* The presence of the cookie may allow the data store to correlate queries and associate
* them with the same server-side context. This may allow the data store to reuse the same
* pre-computed data. We want this as the sorted and paged searches may be quite expensive.
* It is expected that the cookie returned from the search will be passed back in the options
* when the next page of the same search is requested.
*
* It is OK to initialize a search without any cookie. If the datastore utilizes a re-usable
* context it will return a cookie in a search response.
*/
public void setCookie(String cookie) {
this.cookie = cookie;
}
public ObjectPaging clone() {
ObjectPaging clone = new ObjectPaging();
copyTo(clone);
return clone;
}
protected void copyTo(ObjectPaging clone) {
clone.offset = this.offset;
clone.maxSize = this.maxSize;
if (this.ordering != null) {
clone.ordering = new ArrayList<>(this.ordering);
} else {
clone.ordering = null;
}
clone.cookie = this.cookie;
}
@Override
public String debugDump() {
return debugDump(0);
}
@Override
public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
sb.append("Paging:");
if (getOffset() != null) {
sb.append("\n");
DebugUtil.indentDebugDump(sb, indent + 1);
sb.append("Offset: " + getOffset());
}
if (getMaxSize() != null) {
sb.append("\n");
DebugUtil.indentDebugDump(sb, indent + 1);
sb.append("Max size: " + getMaxSize());
}
if (hasOrdering()) {
sb.append("\n");
DebugUtil.indentDebugDump(sb, indent + 1);
sb.append("Ordering: ").append(ordering);
}
if (getCookie() != null) {
sb.append("\n");
DebugUtil.indentDebugDump(sb, indent + 1);
sb.append("Cookie: " + getCookie());
}
return sb.toString();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("PAGING: ");
if (this == null){
sb.append("null");
return sb.toString();
}
if (getOffset() != null){
sb.append("O: ");
sb.append(getOffset());
sb.append(",");
}
if (getMaxSize() != null){
sb.append("M: ");
sb.append(getMaxSize());
sb.append(",");
}
if (hasOrdering()) {
sb.append("ORD: ");
sb.append(ordering);
sb.append(", ");
}
if (getCookie() != null) {
sb.append("C:");
sb.append(getCookie());
}
return sb.toString();
}
@Override
public boolean equals(Object o) {
return equals(o, true);
}
public boolean equals(Object o, boolean exact) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
ObjectPaging that = (ObjectPaging) o;
if (offset != null ? !offset.equals(that.offset) : that.offset != null)
return false;
if (maxSize != null ? !maxSize.equals(that.maxSize) : that.maxSize != null)
return false;
if ((ordering != null && that.ordering == null) || (ordering == null && that.ordering != null)) {
return false;
}
if (ordering != null) {
if (ordering.size() != that.ordering.size()) {
return false;
}
for (int i = 0; i < ordering.size(); i++) {
ObjectOrdering oo1 = this.ordering.get(i);
ObjectOrdering oo2 = that.ordering.get(i);
if (!oo1.equals(oo2, exact)) {
return false;
}
}
}
return cookie != null ? cookie.equals(that.cookie) : that.cookie == null;
}
@Override
public int hashCode() {
int result = offset != null ? offset.hashCode() : 0;
result = 31 * result + (maxSize != null ? maxSize.hashCode() : 0);
result = 31 * result + (ordering != null ? ordering.hashCode() : 0);
result = 31 * result + (cookie != null ? cookie.hashCode() : 0);
return result;
}
}