indexAll method uses ItemIterator and returns number of Items indexed

Add getNormalizedTitle method
Implementation cleanups:
  + getTotalInIndex method returns the number of Items in a Browse index.
      previously this functionality was clumped together in the
      getSomethingInternal() method
 + getTargetColumns() returns the correct columns for a browse type
 + getSubqueryClause() does what its name says
 + getItemId() ditto
 + addScopeClause() puts all the scoping logic in one place

Added examples of generated SQL to javadoc
Remove unused main method from NormalizedTitle class
Resource cleanups in BrowseCache class


git-svn-id: http://scm.dspace.org/svn/repo/trunk@111 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Peter Breton
2002-06-06 15:27:03 +00:00
parent fdfed51292
commit cfd5f0b515

View File

@@ -328,22 +328,25 @@ public class Browse
* Index all items in DSpace. This method may be resource-intensive. * Index all items in DSpace. This method may be resource-intensive.
* *
* @param context - The database context * @param context - The database context
* @return - The number of items indexed.
* @exception SQLException - If a database error occurs * @exception SQLException - If a database error occurs
*/ */
public static void indexAll(Context context) public static int indexAll(Context context)
throws SQLException throws SQLException
{ {
indexRemoveAll(context); indexRemoveAll(context);
TableRowIterator iterator = DatabaseManager.query(context, null, "select item_id from Item"); int count = 0;
ItemIterator iterator = Item.findAll(context);
while (iterator.hasNext()) while (iterator.hasNext())
{ {
TableRow row = (TableRow) iterator.next(); itemAdded(context, (Item) iterator.next());
Item item = Item.find(context, row.getIntColumn("item_id")); count++;
itemAdded(context, item);
} }
}
return count;
}
/** /**
* Remove all items in DSpace from the Browse index. * Remove all items in DSpace from the Browse index.
@@ -362,6 +365,14 @@ public class Browse
} }
} }
////////////////////////////////////////
// Other methods
////////////////////////////////////////
public static String getNormalizedTitle(String title, String lang)
{
return NormalizedTitle.normalize(title, lang);
}
//////////////////////////////////////// ////////////////////////////////////////
// Private methods // Private methods
//////////////////////////////////////// ////////////////////////////////////////
@@ -394,10 +405,8 @@ public class Browse
//////////////////// ////////////////////
// Sanity checks // Sanity checks
//////////////////// ////////////////////
// No null collections
if ((scopeType == COLLECTION_SCOPE) && (obj == null)) if ((scopeType == COLLECTION_SCOPE) && (obj == null))
throw new IllegalArgumentException("Collection is null"); throw new IllegalArgumentException("Collection is null");
// No null communities
if ((scopeType == COMMUNITY_SCOPE) && (obj == null)) if ((scopeType == COMMUNITY_SCOPE) && (obj == null))
throw new IllegalArgumentException("Community is null"); throw new IllegalArgumentException("Community is null");
@@ -410,7 +419,10 @@ public class Browse
BrowseInfo cachedInfo = (BrowseInfo) BrowseCache.get(key); BrowseInfo cachedInfo = (BrowseInfo) BrowseCache.get(key);
if (cachedInfo != null) if (cachedInfo != null)
{
cachedInfo.setCached(true);
return cachedInfo; return cachedInfo;
}
//////////////////// ////////////////////
// Convenience booleans // Convenience booleans
@@ -420,8 +432,7 @@ public class Browse
boolean valueIsItem = (value instanceof Item); boolean valueIsItem = (value instanceof Item);
boolean valueIsInteger = (value instanceof Integer); boolean valueIsInteger = (value instanceof Integer);
// True if we want to search from the start // True if we want to search from the start
// This is true when: // This is true when the client passed a null value
// the client passed a null value
boolean searchFromStart = (value == null); boolean searchFromStart = (value == null);
// True if we want ALL values // True if we want ALL values
boolean nolimit = (total == -1); boolean nolimit = (total == -1);
@@ -450,16 +461,6 @@ public class Browse
// See http://www.postgresql.org/idocs/index.php?xact-serializable.html // See http://www.postgresql.org/idocs/index.php?xact-serializable.html
// //
// Performance hit unknown... // Performance hit unknown...
boolean autocommit = connection.getAutoCommit();
if (!autocommit)
{
if (log.isInfoEnabled())
log.info("Browse: Autocommit is false");
}
connection.setAutoCommit(false);
int transactionIsolation = connection.getTransactionIsolation(); int transactionIsolation = connection.getTransactionIsolation();
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
@@ -471,7 +472,9 @@ public class Browse
//////////////////// ////////////////////
// Run a subquery, if necessary // Run a subquery, if necessary
String subqueryValue = needsSubquery ? String subqueryValue = needsSubquery ?
doSubquery(connection, obj, scopeType, browseType, value) : null; doSubquery(connection, obj,
scopeType, browseType,
getItemId(value)) : null;
if (needsSubquery && log.isInfoEnabled()) if (needsSubquery && log.isInfoEnabled())
log.info("Got subquery value: \"" + subqueryValue + "\""); log.info("Got subquery value: \"" + subqueryValue + "\"");
@@ -483,8 +486,8 @@ public class Browse
if (log.isInfoEnabled()) if (log.isInfoEnabled())
log.info("Created sql: \"" + sql + "\""); log.info("Created sql: \"" + sql + "\"");
// Loop through twice -- once to get items _before_ the value, // Loop through twice -- once to get items _before_ the value,
// and once for those after. // and once for those after.
try try
{ {
List theResults = new ArrayList(); List theResults = new ArrayList();
@@ -509,7 +512,7 @@ public class Browse
if ((!before) && (total == 0)) if ((!before) && (total == 0))
continue; continue;
// Format the SQL // Format the SQL
String SQL = formatSql(sql, String SQL = formatSql(sql,
browseType, browseType,
before ? numberBefore : total, before ? numberBefore : total,
@@ -522,7 +525,7 @@ public class Browse
log.info("Formatted " + (before ? "before" : "after") + log.info("Formatted " + (before ? "before" : "after") +
" sql: \"" + SQL + "\""); " sql: \"" + SQL + "\"");
// Create a PreparedStatement // Create a PreparedStatement
statement = connection.prepareStatement(SQL); statement = connection.prepareStatement(SQL);
///////////////////////// /////////////////////////
@@ -531,8 +534,7 @@ public class Browse
String bindValue = ((!searchFromStart) && needsSubquery) ? String bindValue = ((!searchFromStart) && needsSubquery) ?
subqueryValue : (String) value; subqueryValue : (String) value;
bindParameters(statement, bindValue, searchFromStart, needsSubquery, bindParameters(statement, bindValue, searchFromStart, needsSubquery);
false);
// Run a query, get results // Run a query, get results
String table = BrowseTables.getTable(scopeType, browseType); String table = BrowseTables.getTable(scopeType, browseType);
@@ -586,29 +588,7 @@ public class Browse
int resultSize = theResults.size(); int resultSize = theResults.size();
////////////////////////////// int theTotal = getTotalInIndex(obj, scopeType, browseType, connection, value, total, resultSize);
// Counting
//////////////////////////////
boolean countTotal = true;
int theTotal = 0;
// Got less authors than requested
// This means that we do not need to count them
if ((browseType == ITEMS_BY_AUTHOR_BROWSE) && (total > resultSize))
{
countTotal = false;
theTotal = resultSize;
}
if (countTotal)
{
statement = createTotalSql(obj, scopeType, browseType, connection, value);
theTotal = getIntValue(statement);
// Cleanup the statement
statement.close();
}
// OK, we've counted everything. // OK, we've counted everything.
// Now figure out how many things match the specific query. // Now figure out how many things match the specific query.
@@ -657,7 +637,7 @@ public class Browse
////////// //////////
String svalue = valueIsString ? (String) value : subqueryValue; String svalue = valueIsString ? (String) value : subqueryValue;
bindParameters(statement, svalue, searchFromStart, needsSubquery, true); bindParameters(statement, svalue, searchFromStart, needsSubquery);
////////// //////////
// Run the query, extract results // Run the query, extract results
@@ -679,37 +659,12 @@ public class Browse
statement.close(); statement.close();
} }
if (log.isInfoEnabled()) // FIXME -- sorting is busted
{ BrowseInfo info = new BrowseInfo
log.info("Number of Results: " + theResults.size() + (theResults, overallPosition,
" Overall position: " + overallPosition + theTotal, offset);
" Total " + theTotal +
" Offset " + offset);
int lastIndex = (overallPosition + resultSize);
boolean noresults = (theTotal == 0) || (resultSize == 0);
log.info("Got results: " + logInfo(info);
(noresults ? 0 : overallPosition) +
" to " +
(noresults ? 0 : lastIndex) +
" out of " + theTotal);
}
BrowseInfo info = null;
if (sort == null)
{
info = new BrowseInfo(theResults, overallPosition, theTotal, offset);
}
else
{
String element = sort.booleanValue() ? "title" : "date";
String qualifier = sort.booleanValue() ? null : "issued";
// FIXME
info = new BrowseInfo
(theResults, overallPosition,
theTotal, offset);
}
BrowseCache.add(key, info); BrowseCache.add(key, info);
return info; return info;
@@ -729,8 +684,7 @@ public class Browse
// Need to do this because "closing" the connection simply // Need to do this because "closing" the connection simply
// returns it to the pool // returns it to the pool
connection.setTransactionIsolation(transactionIsolation); connection.setTransactionIsolation(transactionIsolation);
connection.setAutoCommit(autocommit); // connection.close();
connection.close();
} }
} }
} }
@@ -750,48 +704,13 @@ public class Browse
) )
throws SQLException throws SQLException
{ {
////////////////////
// Table and column
////////////////////
String tablename = BrowseTables.getTable(scope, browseType); String tablename = BrowseTables.getTable(scope, browseType);
String column = BrowseTables.getValueColumn(browseType); String column = BrowseTables.getValueColumn(browseType);
//////////////////// StringBuffer sqlb = new StringBuffer()
// Convenience booleans
////////////////////
// True if the value is....
boolean valueIsString = (value instanceof String);
boolean valueIsItem = (value instanceof Item);
boolean valueIsInteger = (value instanceof Integer);
// True if we want to search from the start
// boolean searchFromStart = (value == null) && (! valueIsInteger) && (! valueIsInteger);
boolean searchFromStart = (value == null);
// True if we want ALL values
boolean nolimit = (total == -1);
// True if we added a where clause
boolean addedWhereClause = false;
// True if we need a subquery
boolean needsSubquery = valueIsInteger || valueIsItem;
////////////////////
// Ids
////////////////////
int communityId = (obj instanceof Community) ? ((Community) obj).getID() : -1;
int collectionId = (obj instanceof Collection) ? ((Collection) obj).getID() : -1;
int item_id = -1;
if (valueIsInteger)
item_id = ((Integer) value).intValue();
else if (valueIsItem)
item_id = ((Item) value).getID();
// Target columns are either just authors or everything
String targetColumns = (browseType == AUTHORS_BROWSE) ? "distinct author" : "*";
StringBuffer sqlb = new StringBuffer()// Column(s) to select
.append("select ") .append("select ")
.append(isCount ? "count(" : "") .append(isCount ? "count(" : "")
.append(targetColumns) .append(getTargetColumns(browseType))
.append(isCount ? ")" : "") .append(isCount ? ")" : "")
.append(" from ") .append(" from ")
.append(tablename); .append(tablename);
@@ -801,26 +720,19 @@ public class Browse
// We use a separate query to make sure the subquery works correctly // We use a separate query to make sure the subquery works correctly
// when item values are the same. (this is transactionally // when item values are the same. (this is transactionally
// safe because we set the isolation level). // safe because we set the isolation level).
String subquery = null;
if (subqueryValue != null) // If we're NOT searching from the start, add some clauses
boolean addedWhereClause = false;
if (value != null)
{ {
subquery = new StringBuffer() boolean needsSubquery = (value instanceof Integer) ||
.append(" or ( ") (value instanceof Item);
.append(column) String subquery = (subqueryValue == null ? null :
// Item id must be before or after the desired item getSubqueryClause(column, getItemId(value)));
.append(" = ? and item_id {0} ")
.append(item_id)
.append(")")
.toString();
}
if (log.isDebugEnabled()) if (log.isDebugEnabled())
log.debug("Subquery is \"" + subquery + "\""); log.debug("Subquery is \"" + subquery + "\"");
// If we're NOT searching from the start, add some clauses
if (!searchFromStart)
{
sqlb sqlb
.append(" where ") .append(" where ")
.append("(") .append("(")
@@ -834,79 +746,100 @@ public class Browse
addedWhereClause = true; addedWhereClause = true;
} }
// Optionally, add a scope clause addScopeClause(sqlb, scope, obj,
if (scope == COLLECTION_SCOPE) addedWhereClause ? " and " : " where ");
sqlb.append(addedWhereClause ? " and " : " where ").append(" collection_id = ").append(collectionId);
else if (scope == COMMUNITY_SCOPE)
sqlb.append(addedWhereClause ? " and " : " where ").append(" community_id = ").append(communityId);
// No more clauses after this (except maybe Santa Claus)..... // For counting, skip the "order by" and "limit" clauses
// For counting, skip the "order by" and "limit" clauses
if (isCount) if (isCount)
return sqlb.toString(); return sqlb.toString();
// Add an order by clause -- a parameter // Add an order by clause -- a parameter
sqlb.append(" order by ").append(column).append("{2}") sqlb.append(" order by ").append(column).append("{2}")
// If an item, make sure it's ordered by item_id as well // If an item, make sure it's ordered by item_id as well
.append((valueIsString || (browseType == AUTHORS_BROWSE)) .append(((value instanceof String) || (browseType == AUTHORS_BROWSE))
? "" : ", item_id"); ? "" : ", item_id");
// A limit on the total returned (Postgres extension) // A limit on the total returned (Postgres extension)
// This is a parameter // This is a parameter
if (!nolimit) if (total != -1)
sqlb.append(" LIMIT {3} "); sqlb.append(" LIMIT {3} ");
return sqlb.toString(); return sqlb.toString();
} }
/** /**
* Create a PreparedStatement which counts the total objects in an index. * Return the total number of values in an index.
* Although this may look a bit dizzying, the basic idea is
* straightforward:
*
* We total Authors with SQL like:
* select count(distinct author) from ItemsByAuthor;
* ItemsByAuthor with:
* select count(*) from ItemsByAuthor where author = ?;
* and every other index with:
* select count(*) from ItemsByTitle;
*
* If limiting to a community or collection, we add a clause like:
* community_id = 7
* collection_id = 201
*/ */
private static PreparedStatement createTotalSql(Object obj, private static int getTotalInIndex(Object obj,
int scope, int scopeType,
int browseType, int browseType,
Connection connection, Connection connection,
Object value Object value,
) int total,
int resultSize)
throws SQLException throws SQLException
{ {
// For counting the total, we need to know: if ((browseType == ITEMS_BY_AUTHOR_BROWSE) && (total > resultSize))
// whether browseType is ITEMS_BY_AUTHOR_BROWSE. In this case, we'll return resultSize;
// request different columns.
// scope is COLLECTION_SCOPE or COMMUNITY_SCOPE. If it is, we'll
// append a clause specifying the id.
boolean needsWhere = (browseType == ITEMS_BY_AUTHOR_BROWSE) || PreparedStatement statement = null;
(scope == COLLECTION_SCOPE) || (scope == COMMUNITY_SCOPE);
boolean needsAnd = (browseType == ITEMS_BY_AUTHOR_BROWSE) &&
((scope == COLLECTION_SCOPE) || (scope == COMMUNITY_SCOPE));
//////////////////// try
// Ids {
//////////////////// String table = BrowseTables.getTable(scopeType, browseType);
int communityId = (obj instanceof Community) ? ((Community) obj).getID() : -1;
int collectionId = (obj instanceof Collection) ? ((Collection) obj).getID() : -1;
String table = BrowseTables.getTable(scope, browseType); StringBuffer buffer = new StringBuffer()
.append("select count(")
.append(getTargetColumns(browseType))
.append(") from ")
.append(table);
String sql = new StringBuffer().append("select count(").append((browseType == AUTHORS_BROWSE) ? "distinct author" : "*").append(") from ").append(table).append(needsWhere ? " where " : "").append((browseType == ITEMS_BY_AUTHOR_BROWSE) ? " author = ?" : "").append(needsAnd ? " and " : "")// Optionally, add a scope clause boolean hasWhere = false;
.append((scope == COLLECTION_SCOPE) ? " collection_id = " : "").append((scope == COLLECTION_SCOPE) ? Integer.toString(collectionId) : "").append((scope == COMMUNITY_SCOPE) ? " community_id = " : "").append((scope == COMMUNITY_SCOPE) ? Integer.toString(communityId) : "").toString(); if (browseType == ITEMS_BY_AUTHOR_BROWSE)
{
hasWhere = true;
buffer.append(" where author = ?");
}
if (log.isInfoEnabled()) String sql = addScopeClause(buffer, scopeType, obj,
log.info("Total sql: \"" + sql + "\""); hasWhere ? "and" : "where")
.toString();
PreparedStatement statement = connection.prepareStatement(sql); if (log.isInfoEnabled())
log.info("Total sql: \"" + sql + "\"");
// Bind the author value, if necessary statement = connection.prepareStatement(sql);
if (browseType == ITEMS_BY_AUTHOR_BROWSE)
statement.setString(1, (String) value);
return statement; if (browseType == ITEMS_BY_AUTHOR_BROWSE)
statement.setString(1, (String) value);
return getIntValue(statement);
}
finally
{
if (statement != null)
statement.close();
}
} }
/** /**
* Format the SQL string according to BROWSETYPE. * Format SQL according to BROWSETYPE.
*
* The different browses use different operators.
*
*/ */
private static String formatSql(String sql, private static String formatSql(String sql,
int browseType, int browseType,
@@ -923,8 +856,8 @@ public class Browse
// For authors, only equality is relevant // For authors, only equality is relevant
if (browseType == ITEMS_BY_AUTHOR_BROWSE) if (browseType == ITEMS_BY_AUTHOR_BROWSE)
afterOperator = "="; afterOperator = "=";
// Subqueries add a clause which checks for the item specifically, // Subqueries add a clause which checks for the item specifically,
// so we do not check for equality here // so we do not check for equality here
if (subqueryValue != null) if (subqueryValue != null)
{ {
beforeOperator = "<"; beforeOperator = "<";
@@ -953,9 +886,9 @@ public class Browse
if (!ascending) if (!ascending)
order = before ? "" : " desc"; order = before ? "" : " desc";
// Note that it's OK to have unused arguments in the array; // Note that it's OK to have unused arguments in the array;
// see the javadoc of java.text.MessageFormat // see the javadoc of java.text.MessageFormat
// for the whole story. // for the whole story.
List args = new ArrayList(); List args = new ArrayList();
args.add(before ? beforeSubqueryOperator : afterSubqueryOperator); args.add(before ? beforeSubqueryOperator : afterSubqueryOperator);
@@ -970,93 +903,183 @@ public class Browse
* Bind PreparedStatement parameters * Bind PreparedStatement parameters
*/ */
private static void bindParameters(PreparedStatement statement, private static void bindParameters(PreparedStatement statement,
String value, String value,
boolean searchFromStart, boolean searchFromStart,
boolean needsSubquery, boolean needsSubquery
boolean isCount
) )
throws SQLException throws SQLException
{ {
if (!searchFromStart) if (searchFromStart)
return;
if (needsSubquery)
{ {
if (needsSubquery) if (log.isDebugEnabled())
{ log.debug("Binding subquery value \"" + value + "\"");
if (log.isDebugEnabled())
log.debug("Binding subquery value \"" + value + "\"");
statement.setString(1, value); statement.setString(1, value);
statement.setString(2, value); statement.setString(2, value);
}
else
{
if (log.isDebugEnabled())
log.debug("Binding value \"" + value + "\"");
statement.setString(1, (String) value);
}
} }
} else
private static String doSubquery(Connection connection,
Object obj,
int scope,
int browseType,
Object value
)
throws SQLException
{
PreparedStatement statement = null;
String tablename = BrowseTables.getTable(scope, browseType);
String column = BrowseTables.getValueColumn(browseType);
////////////////////
// Ids
////////////////////
int communityId = (obj instanceof Community) ? ((Community) obj).getID() : -1;
int collectionId = (obj instanceof Collection) ? ((Collection) obj).getID() : -1;
int item_id = -1;
if (value instanceof Integer)
item_id = ((Integer) value).intValue();
else if (value instanceof Item)
item_id = ((Item) value).getID();
try
{ {
String itemValueQuery = new StringBuffer().append("select ").append("max(").append(column).append(") from ").append(tablename).append(" where ").append(" item_id = ").append(item_id).append((scope == COLLECTION_SCOPE) ? " and collection_id = " : "").append((scope == COLLECTION_SCOPE) ? Integer.toString(collectionId) : "").append((scope == COMMUNITY_SCOPE) ? " and community_id = " : "").append((scope == COMMUNITY_SCOPE) ? Integer.toString(communityId) : "").toString(); if (log.isDebugEnabled())
log.debug("Binding value \"" + value + "\"");
// Run the query statement.setString(1, (String) value);
statement = connection.prepareStatement(itemValueQuery);
return getStringValue(statement);
}
finally
{
if (statement != null)
statement.close();
} }
} }
/** /**
* Return a single String value from STATEMENT. * Run a query to find a browse index value for item_id.
*
* In general, these queries look like this:
* select max(date_issued) from ItemsByDate where item_id = 7;
*
* The max operator ensures that only one value is returned.
*
* If limiting to a community or collection, we add a clause like:
* community_id = 7
* collection_id = 201
*/ */
private static String getStringValue(PreparedStatement statement) private static String doSubquery(Connection connection,
Object obj,
int scope,
int browseType,
int item_id
)
throws SQLException throws SQLException
{ {
PreparedStatement statement = null;
ResultSet results = null; ResultSet results = null;
try try
{ {
String tablename = BrowseTables.getTable(scope, browseType);
String column = BrowseTables.getValueColumn(browseType);
StringBuffer buffer = new StringBuffer()
.append("select ")
.append("max(")
.append(column)
.append(") from ")
.append(tablename)
.append(" where ")
.append(" item_id = ")
.append(item_id);
String itemValueQuery = addScopeClause(buffer, scope, obj, "and")
.toString();
statement = connection.prepareStatement(itemValueQuery);
results = statement.executeQuery(); results = statement.executeQuery();
return results.next() ? results.getString(1) : null; return results.next() ? results.getString(1) : null;
} }
finally finally
{ {
if (statement != null)
statement.close();
if (results != null) if (results != null)
results.close(); results.close();
} }
} }
/**
* Write out a log4j message
*/
private static void logInfo(BrowseInfo info)
{
if (! log.isInfoEnabled())
return;
log.info("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.info("Got no results");
log.info("Got results: " +
info.getOverallPosition() +
" to " +
lastIndex +
" out of " + info.getTotal());
}
/**
* Return the columns according to browseType.
*/
private static String getTargetColumns(int browseType)
{
return (browseType == AUTHORS_BROWSE) ? "distinct author" : "*";
}
/**
* Return a subquery clause.
* The SQL looks like this:
* or (sort_title = ? and item_id {0} 3)
*/
private static String getSubqueryClause(String column, int item_id)
{
return new StringBuffer()
.append(" or ( ")
.append(column)
// Item id must be before or after the desired item
.append(" = ? and item_id {0} ")
.append(item_id)
.append(")")
.toString();
}
/**
* Return the id from VALUE, which is either an Item or an Integer
*/
static int getItemId(Object value)
{
if (value instanceof Integer)
return ((Integer) value).intValue();
else if (value instanceof Item)
return ((Item) value).getID();
throw new IllegalArgumentException("Value must be Integer or Item");
}
/**
* Add a scoping clause to BUFFER.
*
* If scope is ALLDSPACE_SCOPE, nothing is added.
*
* Otherwise, the SQL clause which is appended looks like:
* PREFIX community_id = 7
* PREFIX collection_id = 203
*
* PREFIX may be empty, or it may be a SQL keyword like "where", "and",
* and so forth.
*/
static StringBuffer addScopeClause(StringBuffer buffer,
int scope,
Object obj,
String prefix)
{
if (scope == ALLDSPACE_SCOPE)
return buffer;
int id = (obj instanceof Community) ?
((Community) obj).getID() : ((Collection) obj).getID();
String column = (scope == COMMUNITY_SCOPE) ?
"community_id" : "collection_id";
return buffer
.append(prefix)
.append(" ")
.append(column)
.append(" = ")
.append(id);
}
/** /**
* Return a single int value from STATEMENT. * Return a single int value from STATEMENT.
*/ */
@@ -1196,7 +1219,9 @@ class NormalizedTitle
return title.substring(startAt); return title.substring(startAt);
// Otherwise, return the substring with the stop word appended // Otherwise, return the substring with the stop word appended
return new StringBuffer(title.substring(startAt)).append(", ").append(stop).toString(); return new StringBuffer(title.substring(startAt))
.append(", ")
.append(stop).toString();
} }
/** /**
@@ -1246,40 +1271,6 @@ class NormalizedTitle
return first; return first;
} }
/**
* Embedded test harness
*
* @param argv - Command-line arguments
*/
public static void main(String[] argv)
{
String[] test_titles = new String[]
{
"A Test title",
"Title without stop words",
"Theater of the Absurd",
"Another Misleading Title",
"An Egg and a Bunny",
" Leading whitespace",
" An omlette",
" The Missing Link",
" Then Came You",
" Leading and trailing whitespace ",
" The An And -- Very Common Words",
"The",
" The",
"",
null
};
for (int i = 0; i < test_titles.length; i++)
{
System.out.println
("Sorting title for \"" + test_titles[i] + "\"" +
" is " + "\"" + normalizeEnglish(test_titles[i]) + "\"");
}
}
} }
// FIXME Use BrowseScope instead? // FIXME Use BrowseScope instead?
@@ -1433,24 +1424,35 @@ class BrowseCache
public static boolean indexHasChanged(BrowseKey key) public static boolean indexHasChanged(BrowseKey key)
throws SQLException throws SQLException
{ {
int tableid = BrowseTables.getTableId(key.scope, key.browseType); Context context = null;
try
{
int tableid = BrowseTables.getTableId(key.scope, key.browseType);
Context context = new Context(); context = new Context();
TableRow results = countAndMax(context, key); TableRow results = countAndMax(context, key);
long count = results != null ? results.getLongColumn("count") : -1; long count = results != null ? results.getLongColumn("count") : -1;
int max = results != null ? results.getIntColumn("max") : -1; int max = results != null ? results.getIntColumn("max") : -1;
context.complete(); context.complete();
// Same? // Same?
if ((count == COUNT[tableid]) && (max == MAXIMUM[tableid])) if ((count == COUNT[tableid]) && (max == MAXIMUM[tableid]))
return false; return false;
// Update the counts // Update the counts
MAXIMUM[tableid] = max; MAXIMUM[tableid] = max;
COUNT[tableid] = count; COUNT[tableid] = count;
// The index has in fact changed // The index has in fact changed
return true; return true;
}
catch (SQLException sqle)
{
if (context != null)
context.abort();
throw sqle;
}
} }
/** /**
@@ -1468,17 +1470,28 @@ class BrowseCache
public static void updateIndexData(BrowseKey key) public static void updateIndexData(BrowseKey key)
throws SQLException throws SQLException
{ {
int tableid = BrowseTables.getTableId(key.scope, key.browseType); Context context = null;
Context context = new Context(); try
TableRow results = countAndMax(context, key); {
long count = results != null ? results.getLongColumn("count") : -1; int tableid = BrowseTables.getTableId(key.scope, key.browseType);
int max = results != null ? results.getIntColumn("max") : -1;
context.complete();
// Update the counts context = new Context();
MAXIMUM[tableid] = max; TableRow results = countAndMax(context, key);
COUNT[tableid] = count; long count = results != null ? results.getLongColumn("count") : -1;
int max = results != null ? results.getIntColumn("max") : -1;
context.complete();
MAXIMUM[tableid] = max;
COUNT[tableid] = count;
}
catch (Exception e)
{
if (context != null)
context.abort();
e.printStackTrace();
}
} }
/** /**
@@ -1497,18 +1510,11 @@ class BrowseCache
// then some items may have been removed. We assume that // then some items may have been removed. We assume that
// values never change. // values never change.
int communityId = (obj instanceof Community) ? StringBuffer buffer = new StringBuffer()
((Community) obj).getID() : -1;
int collectionId = (obj instanceof Collection) ?
((Collection) obj).getID() : -1;
String sql = new StringBuffer()
.append("select count({0}) as count, max({0}) as max from ") .append("select count({0}) as count, max({0}) as max from ")
.append(BrowseTables.getTable(scope, browseType)) .append(BrowseTables.getTable(scope, browseType));
.append((scope == Browse.COLLECTION_SCOPE) ? " where collection_id = " : "")
.append((scope == Browse.COLLECTION_SCOPE) ? Integer.toString(collectionId) : "") String sql = Browse.addScopeClause(buffer, scope, obj, "where")
.append((scope == Browse.COMMUNITY_SCOPE) ? " where community_id = " : "")
.append((scope == Browse.COMMUNITY_SCOPE) ? Integer.toString(communityId) : "")
.toString(); .toString();
// Format it to use the correct columns // Format it to use the correct columns