try {
collection_ids = evaluateLandscape(landscape, jzkit_conf);
if ( ( collection_ids == null ) && ( collection_ids.size() == 0 ) ) {
throw new SearchException("Landscape Specification does not identify any collections");
}
SimpleAggregatingResultSet internal_result_set = new SimpleAggregatingResultSet(fts,rbs,rfs);
result = internal_result_set;
log.info("plan: "+model+" collections:"+collection_ids);
if ( ( collection_ids == null ) || ( collection_ids.size() == 0 ) || ( model == null ) )
throw new SearchException("Invalid parameters for search - No collections or no query model "+landscape);
Map queries_by_repository = new HashMap();
// We begin with an analysis of the collection_ids that we have been passed.
//
// We run through the collections and try to resolve each one into
// A Searchable resource (and possibly a collection name therin). For example, "LC/BOOKS"
// Might resolve into a search that needs to be sent to a Z3950 Searchable that will query
// the library of congress. The search will itself create a search task that has only one
// member in the collections vector, the "BOOKS" database.
for ( Iterator i = collection_ids.iterator(); i.hasNext(); ) {
String collection_dn = (String) i.next();
log.debug("Looking up collection "+collection_dn);
CollectionDescriptionDBO ci = jzkit_conf.lookupCollectionDescription(collection_dn);
if ( ci != null ) {
String search_service = null;
String profile = null;
String service_id = null;
SearchServiceDescriptionDBO ssd = ci.getSearchServiceDescription();
if ( ssd == null )
throw new RuntimeException("No SearchServiceDescription available for collection "+collection_dn);
search_service = ssd.getCode();
profile = ci.getProfile();
service_id = search_service+":"+profile;
// Figured out a repository to use?
if ( search_service != null ) {
log.debug("Lookup or Create searchable for "+service_id);
// N.B. In the real world, things are going to be more complext that this, with
// potentially many repositories supporting a single collection
Searchable s = (Searchable) all_active_searchable_objects.get(service_id);
// Look to see if we have an active connection to that repository
if ( s == null ) {
try {
log.debug("new searchable required");
// SearchServiceDescriptionDBO ssd = jzkit_conf.lookupSearchService(search_service);
s = ssd.newSearchable(); // Alternate version takes a User object as a param...
s.setApplicationContext(ctx);
all_active_searchable_objects.put(service_id, s);
}
catch (org.jzkit.search.provider.iface.SearchException se) {
se.printStackTrace();
}
}
// Are we already sending a search to this repository (And later, is the combination allowed?)
IRQuery subq = (IRQuery) queries_by_repository.get(service_id);
try {
// Is there a profile to try and apply for this repository?
if ( subq == null ) {
String profile_name = service_id.substring(service_id.lastIndexOf(':')+1,service_id.length());
QueryModel adapted_query_model = null;
if ( ( profile_name != null ) && ( !profile_name.equals("null") ) && ( profile_name.length() > 0 ) ) {
log.debug("Processing profile "+profile_name);
// This is where we call the query rewrite service to make a query conformant to the profile needed
// given the identified profile.
adapted_query_model = profile_service.makeConformant(model,
ssd.getValidAttrs(),
ssd.getServiceSpecificTranslations(),
profile_name);
log.debug("Adapted query : "+adapted_query_model);
}
else {
log.debug("Not adapting query");
adapted_query_model = model;
}
log.info("Query for repository "+service_id+" will be "+adapted_query_model);
// No, so create a new query that will be sent to that repository
subq = new IRQuery();
subq.query = adapted_query_model;
queries_by_repository.put(service_id,subq);
}
}
catch ( org.jzkit.search.util.Profile.ProfileServiceException pse ) {
log.warn("Profile Service Exception",pse);
throw new SearchException(pse.getMessage(),pse,pse.getErrorCode());
}
// We assume that a collection (with mirrors hosted by different repositories) might be known
// by different local names at different repositories. Here, we take the local name for a
// collection at a specific repository to use as a parameter in a query to that repository.
log.debug("Adding "+ci.getLocalId()+" to collection names to search at "+service_id);
subq.collections.add(ci.getLocalId());
}
else {
log.error("Unable to lookup repository for collection "+collection_dn+"... Skipping...");
throw new SearchException("Internal Error "+collection_dn, SearchException.INTERNAL_ERROR);
}
}
else {
log.error("Unable to locate collection information for name "+collection_dn+"... skipping...");
throw new SearchException("Unknown Collection "+collection_dn, SearchException.UNKOWN_COLLECTION);
}
}
log.debug("HSS Task contains "+queries_by_repository.size()+" child tasks");
// Phew, now cycle through each pair in queries_by_repository and send that query to the
// identified searchable object
for ( Iterator rep_ids = queries_by_repository.keySet().iterator(); rep_ids.hasNext(); ) {
// This will yield strings like "LC:bath"
String repos = (String) rep_ids.next();
IRQuery query_to_send_to_this_repository = (IRQuery) queries_by_repository.get(repos);
Searchable s = (Searchable) all_active_searchable_objects.get(repos);
// Create the subtask
IRResultSet subtask = s.evaluate(query_to_send_to_this_repository, null, null);
// So we get something sensible in status reports
subtask.setResultSetName(repos);
internal_result_set.addSource(subtask);
}
}
catch ( ConfigurationException ce) {
throw new SearchException(ce.toString());
}
finally {
log.info("Removed call to jzkit_conf.close()");
// jzkit_conf.close();
}