📄 browse.java
字号:
String afterSubqueryOperator = ">="; // For authors, only equality is relevant if (browseType == ITEMS_BY_AUTHOR_BROWSE || browseType == ITEMS_BY_SUBJECT_BROWSE) { afterSubqueryOperator = "="; } if (!ascending) { beforeSubqueryOperator = ">"; afterSubqueryOperator = "<="; } String order = before ? " desc" : ""; if (!ascending) { order = before ? "" : " desc"; } // Note that it's OK to have unused arguments in the array; // see the javadoc of java.text.MessageFormat // for the whole story. List args = new ArrayList(); args.add(before ? beforeSubqueryOperator : afterSubqueryOperator); args.add(before ? beforeOperator : afterOperator); args.add(order); args.add(new Integer(numberDesired)); return MessageFormat.format(sql, args.toArray()); } /** * Log a message about the results of a browse. * * @param info */ private static void logInfo(BrowseInfo info) { if (!log.isDebugEnabled()) { return; } log.debug("Number of Results: " + info.getResultCount() + " Overall position: " + info.getOverallPosition() + " Total " + info.getTotal() + " Offset " + info.getOffset()); int lastIndex = (info.getOverallPosition() + info.getResultCount()); boolean noresults = (info.getTotal() == 0) || (info.getResultCount() == 0); if (noresults) { log.debug("Got no results"); } log.debug("Got results: " + info.getOverallPosition() + " to " + lastIndex + " out of " + info.getTotal()); } /** * Return the name or names of the column(s) to query for a browse. * * @param scope * The current browse scope * @return The name or names of the columns to query */ private static String getTargetColumns(BrowseScope scope) { int browseType = scope.getBrowseType(); if (browseType == AUTHORS_BROWSE) return "distinct sort_author"; else if (browseType == SUBJECTS_BROWSE) return "distinct sort_subject"; else return "*"; } /** * <p> * Return a scoping clause. * </p> * * <p> * If scope is ALLDSPACE_SCOPE, return the empty string. * </p> * * <p> * Otherwise, the SQL clause which is generated looks like: * </p> * CONNECTOR community_id = 7 CONNECTOR collection_id = 203 * * <p> * CONNECTOR may be empty, or it may be a SQL keyword like <em>where</em>, * <em>and</em>, and so forth. * </p> * * @param scope * @param connector * FIXME ?? * @return */ static String getScopeClause(BrowseScope scope, String connector) { if (scope.isAllDSpaceScope()) { return ""; } boolean isCommunity = scope.isCommunityScope(); Object obj = scope.getScope(); int id = (isCommunity) ? ((Community) obj).getID() : ((Collection) obj) .getID(); String column = (isCommunity) ? "community_id" : "collection_id"; return new StringBuffer().append(" ").append(connector).append(" ") .append(column).append(" = ").append(id).toString(); } /** * Create a PreparedStatement with the given sql. * * @param scope * The current Browse scope * @param sql * SQL query * @return A PreparedStatement with the given SQL * @exception SQLException * If a database error occurs */ private static PreparedStatement createStatement(BrowseScope scope, String sql) throws SQLException { Connection connection = scope.getContext().getDBConnection(); return connection.prepareStatement(sql); } /** * Return a single int value from the PreparedStatement. * * @param statement * A PreparedStatement for a query which returns a single value * of INTEGER type. * @return The integer value from the query. * @exception SQLException * If a database error occurs */ private static int getIntValue(PreparedStatement statement) throws SQLException { ResultSet results = null; try { results = statement.executeQuery(); return results.next() ? results.getInt(1) : (-1); } finally { if (results != null) { results.close(); } } } /** * Convert a list of item ids to full Items. * * @param context * The current DSpace context * @param ids * A list of item ids. Each member of the list is an Integer. * @return A list of Items with the given ids. * @exception SQLException * If a database error occurs */ private static List toItems(Context context, List ids) throws SQLException { // FIXME Again, this is probably a more general need List results = new ArrayList(); for (Iterator iterator = ids.iterator(); iterator.hasNext();) { Integer id = (Integer) iterator.next(); Item item = Item.find(context, id.intValue()); if (item != null) { results.add(item); } } return results; }}class NormalizedTitle{ private static String[] STOP_WORDS = new String[] { "A", "An", "The" }; /** * Returns a normalized String corresponding to TITLE. * * @param title * @param lang * @return */ public static String normalize(String title, String lang) { if (lang == null) { return title; } return (lang.startsWith("en")) ? normalizeEnglish(title) : title; } /** * Returns a normalized String corresponding to TITLE. The normalization is * effected by: * + first removing leading spaces, if any + then removing the first * leading occurences of "a", "an" and "the" (in any case). + removing any * whitespace following an occurence of a stop word * * This simple strategy is only expected to be used for English words. * * @param oldtitle * @return */ public static String normalizeEnglish(String oldtitle) { // Corner cases if (oldtitle == null) { return null; } if (oldtitle.length() == 0) { return oldtitle; } // lower case, stupid! (sorry, just a rant about bad contractors) String title = oldtitle.toLowerCase(); // State variables // First find leading whitespace, if any int startAt = firstWhitespace(title); boolean modified = (startAt != 0); boolean usedStopWord = false; String stop = null; // Examine each stop word for (int i = 0; i < STOP_WORDS.length; i++) { stop = STOP_WORDS[i]; int stoplen = stop.length(); // The title must start with the stop word (skipping white space // and ignoring case). boolean found = title.toLowerCase().startsWith(stop.toLowerCase(), startAt) && ( // The title must be longer than whitespace plus the // stop word title.length() >= (startAt + stoplen + 1)) && // The stop word must be followed by white space Character.isWhitespace(title.charAt(startAt + stoplen)); if (found) { modified = true; usedStopWord = true; startAt += stoplen; // Strip leading whitespace again, if any int firstw = firstWhitespace(title, startAt); if (firstw != 0) { startAt = firstw; } // Only process a single stop word break; } } // If we didn't change anything, just return the title as-is if (!modified) { return title; } // If we just stripped white space, return a substring if (!usedStopWord) { return title.substring(startAt); } // Otherwise, return the substring with the stop word appended return new StringBuffer(title.substring(startAt)).append(", ").append( stop).toString(); } /** * Return the index of the first non-whitespace character in the String. * * @param title * @return */ private static int firstWhitespace(String title) { return firstWhitespace(title, 0); } /** * Return the index of the first non-whitespace character in the character * array. * * @param title * @return */ private static int firstWhitespace(char[] title) { return firstWhitespace(title, 0); } /** * Return the index of the first non-whitespace character in the String, * starting at position STARTAT. * * @param title * @param startAt * @return */ private static int firstWhitespace(String title, int startAt) { return firstWhitespace(title.toCharArray(), startAt); } /** * Return the index of the first letter or number in the character array, * starting at position STARTAT. * * @param title * @param startAt * @return */ private static int firstWhitespace(char[] title, int startAt) { int first = 0; for (int j = startAt; j < title.length; j++) { //if (Character.isWhitespace(title[j])) // Actually, let's skip anything that's not a letter or number if (!Character.isLetterOrDigit(title[j])) { first = j + 1; continue; } break; } return first; }}class BrowseCache{ private static Map tableMax = new HashMap(); private static Map tableSize = new HashMap(); /** log4j object */ private static Logger log = Logger.getLogger(BrowseCache.class); private static Map cache = new WeakHashMap(); // Everything in the cache is held via Weak References, and is // subject to being gc-ed at any time. // The dateCache holds normal references, so anything in it // will stay around. private static SortedMap dateCache = new TreeMap(); private static final int CACHE_MAXIMUM = 30; /** * Look for cached Browse data corresponding to KEY. * * @param key * @return */ public static BrowseInfo get(BrowseScope key) { if (log.isDebugEnabled()) { log .debug("Checking browse cache with " + cache.size() + " objects"); } BrowseInfo cachedInfo = (BrowseInfo) cache.get(key); try { // Index has never been calculated if (getMaximum(key) == -1) { updateIndexData(key); } if (cachedInfo == null) { if (log.isDebugEnabled()) { log.debug("Not in browse cache"); } return null; } // If we found an object, make sure that the browse indexes // have not changed. // // The granularity for this is quite large; // any change to the index and we will calculate from scratch., // Thus, the cache works well when few changes are made, or // when changes are spaced widely apart. if (indexHasChanged(key)) { if (log.isDebugEnabled()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -