Created
February 23, 2013 09:25
-
-
Save vmencik/5019110 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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