Skip to content

Instantly share code, notes, and snippets.

@vmencik
Created February 23, 2013 09:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vmencik/5019110 to your computer and use it in GitHub Desktop.
Save vmencik/5019110 to your computer and use it in GitHub Desktop.
package models;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PaginationData {
public static final String SPECIAL_RUNOVER = "runover";
public static final String SPECIAL_ELLIPSIS = "ellipsis";
private int count;
private int offset;
private boolean runover;
private int pageSize = 20;
private int forwardCnt = 4;
private int backwardCnt = 4;
private int headCnt = 3;
private int tailCnt = 4;
private String param = "pos";
private int maxOffset;
private boolean consoleEnds;
private boolean indexByPage;
private boolean indexByPageIndex;
private boolean independentVicinity;
// Offset of the first vicinity page
private int vicinityStart;
// Offset of the last vicinity page
private int vicinityEnd;
private boolean duplicateEnds;
private Map<Integer, Page> pageCache = new HashMap<Integer, Page>();
PageAddressAdapter addrAdapter;
public static interface PageAddressAdapter {
Object makePageAddress(int offset);
}
public void setAddressAdapter(PageAddressAdapter aa) {
this.addrAdapter = aa;
}
public boolean isIndependentVicinity() {
return independentVicinity;
}
public void setIndependentVicinity(boolean independentVicinity) {
this.independentVicinity = independentVicinity;
}
public boolean isIndexByPage() {
return indexByPage;
}
public void setIndexByPage(boolean indexByPage) {
this.indexByPage = indexByPage;
}
public boolean isIndexByPageIndex() {
return indexByPageIndex;
}
public void setIndexByPageIndex(boolean indexByPageIndex) {
this.indexByPageIndex = indexByPageIndex;
}
public boolean getRunover() {
return runover;
}
public int getPageSize() {
return pageSize;
}
public int getTotalCount() {
return count;
}
public int getForwardCnt() {
return forwardCnt;
}
public void setForwardCnt(int forwardCnt) {
this.forwardCnt = forwardCnt;
}
public int getBackwardCnt() {
return backwardCnt;
}
public void setBackwardCnt(int backwardCnt) {
this.backwardCnt = backwardCnt;
}
public int getHeadCnt() {
return headCnt;
}
public void setHeadCnt(int headCnt) {
this.headCnt = headCnt;
}
public int getTailCnt() {
return tailCnt;
}
public void setTailCnt(int tailCnt) {
this.tailCnt = tailCnt;
}
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
public boolean isConsoleEnds() {
return consoleEnds;
}
public void setConsoleEnds(boolean consoleEnds) {
this.consoleEnds = consoleEnds;
}
public int getMaxOffset() {
return maxOffset;
}
public int getVicinityStart() {
return vicinityStart;
}
public void setVicinityStart(int vicinityStart) {
this.vicinityStart = vicinityStart;
}
public int getVicinityEnd() {
return vicinityEnd;
}
public void setVicinityEnd(int vicinityEnd) {
this.vicinityEnd = vicinityEnd;
}
public boolean isDuplicateEnds() {
return duplicateEnds;
}
public void setDuplicateEnds(boolean duplicateEnds) {
this.duplicateEnds = duplicateEnds;
}
public void setTotalCount(int totalCount) {
this.count = totalCount;
}
public void setCurrentPageOffset(int currentPageOffset) {
this.offset = currentPageOffset;
}
public void setRunover(boolean runover) {
this.runover = runover;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public List<Page> getVicinity() {
return getPageRange(vicinityStart, vicinityEnd);
}
public List<Page> getHead() {
int end;
end = (getHeadCnt() - 1) * pageSize;
if (!isDuplicateEnds())
end = Math.min(end, vicinityStart - pageSize);
return getPageRange(0, correctEndPageOffset(end));
}
public List<Page> getTail() {
if (runover) {
List<Page> r = new ArrayList<Page>();
r.add(createSpecialPage(SPECIAL_RUNOVER));
return r;
}
int lastPageOffset = calculateLastPageOffset(0);
int start = lastPageOffset - (getTailCnt() - 1) * pageSize;
if (!isDuplicateEnds()) {
int minStart = lastPageOffset
- ((lastPageOffset - vicinityEnd) / pageSize - 1)
* pageSize;
start = Math.max(start, minStart);
}
return getPageRange(start >= 0 ? start : 0, lastPageOffset);
}
public List<Page> getConsole() {
List<Page> r = new ArrayList<Page>();
if (consoleEnds) {
List<Page> h = getHead();
r.addAll(h);
Page last = (!h.isEmpty()) ? h.get(h.size() - 1) : null;
if (last != null && last.getOffset() < (vicinityStart - pageSize))
r.add(createSpecialPage(SPECIAL_ELLIPSIS));
}
r.addAll(getVicinity());
if (consoleEnds) {
List<Page> t = getTail();
Page first = (!r.isEmpty()) ? r.get(0) : null;
if (first != null && first.getOffset() > (vicinityEnd + pageSize))
r.add(createSpecialPage(SPECIAL_ELLIPSIS));
r.addAll(t);
}
return r;
}
public final Page getFirst() {
return getPage(0);
}
public Page getMinus10() {
return getDeltaPage(-10);
}
public Page getPrev() {
return getDeltaPage(-1);
}
public Page getCurrent() {
return getDeltaPage(0);
}
public Page getNext() {
return getDeltaPage(1);
}
public Page getPlus10() {
return getDeltaPage(10);
}
public Page getLast() {
return getPage(calculateLastPageOffset(0));
}
protected Page getPage(int offset) {
if (count < 1 || offset < 0 || offset > maxOffset)
return null;
Page ret = pageCache.get(Integer.valueOf(offset));
if (ret == null) {
int firstPageItem = offset + 1;
int pageNumber = offset / pageSize + 1;
int pagePos;
if (isIndexByPage())
pagePos = pageNumber;
else if (isIndexByPageIndex())
pagePos = pageNumber - 1;
else
pagePos = offset;
Page p = new Page();
p.setCount(Math.min(pageSize, count - firstPageItem + 1));
p.setOffset(offset);
p.setNumber(pageNumber);
p.setPos(pagePos);
p.setSpecial(null);
pageCache.put(Integer.valueOf(offset), ret = p);
}
return ret;
}
public void configure(int count, int pos) {
if (isIndexByPage())
offset = pos > 0 ? (pos - 1) * pageSize : 0;
else if (isIndexByPageIndex())
offset = pos * pageSize;
else
offset = pos;
if (offset < 0)
offset = 0;
this.count = count >= 0 ? count : offset + 1;
this.maxOffset = this.runover ? this.count : this.count - 1;
calculateVicinityRange();
}
protected Page createSpecialPage(String special) {
Page p = new Page();
p.setSpecial(special);
return p;
}
protected List<Page> getPageRange(int startOffset, int endOffset) {
List<Page> r = new ArrayList<Page>();
for (int i = startOffset; i <= endOffset; i += pageSize) {
r.add(getPage(i));
}
return r;
}
protected Page getDeltaPage(int delta) {
return getPage(offset + delta * pageSize);
}
protected void calculateVicinityRange() {
boolean placeFromStart = offset < count - offset - pageSize;
int start;
int end;
if (placeFromStart) {
int minStart = calculateFirstPageOffset(offset);
start = offset - backwardCnt * pageSize;
start = (start < minStart) ? minStart : start;
end = independentVicinity ? (offset + backwardCnt * pageSize)
: (start + (forwardCnt + backwardCnt) * pageSize);
end = correctEndPageOffset(end);
} else {
int maxEnd = calculateLastPageOffset(offset);
end = offset + forwardCnt * pageSize;
end = (end > maxEnd) ? maxEnd : end;
start = independentVicinity ? (offset - forwardCnt * pageSize)
: (end - (backwardCnt + forwardCnt) * pageSize);
if (start < 0)
start = 0;
}
this.vicinityStart = start;
this.vicinityEnd = end;
}
protected int calculateFirstPageOffset(int offset) {
return offset % pageSize;
}
protected int calculateLastPageOffset(int offset) {
return ((maxOffset - offset) / pageSize) * pageSize + offset;
}
protected int correctEndPageOffset(int offset) {
return (offset > maxOffset) ? maxOffset : offset;
}
public int getCount() {
return count;
}
@Deprecated
public final int getCurrentPageOffset() {
return getOffset();
}
public int getOffset() {
return offset;
}
public Object getOffsetAddress(int of) {
return (addrAdapter == null) ? null : addrAdapter.makePageAddress(of);
}
/**
* One page of the result.
*/
public class Page {
private int pageCount;
private int pageOffset;
private int number;
private int pos;
private String special;
Object address;
public boolean isShown() {
return pageOffset == PaginationData.this.getOffset();
}
public int getIndex() {
return number - 1;
}
public Page getPrev() {
return PaginationData.this.getPage(pageOffset
- PaginationData.this.getPageSize());
}
public Page getNext() {
return PaginationData.this.getPage(pageOffset
+ PaginationData.this.getPageSize());
}
public int getFirstNumber() {
return pageOffset + 1;
}
public int getFirstIndex() {
return pageOffset;
}
public int getLastNumber() {
return pageOffset + pageCount;
}
public int getLastIndex() {
return getLastNumber() - 1;
}
public String getOutput() {
if (special == SPECIAL_ELLIPSIS)
return "...";
else if (special == SPECIAL_RUNOVER)
return "";
return String.valueOf(number);
}
@Override
public int hashCode() {
final int prime = 53;
int result = 1;
result = prime * result + pageCount;
result = prime * result + pageOffset;
result = prime * result + pos;
result = prime * result
+ ((special == null) ? 0 : special.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Page other = (Page) obj;
if (pageCount != other.pageCount)
return false;
if (pageOffset != other.pageOffset)
return false;
if (pos != other.pos)
return false;
if (special == null) {
if (other.special != null)
return false;
} else if (!special.equals(other.special))
return false;
return true;
}
public int getCount() {
return pageCount;
}
public void setCount(int count) {
this.pageCount = count;
}
public int getOffset() {
return pageOffset;
}
public void setOffset(int offset) {
this.pageOffset = offset;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public int getPos() {
return pos;
}
public void setPos(int pos) {
this.pos = pos;
}
public String getSpecial() {
return special;
}
public void setSpecial(String special) {
this.special = special;
}
public Object getAddr() {
if (address == null) {
address = getOffsetAddress(pageOffset);
}
return address;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment