String getKey() { try { String key = ""; key += "-" + scope.getBrowseIndex().getName(); key += "-" + scope.getBrowseLevel(); key += "-" + scope.getStartsWith(); key += "-" + scope.getResultsPerPage(); key += "-" + scope.getSortBy(); key += "-" + scope.getSortOption().getNumber(); key += "-" + scope.getOrder(); key += "-" + scope.getJumpToItem(); key += "-" + scope.getFilterValue(); key += "-" + scope.getFilterValueLang(); key += "-" + scope.getJumpToValue(); key += "-" + scope.setJumpToValueLang(); key += "-" + etAl; return key; } catch (Exception e) { return null; // ignore exception and return no key } }
/** * Browse the archive by single values (such as the name of an author). This produces a BrowseInfo * object that contains Strings as the results of the browse * * @param bs the scope of the browse * @return the results of the browse * @throws BrowseException */ private BrowseInfo browseByValue(BrowserScope bs) throws BrowseException { log.info(LogManager.getHeader(context, "browse_by_value", "focus=" + bs.getJumpToValue())); try { // get the table name that we are going to be getting our data from // this is the distinct table constrained to either community or collection dao.setTable(browseIndex.getDistinctTableName()); // remind the DAO that this is a distinct value browse, so it knows what sort // of query to build dao.setDistinct(true); // tell the browse query whether we are ascending or descending on the value dao.setAscending(scope.isAscending()); // set our constraints on community or collection if (scope.inCollection() || scope.inCommunity()) { // Scoped browsing of distinct metadata requires the mapping // table to be specified. dao.setFilterMappingTables(null, browseIndex.getMapTableName()); if (scope.inCollection()) { Collection col = (Collection) scope.getBrowseContainer(); dao.setContainerTable("collection2item"); dao.setContainerIDField("collection_id"); dao.setContainerID(col.getID()); } else if (scope.inCommunity()) { Community com = (Community) scope.getBrowseContainer(); dao.setContainerTable("communities2item"); dao.setContainerIDField("community_id"); dao.setContainerID(com.getID()); } } // this is the total number of results in answer to the query int total = getTotalResults(true); // set the ordering field (there is only one option) dao.setOrderField("sort_value"); // assemble the focus clause if we are to have one // it will look like one of the following // - sort_value < myvalue // = sort_1 > myvalue dao.setJumpToField("sort_value"); int offset = scope.getOffset(); String rawFocusValue = null; if (offset < 1 && scope.hasJumpToValue() || scope.hasStartsWith()) { String focusValue = getJumpToValue(); // store the value to tell the Browse Info object which value we are browsing on rawFocusValue = focusValue; // make sure the incoming value is normalised focusValue = normalizeJumpToValue(focusValue); offset = getOffsetForDistinctValue(focusValue); } // assemble the offset and limit dao.setOffset(offset); dao.setLimit(scope.getResultsPerPage()); // Holder for the results List<String[]> results = null; // Does this browse have any contents? if (total > 0) { // now run the query results = dao.doValueQuery(); // now, if we don't have any results, we are at the end of the browse. This will // be because a starts_with value has been supplied for which we don't have // any items. if (results.size() == 0) { // In this case, we will calculate a new offset for the last page of results offset = total - scope.getResultsPerPage(); if (offset < 0) { offset = 0; } // And rerun the query dao.setOffset(offset); results = dao.doValueQuery(); } } else { // No records, so make an empty list results = new ArrayList<String[]>(); } // construct the BrowseInfo object to pass back BrowseInfo browseInfo = new BrowseInfo(results, offset, total, offset); if (offset + scope.getResultsPerPage() < total) { browseInfo.setNextOffset(offset + scope.getResultsPerPage()); } if (offset - scope.getResultsPerPage() > -1) { browseInfo.setPrevOffset(offset - scope.getResultsPerPage()); } // add the browse index to the Browse Info browseInfo.setBrowseIndex(browseIndex); // set the sort option for the Browse Info browseInfo.setSortOption(scope.getSortOption()); // tell the Browse Info which way we are sorting browseInfo.setAscending(scope.isAscending()); // tell the Browse Info which level of browse we are at browseInfo.setBrowseLevel(scope.getBrowseLevel()); // set the browse value if there is one browseInfo.setFocus(rawFocusValue); // tell the browse info if it is working from a starts with parameter browseInfo.setStartsWith(scope.hasStartsWith()); // tell the browse info what the container for the browse was if (scope.inCollection() || scope.inCommunity()) { browseInfo.setBrowseContainer(scope.getBrowseContainer()); } browseInfo.setResultsPerPage(scope.getResultsPerPage()); return browseInfo; } catch (SQLException e) { log.error("caught exception: ", e); throw new BrowseException(e); } }
/** * Perform a limited browse, which only returns the results requested, without any extraneous * information. To perform a full browse, use BrowseEngine.browse() above. This supports Item * browse only, and does not currently support focus or values. This method is used, for example, * to generate the Recently Submitted Items results. * * @param bs the scope of the browse * @return the results of the browse */ public BrowseInfo browseMini(BrowserScope bs) throws BrowseException { log.info(LogManager.getHeader(context, "browse_mini", "")); // load the scope into the object this.scope = bs; // since we use it so much, get the browse index out of the // scope and store as a member browseIndex = scope.getBrowseIndex(); // get the table name that we are going to be getting our data from dao.setTable(browseIndex.getTableName()); // tell the browse query whether we are ascending or descending on the value dao.setAscending(scope.isAscending()); // define a clause for the WHERE clause which will allow us to constrain // our browse to a specified community or collection if (scope.inCollection() || scope.inCommunity()) { if (scope.inCollection()) { Collection col = (Collection) scope.getBrowseContainer(); dao.setContainerTable("collection2item"); dao.setContainerIDField("collection_id"); dao.setContainerID(col.getID()); } else if (scope.inCommunity()) { Community com = (Community) scope.getBrowseContainer(); dao.setContainerTable("communities2item"); dao.setContainerIDField("community_id"); dao.setContainerID(com.getID()); } } dao.setOffset(scope.getOffset()); dao.setLimit(scope.getResultsPerPage()); // assemble the ORDER BY clause String orderBy = browseIndex.getSortField(scope.isSecondLevel()); if (scope.getSortBy() > 0) { orderBy = "sort_" + Integer.toString(scope.getSortBy()); } dao.setOrderField(orderBy); // now run the query List<BrowseItem> results = dao.doQuery(); // construct the mostly empty BrowseInfo object to pass back BrowseInfo browseInfo = new BrowseInfo(results, 0, scope.getResultsPerPage(), 0); // add the browse index to the Browse Info browseInfo.setBrowseIndex(browseIndex); // set the sort option for the Browse Info browseInfo.setSortOption(scope.getSortOption()); // tell the Browse Info which way we are sorting browseInfo.setAscending(scope.isAscending()); // tell the browse info what the container for the browse was if (scope.inCollection() || scope.inCommunity()) { browseInfo.setBrowseContainer(scope.getBrowseContainer()); } browseInfo.setResultsPerPage(scope.getResultsPerPage()); browseInfo.setEtAl(scope.getEtAl()); return browseInfo; }
/** * Browse the archive by the full item browse mechanism. This produces a BrowseInfo object which * contains full BrowseItem objects as its result set. * * @param bs the scope of the browse * @return the results of the browse * @throws BrowseException */ private BrowseInfo browseByItem(BrowserScope bs) throws BrowseException { log.info(LogManager.getHeader(context, "browse_by_item", "")); try { // get the table name that we are going to be getting our data from dao.setTable(browseIndex.getTableName()); // tell the browse query whether we are ascending or descending on the value dao.setAscending(scope.isAscending()); // assemble the value clause String rawValue = null; if (scope.hasFilterValue() && scope.isSecondLevel()) { String value = scope.getFilterValue(); rawValue = value; // make sure the incoming value is normalised value = OrderFormat.makeSortString( value, scope.getFilterValueLang(), scope.getBrowseIndex().getDataType()); dao.setAuthorityValue(scope.getAuthorityValue()); // set the values in the Browse Query if (scope.isSecondLevel()) { dao.setFilterValueField("value"); dao.setFilterValue(rawValue); } else { dao.setFilterValueField("sort_value"); dao.setFilterValue(value); } dao.setFilterValuePartial(scope.getFilterValuePartial()); // to apply the filtering, we need the distinct and map tables for the index dao.setFilterMappingTables( browseIndex.getDistinctTableName(), browseIndex.getMapTableName()); } // define a clause for the WHERE clause which will allow us to constrain // our browse to a specified community or collection if (scope.inCollection() || scope.inCommunity()) { if (scope.inCollection()) { Collection col = (Collection) scope.getBrowseContainer(); dao.setContainerTable("collection2item"); dao.setContainerIDField("collection_id"); dao.setContainerID(col.getID()); } else if (scope.inCommunity()) { Community com = (Community) scope.getBrowseContainer(); dao.setContainerTable("communities2item"); dao.setContainerIDField("community_id"); dao.setContainerID(com.getID()); } } // this is the total number of results in answer to the query int total = getTotalResults(); // assemble the ORDER BY clause String orderBy = browseIndex.getSortField(scope.isSecondLevel()); if (scope.getSortBy() > 0) { orderBy = "sort_" + Integer.toString(scope.getSortBy()); } dao.setOrderField(orderBy); int offset = scope.getOffset(); String rawFocusValue = null; if (offset < 1 && (scope.hasJumpToItem() || scope.hasJumpToValue() || scope.hasStartsWith())) { // We need to convert these to an offset for the actual browse query. // First, get a value that we can look up in the ordering field rawFocusValue = getJumpToValue(); // make sure the incoming value is normalised String focusValue = normalizeJumpToValue(rawFocusValue); log.debug("browsing using focus: " + focusValue); // Convert the focus value into an offset offset = getOffsetForValue(focusValue); } dao.setOffset(offset); // assemble the LIMIT clause dao.setLimit(scope.getResultsPerPage()); // Holder for the results List<BrowseItem> results = null; // Does this browse have any contents? if (total > 0) { // now run the query results = dao.doQuery(); // now, if we don't have any results, we are at the end of the browse. This will // be because a starts_with value has been supplied for which we don't have // any items. if (results.size() == 0) { // In this case, we will calculate a new offset for the last page of results offset = total - scope.getResultsPerPage(); if (offset < 0) { offset = 0; } // And rerun the query dao.setOffset(offset); results = dao.doQuery(); } } else { // No records, so make an empty list results = new ArrayList<BrowseItem>(); } // construct the BrowseInfo object to pass back // BrowseInfo browseInfo = new BrowseInfo(results, position, total, offset); BrowseInfo browseInfo = new BrowseInfo(results, offset, total, offset); if (offset + scope.getResultsPerPage() < total) { browseInfo.setNextOffset(offset + scope.getResultsPerPage()); } if (offset - scope.getResultsPerPage() > -1) { browseInfo.setPrevOffset(offset - scope.getResultsPerPage()); } // add the browse index to the Browse Info browseInfo.setBrowseIndex(browseIndex); // set the sort option for the Browse Info browseInfo.setSortOption(scope.getSortOption()); // tell the Browse Info which way we are sorting browseInfo.setAscending(scope.isAscending()); // tell the Browse Info which level of browse we are at browseInfo.setBrowseLevel(scope.getBrowseLevel()); // set the browse value if there is one browseInfo.setValue(rawValue); // set the browse authority key if there is one browseInfo.setAuthority(scope.getAuthorityValue()); // set the focus value if there is one browseInfo.setFocus(rawFocusValue); if (scope.hasJumpToItem()) { browseInfo.setFocusItem(scope.getJumpToItem()); } // tell the browse info if it is working from a starts with parameter browseInfo.setStartsWith(scope.hasStartsWith()); // tell the browse info what the container for the browse was if (scope.inCollection() || scope.inCommunity()) { browseInfo.setBrowseContainer(scope.getBrowseContainer()); } browseInfo.setResultsPerPage(scope.getResultsPerPage()); browseInfo.setEtAl(scope.getEtAl()); return browseInfo; } catch (SQLException e) { log.error("caught exception: ", e); throw new BrowseException(e); } }
/** * Get the value (for single value browses) for the result that appears at the top of the previous * page, for when the User Interface is performing result set paging. The callback argument allows * for this method to populate the List with the results obtained from the query, which can be * useful when, for example, reaching the final browse page and needing additional results to pad * up to the number of results per page * * @param callback A List object for holding String objects indexed numerically in the correct * order * @return the value of the top of the previous page * @throws SQLException * @throws BrowseException */ private String getPreviousPageValue(List callback) throws SQLException, BrowseException { // do we want to capture the results? boolean capture = false; if (callback != null) { capture = true; } log.debug( LogManager.getHeader(context, "get_previous_page_value", "capture_results=" + capture)); // the only thing we need to do is reverse the direction // of the query, and set it to not use the "=" part of the // comparator (i.e. < and > not <= and >=). boolean isAscending = dao.isAscending(); dao.setAscending(!isAscending); boolean useEquals = dao.useEqualsComparator(); dao.setEqualsComparator(false); // store in local scope the things that we are going to change // during this method int resultLimit = dao.getLimit(); // if the database supports it (postgres does), we use limit // and offset to minimise the work it has to do. // the limit will be the size of a page, or double the size of the // page if we are capturing the result set (because the first page's worth // will be the results, so the previous link will need to come from the // page *before* that) int limit = scope.getResultsPerPage(); if (capture) { limit *= 2; } dao.setLimit(limit); // now we have a query which is exactly the opposite of the // original query. So lets execute it: List results = dao.doValueQuery(); // before we continue, put back the variables we messed with dao.setAscending(isAscending); dao.setEqualsComparator(useEquals); dao.setLimit(resultLimit); Iterator itr = results.iterator(); // work our way through the list, capturing if necessary, and finally // having the last result, which will be the top of the previous page int i = 0; String prev = null; while (itr.hasNext()) { String value = (String) itr.next(); // we need to copy this, because of the scoping vs by-reference issue prev = value; // if we need to capture the results in the call back, do it here. // Note that since the results will come in backwards, we place // each one at the start of the array so that it displaces the others // in the right direction. By the end, they should be sorted correctly // we use the index i to be sure that we only grab one page's worth // of results (see note above about limit) if (capture && i < scope.getResultsPerPage()) { callback.add(0, value); i++; } } log.debug(LogManager.getHeader(context, "get_previous_page_value_return", "return=" + prev)); return prev; }