/******************************************************************************* * * Copyright (c) 2003, 2004, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package edu.indiana.lib.twinpeaks.util; import java.lang.*; import java.util.*; import org.w3c.dom.*; import org.xml.sax.*; public class StatusUtils { private static org.apache.commons.logging.Log _log = LogUtils.getLog(StatusUtils.class); /** * Set up initial status information */ public static void initialize(SessionContext sessionContext, String targets) { StringTokenizer parser = new StringTokenizer(targets, " \t,"); ArrayList dbList = new ArrayList(); HashMap targetMap = getNewStatusMap(sessionContext); /* * Establish the DB list and initial (pre-LOGON) status */ while (parser.hasMoreTokens()) { String db = parser.nextToken(); HashMap emptyMap = new HashMap(); /* * Empty status entry */ emptyMap.put("STATUS", "INACTIVE"); emptyMap.put("STATUS_MESSAGE", "<none>"); emptyMap.put("HITS", "0"); emptyMap.put("ESTIMATE", "0"); emptyMap.put("MERGED", "0"); /* * Save */ dbList.add(db); targetMap.put(db, emptyMap); } /* * Search targets, global status */ sessionContext.put("TARGETS", dbList); sessionContext.putInt("active", 0); sessionContext.put("STATUS", "INACTIVE"); sessionContext.put("STATUS_MESSAGE", "<none>"); /* * Initial totals */ sessionContext.putInt("TOTAL_ESTIMATE", 0); sessionContext.putInt("TOTAL_HITS", 0); sessionContext.putInt("maxRecords", 0); /* * Assume this search is synchronous. An OSID that implements an * asynchronous search will need to set the async flags manually after * this code has finished. */ clearAsyncSearch(sessionContext); clearAsyncInit(sessionContext); } /** * Get an iterator into the system status map * @param sessionContext Active SessionContext * @return Status map Iterator */ public static Iterator getStatusMapEntrySetIterator(SessionContext sessionContext) { HashMap statusMap = (HashMap) sessionContext.get("searchStatus"); Set entrySet = Collections.EMPTY_SET; if (statusMap != null) { entrySet = statusMap.entrySet(); } return entrySet.iterator(); } /** * Get the status entry for a specified target database * @param sessionContext Active SessionContext * @param target Database name * @return Status Map for this target (null if none) */ public static HashMap getStatusMapForTarget(SessionContext sessionContext, String target) { HashMap statusMap = (HashMap) sessionContext.get("searchStatus"); return (statusMap == null) ? null : (HashMap) statusMap.get(target); } /** * Create a new status map * @param sessionContext Active SessionContext * @return Status Map for this target */ public static HashMap getNewStatusMap(SessionContext sessionContext) { HashMap statusMap = new HashMap(); sessionContext.remove("searchStatus"); sessionContext.put("searchStatus", statusMap); return statusMap; } /** * Set global status (effects all target databases) * @param sessionContext Active SessionContext * @param status One of ERROR | DONE * @param message Status text */ public static void setGlobalStatus(SessionContext sessionContext, String status, String message) { /* * Set global status */ sessionContext.put("STATUS", status); sessionContext.put("STATUS_MESSAGE", message); /* * Per-target status */ for (Iterator iterator = StatusUtils.getStatusMapEntrySetIterator(sessionContext); iterator.hasNext(); ) { Map.Entry entry = (Map.Entry) iterator.next(); HashMap targetMap = (HashMap) entry.getValue(); targetMap.put("STATUS", status); targetMap.put("STATUS_MESSAGE", message); } } /** * Set global error status (effects all target databases) * @param sessionContext Active SessionContext * @param message Expanded error text (null if none - produces "unknown") */ public static void setGlobalError(SessionContext sessionContext, String message) { String statusMessage = "*unknown*"; if (!StringUtils.isNull(message)) { statusMessage = message; } setGlobalStatus(sessionContext, "ERROR", statusMessage); } /** * Set global error status (effects all target databases) * @param sessionContext Active SessionContext * @param error Error number * @param message Expanded error text (null to omit expanded message) */ public static void setGlobalError(SessionContext sessionContext, String error, String message) { String statusMessage = "Error " + error; if (!StringUtils.isNull(message)) { statusMessage += ": " + message; } setGlobalStatus(sessionContext, "ERROR", statusMessage); } /** * Set all status value to "search complete" (effects all target databases) * @param sessionContext Active SessionContext */ public static void setAllComplete(SessionContext sessionContext) { setGlobalStatus(sessionContext, "DONE", "Search complete"); } /** * Update the hit count for this target (database) * @param sessionContext Active SessionContext * @param target Database name * @return Updated hit count */ public static int updateHits(SessionContext sessionContext, String target) { Map targetMap; String hits; int total, totalHits, estimate; if (StringUtils.isNull(target)) { throw new SearchException("No target database to update"); } if ((targetMap = getStatusMapForTarget(sessionContext, target)) == null) { throw new SearchException("No status map found for target database " + target); } _log.debug("Map for target " + target + ": " + targetMap); /* * Update total hits from this search source */ hits = (String) targetMap.get("HITS"); total = Integer.parseInt(hits) + 1; targetMap.put("HITS", String.valueOf(total)); totalHits = sessionContext.getInt("TOTAL_HITS") + 1; sessionContext.putInt("TOTAL_HITS", totalHits); /* * Have we collected all available results? */ estimate = Integer.parseInt((String) targetMap.get("ESTIMATE")); if (estimate == total) { int active = sessionContext.getInt("active"); /* * If this is the last active source, mark everything DONE */ if (--active <= 0) { setAllComplete(sessionContext); } else { /* * Just this source is finished */ targetMap.put("STATUS", "DONE"); targetMap.put("STATUS_MESSAGE", "Search complete"); } sessionContext.putInt("active", active); } return total; } /** * Fetch the estimated hits for a specified target (database) * @param sessionContext Active SessionContext * @param target Database name * @return Updated hit count */ public static int getEstimatedHits(SessionContext sessionContext, String target) { Map targetMap; String estimate; if ((targetMap = getStatusMapForTarget(sessionContext, target)) == null) { throw new SearchException("No status map for target database " + target); } estimate = (String) targetMap.get("ESTIMATE"); return Integer.parseInt(estimate); } /** * Fetch the number of remaining hits (all targets) * @param sessionContext Active SessionContext * @return Remaining hits */ public static int getAllRemainingHits(SessionContext sessionContext) { int estimate = sessionContext.getInt("TOTAL_ESTIMATE"); int hits = sessionContext.getInt("TOTAL_HITS"); int remaining = estimate - hits; return (remaining > 0) ? remaining : 0; } /** * Fetch the number of active (searching) targets * @param sessionContext Active SessionContext * @return Count of active targets */ public static int getActiveTargetCount(SessionContext sessionContext) { return sessionContext.getInt("active"); } /** * Is this an asynchronous search? * @param sessionContext Active SessionContext * @return true if so */ public static boolean isAsyncSearch(SessionContext sessionContext) { return "TRUE".equals(sessionContext.get("ASYNC_SEARCH")); } /** * Clear the asynchronous search flag * @param sessionContext Active SessionContext */ public static void clearAsyncSearch(SessionContext sessionContext) { sessionContext.put("ASYNC_SEARCH", "FALSE"); } /** * Indicate an asynchronous search * @param sessionContext Active SessionContext */ public static void setAsyncSearch(SessionContext sessionContext) { sessionContext.put("ASYNC_SEARCH", "TRUE"); } /** * Clear the asynchronous initialization flag * @param sessionContext Active SessionContext */ public static void clearAsyncInit(SessionContext sessionContext) { sessionContext.put("ASYNC_INIT", "FALSE"); } /** * Indicate asynchronous initialization in progress * @param sessionContext Active SessionContext */ public static void setAsyncInit(SessionContext sessionContext) { sessionContext.put("ASYNC_INIT", "TRUE"); } /** * Still performing asynchronous init? * @param sessionContext Active SessionContext * @return true if so */ public static boolean doingAsyncInit(SessionContext sessionContext) { return "TRUE".equals(sessionContext.get("ASYNC_INIT")); } }