📄 browse.java
字号:
* * <p> If limiting to a community or collection, we add a clause like: * community_id = 7 collection_id = 201 </p> */ protected static int countTotalInIndex(BrowseScope scope, int numberOfResults) throws SQLException { int browseType = scope.getBrowseType(); // When finding Items by Author, it often happens that // we find every single Item (eg, the Author only published // 2 works, and we asked for 15), and so can skip the // query. if ((browseType == ITEMS_BY_AUTHOR_BROWSE) && (scope.hasNoLimit() || (scope.getTotal() > numberOfResults))) { return numberOfResults; } PreparedStatement statement = null; Object obj = scope.getScope(); try { String table = BrowseTables.getTable(scope); StringBuffer buffer = new StringBuffer().append("select count(") .append(getTargetColumns(scope)).append(") from ").append( table); boolean hasWhere = false; if (browseType == ITEMS_BY_AUTHOR_BROWSE) { hasWhere = true; buffer.append(" where sort_author = ?"); } if (browseType == ITEMS_BY_SUBJECT_BROWSE) { hasWhere = true; buffer.append(" where sort_subject = ?"); } String connector = hasWhere ? "and" : "where"; String sql = buffer.append(getScopeClause(scope, connector)) .toString(); if (log.isDebugEnabled()) { log.debug("Total sql: \"" + sql + "\""); } statement = createStatement(scope, sql); if (browseType == ITEMS_BY_AUTHOR_BROWSE) { statement.setString(1, (String) scope.getFocus()); } if (browseType == ITEMS_BY_SUBJECT_BROWSE) { statement.setString(1, (String) scope.getFocus()); } return getIntValue(statement); } finally { if (statement != null) { statement.close(); } } } /** * Return the number of matches for the browse scope. * * @param scope * @param itemValue * item value we're looking for * @param totalInIndex * FIXME ?? * @param numberOfResults * FIXME ?? * @return number of matches * @throws SQLException */ protected static int countMatches(BrowseScope scope, String itemValue, int totalInIndex, int numberOfResults) throws SQLException { // Matched everything if (numberOfResults == totalInIndex) { return totalInIndex; } // Scope matches everything in the index // Note that this only works when the scope is all of DSpace, // since the Community and Collection index tables // include Items in other Communities/Collections if ((!scope.hasFocus()) && scope.isAllDSpaceScope()) { return totalInIndex; } PreparedStatement statement = null; try { statement = createSql(scope, itemValue, true, true); return getIntValue(statement); } finally { if(statement != null) { try { statement.close(); } catch(SQLException e) { log.error("Problem releasing statement", e); } } } } private static int getPosition(int total, int matches, int beforeFocus) { // Matched everything, so position is at start (0) if (total == matches) { return 0; } return total - matches - beforeFocus; } /** * Sort the results returned from the browse if necessary. The list of * results is sorted in-place. * * @param scope * @param results */ private static void sortResults(BrowseScope scope, List results) { // Currently we only sort ItemsByAuthor, Advisor, Subjects browses if ((scope.getBrowseType() != ITEMS_BY_AUTHOR_BROWSE) || (scope.getBrowseType() != ITEMS_BY_SUBJECT_BROWSE)) { return; } ItemComparator ic = scope.getSortByTitle().booleanValue() ? new ItemComparator( "title", null, Item.ANY, true) : new ItemComparator("date", "issued", Item.ANY, true); Collections.sort(results, ic); } /** * Transform the results of the query (TableRow objects_ into a List of * Strings (for getAuthors()) or Items (for all the other browses). * * @param scope * The Browse Scope * @param results * The results of the query * @param max * The maximum number of results to return * @return FIXME ?? * @throws SQLException */ private static List getResults(BrowseScope scope, List results, int max) throws SQLException { if (results == null) { return Collections.EMPTY_LIST; } List theResults = new ArrayList(); boolean hasLimit = !scope.hasNoLimit(); boolean isAuthorsBrowse = scope.getBrowseType() == AUTHORS_BROWSE; boolean isSubjectsBrowse = scope.getBrowseType() == SUBJECTS_BROWSE; for (Iterator iterator = results.iterator(); iterator.hasNext();) { TableRow row = (TableRow) iterator.next(); Object theValue = null; if (isAuthorsBrowse) theValue = (Object) row.getStringColumn("author"); else if (isSubjectsBrowse) theValue = (Object) row.getStringColumn("subject"); else theValue = (Object) new Integer(row.getIntColumn("item_id")); // Should not happen if (theValue == null) { continue; } // Exceeded limit if (hasLimit && (theResults.size() >= max)) { break; } theResults.add(theValue); if (log.isDebugEnabled()) { log.debug("Adding result " + theValue); } } return (isAuthorsBrowse||isSubjectsBrowse) ? theResults : toItems(scope.getContext(), theResults); } /** * Create a PreparedStatement to run the correct query for scope. * * @param scope * The Browse scope * @param subqueryValue * If the focus is an item, this is its value in the browse index * (its title, author, date, etc). Otherwise null. * @param after * If true, create SQL to find the items after the focus. * Otherwise create SQL to find the items before the focus. * @param isCount * If true, create SQL to count the number of matches for the * query. Otherwise just the query. * @return a prepared statement * @throws SQLException */ private static PreparedStatement createSql(BrowseScope scope, String subqueryValue, boolean after, boolean isCount) throws SQLException { String sqli = createSqlInternal(scope, subqueryValue, isCount); String sql = formatSql(scope, sqli, subqueryValue, after); PreparedStatement statement = createStatement(scope, sql); // Browses without a focus have no parameters to bind if (scope.hasFocus()) { String value = subqueryValue; if (value == null && scope.getFocus() instanceof String) { value = (String)scope.getFocus(); } statement.setString(1, value); // Binds the parameter in the subquery clause if (subqueryValue != null) { statement.setString(2, value); } } if (log.isDebugEnabled()) { log.debug("Created SQL \"" + sql + "\""); } return statement; } /** * Create a SQL string to run the correct query. * * @param scope * @param itemValue * FIXME ?? * @param isCount * @return */ private static String createSqlInternal(BrowseScope scope, String itemValue, boolean isCount) { String tablename = BrowseTables.getTable(scope); String column = BrowseTables.getValueColumn(scope); int browseType = scope.getBrowseType(); StringBuffer sqlb = new StringBuffer(); sqlb.append("select "); sqlb.append(isCount ? "count(" : ""); sqlb.append(getTargetColumns(scope)); sqlb.append(isCount ? ")" : ""); /** * This next bit adds another column to the query, so authors don't show * up lower-case */ if ((browseType == AUTHORS_BROWSE) && !isCount) { sqlb.append(",author"); } if ((browseType == SUBJECTS_BROWSE) && !isCount) { sqlb.append(",subject"); } sqlb.append(" from "); sqlb.append(tablename); // If the browse uses items (or item ids) instead of String values // make a subquery. // We use a separate query to make sure the subquery works correctly // when item values are the same. (this is transactionally // safe because we set the isolation level). // If we're NOT searching from the start, add some clauses boolean addedWhereClause = false; if (scope.hasFocus()) { String subquery = null; if (scope.focusIsItem()) { subquery = new StringBuffer().append(" or ( ").append(column) .append(" = ? and item_id {0} ").append( scope.getFocusItemId()).append(")").toString(); } if (log.isDebugEnabled()) { log.debug("Subquery is \"" + subquery + "\""); } sqlb.append(" where ").append("(").append(column).append(" {1} ") .append("?").append(scope.focusIsItem() ? subquery : "") .append(")"); addedWhereClause = true; } String connector = addedWhereClause ? " and " : " where "; sqlb.append(getScopeClause(scope, connector)); // For counting, skip the "order by" and "limit" clauses if (isCount) { return sqlb.toString(); } // Add an order by clause -- a parameter sqlb .append(" order by ") .append(column) .append("{2}") .append( ((scope.focusIsString() && (scope.getBrowseType() != ITEMS_BY_DATE_BROWSE)) || (scope.getBrowseType() == AUTHORS_BROWSE) || (scope .getBrowseType() == SUBJECTS_BROWSE)) ? "" : ", item_id{2}"); String myquery = sqlb.toString(); // A limit on the total returned (Postgres extension) if (!scope.hasNoLimit()) { if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) { myquery = "SELECT * FROM (" + myquery + ") WHERE ROWNUM <= {3} "; } else { // postgres uses LIMIT myquery = myquery + " LIMIT {3} "; } } return myquery; } /** * Format SQL according to the browse type. * * @param scope * @param sql * @param subqueryValue * FIXME ?? * @param after * @return * * */ private static String formatSql(BrowseScope scope, String sql, String subqueryValue, boolean after) { boolean before = !after; int browseType = scope.getBrowseType(); boolean ascending = scope.getAscending(); int numberDesired = before ? scope.getNumberBefore() : scope.getTotal(); // Search operator // Normal case: before is less than, after is greater than or equal String beforeOperator = "<"; String afterOperator = ">="; // For authors, only equality is relevant if (browseType == ITEMS_BY_AUTHOR_BROWSE) { afterOperator = "="; } if (browseType == ITEMS_BY_SUBJECT_BROWSE) { afterOperator = "="; } // Subqueries add a clause which checks for the item specifically, // so we do not check for equality here if (subqueryValue != null) { beforeOperator = "<"; afterOperator = ">"; } if (!ascending) { beforeOperator = ">"; afterOperator = "<="; } if (browseType == ITEMS_BY_DATE_BROWSE) { if (!ascending) { beforeOperator = ">"; afterOperator = "<"; } else { beforeOperator = "<"; afterOperator = ">"; } } String beforeSubqueryOperator = "<";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -