package com.openedit.hittracker; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openedit.Data; import org.openedit.MultiValued; import org.openedit.data.PropertyDetail; import org.openedit.data.Searcher; import org.openedit.util.DateStorageUtil; import com.openedit.OpenEditException; public abstract class HitTracker implements Serializable, Collection { private static final Log log = LogFactory.getLog(HitTracker.class); protected boolean fieldAllSelected; protected Collection<String> fieldSelections; protected int fieldPage = 0; protected int fieldHitsPerPage = 15; protected int fieldCurrentHit; protected SearchQuery fieldSearchQuery; protected boolean fieldUseRandom; protected List fieldRandomLookup; protected transient String fieldIndexId; //cause this index to invalidate protected String fieldResultType; protected String fieldDataSource; protected String fieldHitsName; protected List fieldCurrentPage; protected int fieldMaxPageListing = 10; //used for page listing protected Searcher fieldSearcher; protected boolean fieldShowOnlySelected; protected String fieldTempSessionId; protected List<FilterNode> fieldFilterOptions; public HitTracker() { } public HitTracker(Searcher inSearcher) { setSearcher(inSearcher); } protected void setAllSelected(boolean inSelectAll) { fieldAllSelected = inSelectAll; } public boolean isShowOnlySelected() { return fieldShowOnlySelected; } public void setShowOnlySelected(boolean inShowOnlySelected) { fieldShowOnlySelected = inShowOnlySelected; } public String getResultType() { return getSearchQuery().getResultType(); } /* public List getPartOfPageOfHits(int inStart, int inEnd) throws Exception { List page = new ArrayList(); int count = (getPage() - 1) * getHitsPerPage(); // this is the start of // the count count = count + inStart; // tack on the offset for (int i = inStart; i < getHitsPerPage() && i < inEnd; i++) { if (count < getTotal()) { page.add(get(count)); count++; } } return page; } */ /** * This is the absolute position of a result * @param count * @return */ public int indexOf(int count) { int bottom = (getPage() - 1) * getHitsPerPage(); // this is the start of return bottom + count; // the offset } public abstract Data get(int count); public Object getById(String inId) { for (int i = 0; i < size(); i++) { Data hit = get(i); String id = getValue(hit, "id"); if( id.equals(inId)) { return hit; } } return null; //throw new OpenEditException("getById Not implemented"); } public Collection<String> getSourcePaths() { List paths = new ArrayList(); for (Iterator iterator = iterator(); iterator.hasNext();) { Data data = (Data) iterator.next(); paths.add(data.getSourcePath()); } return paths; } public List<Data> getPageOfHits() { if( fieldCurrentPage == null) { setPage(1); } return fieldCurrentPage; } public Collection getLast(int inCount) { List page = new ArrayList(inCount); int total = size() - 1; for (int i = 0; i < inCount; i++) { int index = total - i; if( index > -1) { page.add(get(index)); } else { break; } } return page; } public List getPageInRows(int inColCount) throws Exception { List page = getPageOfHits(); // Now break up the page into rows by dividing the count they wanted double rowscount = (double) page.size() / (double) inColCount; List rows = new ArrayList(); for (int i = 0; i < rowscount; i++) { int start = i * inColCount; int end = i * inColCount + inColCount; List sublist = page.subList(start, Math.min(page.size(), end)); rows.add(sublist); } return rows; } public int getHitsPerPage() { return fieldHitsPerPage; } public void setHitsPerPage(int inHitsPerPage) { if (inHitsPerPage > 0 && inHitsPerPage != fieldHitsPerPage) { fieldCurrentPage = null; fieldHitsPerPage = inHitsPerPage; if( fieldPage > 0) { setPage(1); } } } public int getPage() { if( fieldPage == 0) { setPage(1); } return fieldPage; } public void setPageByIndex(int inIndex) { if( inIndex < getHitsPerPage() ) { setPage(1); } else { int page = size() / inIndex; setPage(page); } } public void setPage(int inPageOneBased) { if( fieldPage != inPageOneBased || fieldCurrentPage == null) { fieldPage = inPageOneBased; int inHitsPerPage = getHitsPerPage(); List page = new ArrayList(); int count = (getPage() - 1) * inHitsPerPage; // pick up from here fieldCurrentPage = page; int total = size(); for (int i = 0; i < inHitsPerPage; i++) { if (count < total) { page.add(get(count)); count++; } else { break; } } } } public int getMaxPageListing() { return fieldMaxPageListing; } public void setMaxPageListing(int inMaxPageListing) { fieldMaxPageListing = inMaxPageListing; } /** * @deprecated use iterator() */ public Iterator getAllHits() { return iterator(); } public abstract Iterator iterator(); public int getCurrentHit() { return fieldCurrentHit; } public void setCurrentHit(int inCurrentHit) { fieldCurrentHit = inCurrentHit; } public boolean containsById(String inId) { return getById(inId) != null; } public abstract boolean contains(Object inHit); public int getTotal() { return size(); } public abstract int size(); public int getTotalPages() { double pages = (double) getTotal() / (double) getHitsPerPage(); if (pages % 1 > 0) { pages++; } return (int) pages; } public Integer nextPage() { int page = getPage() + 1; if (page > getTotalPages()) { return null; } else { return new Integer(page); } } public Integer prevPage() { int page = getPage() - 1; if (page < 1) { return null; } else { return new Integer(page); } } public Integer getPageStart() { if (getTotal() == 0) { return null; } int start = (getPage() - 1) * getHitsPerPage(); return new Integer(start + 1); } public Integer getPageEnd() { if (getTotal() == 0) { return null; } int start = getPage() * getHitsPerPage(); if (start > getTotal()) { return new Integer(getTotal()); } return new Integer(start); } public SearchQuery getSearchQuery() { if (fieldSearchQuery == null) { fieldSearchQuery = new SearchQuery(); } return fieldSearchQuery; } public String getQuery() { if (getSearchQuery() != null) { return getSearchQuery().toQuery(); } return null; } public List linkRange() { int totalPages = getTotalPages(); int page = getPage(); int start = 1; if (page < getMaxPageListing() / 2) // under the first 5 records { start = 1;// - getMaxPageListing()/2; } else if (page + getMaxPageListing() / 2 + 1 >= totalPages) // near // the // end + // 1 for // the // selected // one { start = 1 + totalPages - getMaxPageListing(); // Make it start 10 // from the end start = Math.max(1, start); // dont go below 1 } else { start = 1 + page - getMaxPageListing() / 2; } int count = Math.min(totalPages, getMaxPageListing()); // what is // higher the // total count // or 10 List hits = new ArrayList(count); for (int i = 0; i < count; i++) { hits.add(new Integer(start + i)); } return hits; } public List linksBefore() { List range = linkRange(); int i = 0; for (; i < range.size(); i++) { Integer in = (Integer) range.get(i); if (in.intValue() >= getPage()) { break; } } return range.subList(0, i); } public List linksAfter() { if (getTotalPages() == getPage()) { return Collections.EMPTY_LIST; } List range = linkRange(); if (range.size() == 1) // Only one hit { return Collections.EMPTY_LIST; } int start = 0; for (int i = 0; i < range.size(); i++) { Integer in = (Integer) range.get(i); if (in.intValue() > getPage()) { start = i; break; } } return range.subList(start, range.size()); } /** * @deprecated Use getSearchQuery().getInput("nameof field") */ public String getUserQuery() { return getSearchQuery().getInput("description"); } public String getInput(String inKey) { SearchQuery query = getSearchQuery(); if (query != null) { return query.getInput(inKey); } return null; } public boolean wasInput(String inKey, String inValue) { SearchQuery query = getSearchQuery(); if (query != null && inValue != null && inKey != null) { Collection inputs = query.getInputs(inKey); if (inputs != null) { if( inputs.contains(inValue) ) { return true; } } } return false; } public String getOrdering() { if (getSearchQuery() == null) { return null; } return getSearchQuery().getSortBy(); } public String getIndexId() { return fieldIndexId; } public void setIndexId(String inIndexCounter) { fieldIndexId = inIndexCounter; } public String getFriendlyQuery() { SearchQuery query = getSearchQuery(); if (query != null) { return getSearchQuery().toFriendly(); } return null; } public void setSearchQuery(SearchQuery inQuery) { fieldSearchQuery = inQuery; } public boolean isEmpty() { return size() == 0; } // Remaining API are not implemented public List keys() { // All the ID's we can find return null; } public String highlight(Object inDoc, String inField) { return "Not implemented"; } public String getValue(Object inHit, String inString) { return getValue((Data)inHit, inString); } public String getValue(Data inHit, String inString) { return inHit.get(inString); } //Use SearchResultsData.getValues // public Collection getValues(Object inHit, String inString) // { // String val = getValue((Data)inHit, inString); // if( val == null) // { // return Collections.EMPTY_LIST; // } // String[] vals = null; // Collection collection = null; // if( val.contains("|") ) // { // vals = MultiValued.VALUEDELMITER.split(val); // } // else // { // vals = new String[] { val }; // } // collection = Arrays.asList(vals); // //if null check parent // return collection; // } public String toString(Data inHit) { if (inHit instanceof Data) { return inHit.toString(); } else { String name = getValue(inHit, "name"); if (name == null) { name = getValue(inHit, "shortdescription"); } if (name == null) { name = getValue(inHit, "id"); } return name; } } public void clear() { } public boolean containsAll(Collection arg0) { // TODO Auto-generated method stub return false; } public boolean remove(Object inO) { return false; } public boolean removeAll(Collection arg0) { return false; } public boolean retainAll(Collection arg0) { return false; } public Object[] toArray() { Object[] all = new Object[size()]; return toArray(all); } public Object[] toArray(Object[] all) { Iterator iter = iterator(); int c = 0; while( iter.hasNext() ) { all[c] = iter.next(); c++; } return all; } public boolean add(Object arg0) { return false; } public boolean addAll(Collection arg0) { return false; } public Date getDateValue(Data inHit, String inField) { String value = getValue(inHit, inField); if( value == null) { return null; } SearchQuery q = getSearchQuery(); if( q != null) { PropertyDetail detail = q.getPropertyDetails().getDetail(inField); Date date = DateStorageUtil.getStorageUtil().parseFromStorage(value); return date; } throw new OpenEditException("Search Query must be set"); } @Deprecated public Collection getSelectedHits(){ return getSelectedHitracker(); } public HitTracker getSelectedHitracker() { if( isAllSelected() ) { return this; } if( getSessionId().startsWith("selected") ) { return this; } HitTracker selecteddata = getSearcher().search(getSearchQuery()); if( isAllSelected() ) { //rerun the search selecteddata.selectAll(); } else { selecteddata.setSelections(getSelections()); selecteddata.setShowOnlySelected(true); } // else // { // ListHitTracker lhits = new ListHitTracker(); // lhits.setSessionId("selected" + getSessionId() ); // hits = lhits; // SelectedHitsTracker hits = new SelectedHitsTracker(this); // selecteddata.setHitsName("selected" + getHitsName() + selecteddata.size() ); selecteddata.setSessionId("selected" + getSessionId()); return selecteddata; } // // public Collection<Data> getSelectedHits() // { // if( isAllSelected() ) // { // return this; // } // return getSelectedHitracker(); // } public boolean hasMultipleSelections() { if( isAllSelected() ) { return true; } if( fieldSelections != null && fieldSelections.size() > 1 ) { return true; } return false; } public int getSelectionSize() { if( isAllSelected() ) { return size(); } if( fieldSelections != null ) { return fieldSelections.size(); } return 0; } public boolean hasSelections() { if( isAllSelected() ) { return true; } if( fieldSelections != null && fieldSelections.size() > 0 ) { return true; } return false; } public Collection<String> getSelections() { if (fieldSelections == null) { fieldSelections = new ArrayList<String>(); } return fieldSelections; } public void setSelections(Collection<String> inSelections) { fieldSelections = inSelections; } public void addSelection(String inId) { if( inId == null) { return; } if(!getSelections().contains(inId)){ getSelections().add(inId); } } public void removeSelection(String inId) { getSelections().remove(inId); } public boolean isSelected(String inId) { if( isAllSelected() ) { return true; } return getSelections().contains(inId); } /** * @deprecated Call isSelected instead * @param inId * @return */ public boolean isSelectedOnPage(String inId) { // int bottom = (getPage() - 1) * getHitsPerPage(); // this is the start of // int index = bottom + count; // the offset // // boolean selected = getSelections().contains(new Integer(index)); // return selected; return isSelected(inId); } public void toggleSelected(String inId) { if (isSelected(inId)) { removeSelection(inId); } else { addSelection(inId); } } public void selectAll() { fieldAllSelected = true; } public void deselectAll() { getSelections().clear(); fieldAllSelected = false; } public String getFirstSelected() { if( hasSelections() ) { if( isAllSelected()) { return get(0).getId(); } String first = getSelections().iterator().next(); if( first != null) { return first; } } return null; } public void deselectCurrentPage() throws Exception { //deselectAll(); List page = getPageOfHits(); for (Iterator iterator = page.iterator(); iterator.hasNext();) { Data row = (Data) iterator.next(); removeSelection(row.getId()); } } public boolean isPageSelected() throws Exception { //deselectAll(); List page = getPageOfHits(); for (Iterator iterator = page.iterator(); iterator.hasNext();) { Data row = (Data) iterator.next(); if( !isSelected(row.getId()) ) { return false; } } return true; } public void selectCurrentPage() throws Exception { //deselectAll(); List page = getPageOfHits(); for (Iterator iterator = page.iterator(); iterator.hasNext();) { Data row = (Data) iterator.next(); addSelection(row.getId()); } } public String getSessionId() { if( fieldTempSessionId != null) { return fieldTempSessionId; } return getSearchQuery().getSessionId(); } public String getHitsName() { if( fieldHitsName != null) //This may be not needed { return fieldHitsName; } return getSearchQuery().getHitsName(); } public void setHitsName(String inHitsname) { fieldHitsName = inHitsname; } public String getCatalogId() { return getSearchQuery().getCatalogId(); } public void setCatalogId(String inCatalogid) { getSearchQuery().setCatalogId(inCatalogid); } public int indexOf(String inCatalogId, String inId) { if( inCatalogId == null) { inCatalogId = getCatalogId(); } if( inId == null) { return -1; } for(int i = 0; i < size(); i++) { Data hit = get(i); String catalogId = getValue(hit, "catalogid"); String id = getValue(hit, "id"); if(inCatalogId.equals(catalogId) && inId.equals(id)) { return i; } } return -1; } public int getPageForIndexLocation(int inIndex) { int page = inIndex / getHitsPerPage(); page++; return page; } public Object previous(int inIndex) { if(inIndex == -1) { return null; } if(inIndex == 0) { return null; } return get(inIndex - 1); } public int previousIndex(String inIndex){ int index = Integer.parseInt(inIndex); if(index <= 1) { return -1; } return index - 1; } public Object previous(String inCatalogId, String inId) { int indexOfCurrent = indexOf(inCatalogId, inId); return previous(indexOfCurrent); } public Object first() { if( size() == 0) { return null; } return get(0); } public Object next(int inIndex) { if(inIndex == -1) { return null; } if(inIndex >= size() - 1) { return null; } return get(inIndex + 1); } public int nextIndex(String inIndex){ int index = Integer.parseInt(inIndex); if(index >= size()){ return -1; } return index + 1; } public Object next(String inCatalogId, String inId) { int indexOfCurrent = indexOf(inCatalogId, inId); return next(indexOfCurrent); } public Object nextById(String inId){ int current = indexOfId(inId); if(current != -1){ if(current < size()-1){ return get(current +1); } } return null; } public Object previousById(String inId){ int current = indexOfId(inId); if(current != -1){ if(current > 0){ return get(current -1); } } return null; } public int indexOfId(String inId) { if( inId == null || inId.startsWith("multiedit:") || inId.trim().isEmpty() ) { return -1; } int found = findIdOnPage(inId,getPage()); if( found > -1) { return found; } if( getTotalPages() > getPage() ) { //Look one after found = findIdOnPage(inId,getPage() + 1); if( found > -1) { return found; } } //Look one before if( getPage() > 1 ) { found = findIdOnPage(inId,getPage() -1); if( found > -1) { return found; } } return -1; } protected int findIdOnPage(String inId, int inPage) { int size = size(); int start = (inPage-1) * getHitsPerPage(); int end = (inPage) * getHitsPerPage(); end = Math.min(size, end); for (int i = start; i < end; i++) { Data hit = get(i); String id = getValue(hit, "id"); if( id.equals(inId)) { return i; } } return -1; } public String getDataSource() { return fieldDataSource; } public void setDataSource(String inDataSource) { fieldDataSource = inDataSource; } public int parseInt(Object inValue) { if( inValue == null) { return 0; } String text = String.valueOf(inValue); if( text.length() == 0) { return 0; } if( Character.isDigit(text.charAt(0))) { return Integer.parseInt(text); } return 0; } public boolean isAllSelected() { return fieldAllSelected; } public Data findData(String inField, String inValue) { if(inValue == null || inField == null) { return null; } for (Data hit: getPageOfHits() ) { if(inValue.equals(hit.get(inField))) { return hit; } } for (int i = 0; i < size(); i++) { Data hit = get(i); if(inValue.equals(hit.get(inField))) { return hit; } } return null; } public int findRow(String inField, String inValue) { if(inValue == null || inField == null) { return -1; } for (int i = 0; i < size(); i++) { Data hit = get(i); if(inValue.equals(hit.get(inField))) { return i; } } return -1; } public void loadPreviousSelections(HitTracker inOld) { setSelections(inOld.getSelections()); //setAllSelected(inOld.isAllSelected()); This is dangerous behaviour - //if I've done a search and had 10 hits and selected all, I don't want to still have all selected when I then do another search for totally different assets } public Searcher getSearcher() { return fieldSearcher; } public void setSearcher(Searcher inSearcher) { fieldSearcher = inSearcher; } protected void setSessionId(String inSessionId) { fieldTempSessionId = inSessionId; } public List<FilterNode> getFilterOptions() { if(fieldFilterOptions == null){ fieldFilterOptions = loadFacetsFromResults(); } return fieldFilterOptions; } public void setFilterOptions(List <FilterNode> filters){ fieldFilterOptions = filters; } protected List loadFacetsFromResults() { // TODO Auto-generated method stub return new ArrayList(); //this is load code } public FilterNode findFilterNode(String inType) { List <FilterNode> nodes = getFilterOptions(); if( nodes != null) { for (Iterator iterator = nodes.iterator(); iterator.hasNext();) { FilterNode filterNode = (FilterNode) iterator.next(); if( filterNode.getId().endsWith(inType)) { return filterNode; } } } return null; } // public void selectFilters(List selected) // { // List topnodes = getFilters(); // // if (topnodes != null)//Assettype, colour, // { // for (Iterator iterator = topnodes.iterator(); iterator.hasNext();) // { // FilterNode node = (FilterNode) iterator.next(); // for (Iterator iterator2 = node.getChildren().iterator(); iterator2.hasNext();) // { // FilterNode child = (FilterNode) iterator2.next(); // if (selected.contains(child.getId())) // { // child.setSelected(true);//values // } // else // { // child.setSelected(false); // } // } // } // } // // } // public boolean hasSelectedFilters() // { // // List topnodes = getFilters(); // for (Iterator iterator = topnodes.iterator(); iterator.hasNext();) // { // FilterNode node = (FilterNode) iterator.next(); // for (Iterator iterator2 = node.getChildren().iterator(); iterator2.hasNext();) // { // FilterNode child = (FilterNode) iterator2.next(); // if (child.isSelected()) // { // return true; // } // } // } // return false; // } // public void refreshFilters() throws Exception // { // // TODO Auto-generated method stub // // } public boolean isChildFacetSelected(FilterNode inNode){ List selectedfilters = getSearchQuery().getFilters(); for (Iterator iterator = selectedfilters.iterator(); iterator.hasNext();) { FilterNode selected = (FilterNode) iterator.next(); if(selected.getId().equals(inNode.getId())){ return true; } } return false; } public void invalidate() { setIndexId(getIndexId() + 1); } }