aslcore/src/org/gcube/application/framework/core/cache/factories/CollectionCacheEntryFactory...

402 lines
16 KiB
Java

package org.gcube.application.framework.core.cache.factories;
import org.apache.axis.message.addressing.EndpointReferenceType;
import org.xml.sax.InputSource;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.xpath.XPathAPI;
import org.gcube.application.framework.core.cache.CachesManager;
import org.gcube.application.framework.core.commons.model.CollectionInfo;
import org.gcube.application.framework.core.commons.model.IndexInfo;
import org.gcube.application.framework.core.util.CacheEntryConstants;
import org.gcube.application.framework.core.util.QueryString;
import org.gcube.application.framework.core.util.SessionConstants;
import org.gcube.application.framework.core.vremanagement.model.ISGenericResource;
import org.gcube.common.core.contexts.GHNContext;
import org.gcube.common.core.informationsystem.client.ISClient;
import org.gcube.common.core.informationsystem.client.RPDocument;
import org.gcube.common.core.informationsystem.client.queries.WSResourceQuery;
import org.gcube.common.core.scope.GCUBEScope;
import org.gcube.common.core.utils.logging.GCUBELog;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
/**
* This cache serves the available searchable collections for each VRE
* @author Valia Tsagkalidou (NKUA)
*
*/
public class CollectionCacheEntryFactory implements CacheEntryFactory {
static ISClient client = null;
/** Object logger. */
protected final GCUBELog logger = new GCUBELog(this);
public CollectionCacheEntryFactory() {
super();
//Initialize static variable
if(client == null)
{
try {
client = GHNContext.getImplementation(ISClient.class);
} catch (Exception e) {
// TODO Auto-generated catch block
logger.error("Failed to get implemetation of ISClient", e);
}
}
}
/**
* Document factory instance
*/
public static final DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
/**
* whether geospatial tab should be available in Search portlet or not
*/
protected boolean geospatial;
//TODO: find a way to return also the geospatial tab boolean variable
/**
* @param key a String representing the VRE name.
* @return List<CollectionInfo>[] an array of Lists containing CollectionInfo objects. Each List contains a Collection group. The First element of the list is the CollectionInfo containing info for the Group (name, description etc). The rest of the objects in the list are the actual collections.
*/
public Object createEntry(Object key) throws Exception {
System.out.println("GenericResource: inside collection cache entry factory create entry");
List<CollectionInfo> collections;
String searchConfig = (String) CachesManager.getInstance().getSearchConfigCache().get(key).getValue();
System.out.println("The search configuration returned from the search master (dynamic) is: " + searchConfig);
if(searchConfig == null || searchConfig.equals("")) {
System.out.println("The searchConfigCache returned null for the search configuration!!!!");
return null;
}
collections = parseSearchConfig(searchConfig);
System.out.println("GenericResource - Inside collection cache entry factory calling retrieve static configuration");
return retrieveStaticConfiguration(key.toString(), collections);
}
/**
* @param searchConfig the search configuration as it is returned from the SearchMaster
* @return a list of CollectionInfo, which represents the currently available collections
*/
protected List<CollectionInfo> parseSearchConfig(String searchConfig)
{
try {
// Interpreting the dynamic configuration (the one retrieved from Search Master)
logger.debug(searchConfig);
InputSource colls_in = new InputSource(new StringReader(searchConfig));
Document colls_doc;
colls_doc = dfactory.newDocumentBuilder().parse(colls_in);
NodeList colls_res;
//Getting the info of all the available content collections:
colls_res = XPathAPI.selectNodeList(colls_doc, "/SearchConfig/collections/collection[TYPE='DATA']");
int n = colls_res.getLength(),i;
List<CollectionInfo> collections = new ArrayList<CollectionInfo>();
for (i = 0; i < n; i++)
{//For each content collection:
// Storing the information in local variables.
CollectionInfo colInfo = new CollectionInfo();
String val;
String id = colls_res.item(i).getAttributes().getNamedItem("id").getNodeValue();
val = id;
String colName = colls_res.item(i).getAttributes().getNamedItem("name").getNodeValue();
colInfo.setId(id);
colInfo.setName(colName);
NodeList contentRes = XPathAPI.selectNodeList(colls_doc, "/SearchConfig/collections/collection[@id='"+id+"']/ASSOCIATEDWITH");
int attrNo = contentRes.getLength();
for(int j=0; j<attrNo; j++)
{//For each corresponding metadata collection:
try
{
String metadataID = contentRes.item(j).getFirstChild().getNodeValue();
String language = null, schema = null;
// get the language of this collection:
NodeList metaRes = XPathAPI.selectNodeList(colls_doc, "/SearchConfig/collections/collection[@id='"+metadataID+"']/"+"LANGUAGE");
if(metaRes == null)
continue;
language = metaRes.item(0).getFirstChild().getNodeValue();
// get the schema of this collection:
metaRes = XPathAPI.selectNodeList(colls_doc, "/SearchConfig/collections/collection[@id='"+metadataID+"']/"+"SCHEMA");
if(metaRes != null)
schema = metaRes.item(0).getFirstChild().getNodeValue();
// get the available indices for this collection:
metaRes = XPathAPI.selectNodeList(colls_doc, "/SearchConfig/collections/collection[@id='"+metadataID+"']/"+"INDEX");
IndexInfo indexInformation = new IndexInfo();
if(metaRes != null)
{
logger.debug("collection: " + colInfo.getName() + " schema = " + metaRes);
int k, total = metaRes.getLength();
for(k=0; k<total; k++)
{//For each Index:
logger.debug(" -- " + metaRes.item(k).getFirstChild().getNodeValue());
if(metaRes.item(k).getFirstChild().getNodeValue().equals("FTS"))
{
indexInformation.setFts(true);
logger.debug("id name : "+val);
}
else if(metaRes.item(k).getFirstChild().getNodeValue().equals("GEO"))
{
indexInformation.setGeospatial(true);
logger.debug("id name : "+val);
}
else if(metaRes.item(k).getFirstChild().getNodeValue().equals("FEATURE"))
{
//This is probably deprecated. It refers to feature indices which are no longer available on the infrastructure.
indexInformation.setSimilarity(true);
logger.debug("id name : "+val);
}
}
}
colInfo.setMetadataCollection(schema, metadataID, language, indexInformation);
}
catch (Exception e) {
logger.error("", e);
}
}//End of for each metadata collection.
collections.add(colInfo);
}//End of for each content collection.
return collections;
} catch (Exception e1) {
logger.error("", e1);
}
return null;
}
/**
* Retrieves the static configuration for the collections from the IS. This information is stored in a generic resource published on IS.
* @param vre the vre for which it will retrieve the static configuration (generic resource in IS)
* @param collections the collection derived from the dynamic configuration (SearchMaster configuration)
* @return an array of Lists containing CollectionInfo objects. Each List contains a Collection group. The First element of the list is the CollectionInfo containing info for the Group (name, description etc). The rest of the objects in the list are the actual collections.
* @throws Exception an Exception occurred during the procedure
*/
protected List<CollectionInfo>[] retrieveStaticConfiguration(String vre, List<CollectionInfo> collections) throws Exception
{
// Reading the static configuration file and initializing the parameters
System.out.println("About to retrieve the static configuration");
List<CollectionInfo>[] colHierarchy;
QueryString query = new QueryString();
query.put(CacheEntryConstants.vre, vre);
query.put(CacheEntryConstants.name, SessionConstants.ScenarioSchemaInfo);
//Retrieving the generic resource:
List<ISGenericResource> scenarioSchemaInfo = (List<ISGenericResource>) CachesManager.getInstance().getGenericResourceCache().get(query).getValue();
if(scenarioSchemaInfo == null || scenarioSchemaInfo.size() == 0)
{
System.out.println("The scenarioSchemaInfo is null");
colHierarchy = new ArrayList[0];
return colHierarchy;
}
System.out.println("Printing the static configuration");
logger.debug(scenarioSchemaInfo.get(0).getBody());
InputSource in = new InputSource(new StringReader(scenarioSchemaInfo.get(0).getBody()));
Document doc = dfactory.newDocumentBuilder().parse(in);
retrieveCollections(doc, collections);
colHierarchy = retrieveCollectionHierarchy(vre, doc, collections);
return colHierarchy;
}
/**
* Retrieves the collections by joining information from static and dynamic configuration.
* @param doc document which holds the collections
* @param collections the list containing the collections
*/
protected void retrieveCollections(Document doc, List<CollectionInfo> collections)
{
int i,n;
List<CollectionInfo> availableCollections = new ArrayList<CollectionInfo>();
// Reading the collections and storing them in a list only if they are currently available.
NodeList res = doc.getElementsByTagName("collection");
n = res.getLength();
System.out.println("CollectionCacheEntryFactory: The number of collections is: " + n);
for (i = 0; i < n; i++)
{
String val = res.item(i).getAttributes().getNamedItem("name").getNodeValue();
CollectionInfo colInfo = null;
colInfo = getCollectionInfo(val, collections);
if (colInfo == null)
continue;// This collection is not currently available.
val = res.item(i).getAttributes().getNamedItem("description").getNodeValue();
colInfo.setDescription(val);
val = res.item(i).getAttributes().getNamedItem("reference").getNodeValue();
colInfo.setReference(val);
val = res.item(i).getAttributes().getNamedItem("shortname").getNodeValue();
colInfo.setShortName(val);
availableCollections.add(colInfo);
}
//Copying available collections to collections
collections.clear();
for(CollectionInfo col : availableCollections)
{
collections.add(col);
}
//Adding the collection groups to the available collections
res = doc.getElementsByTagName("collections");
n = res.getLength();
for (i = 0; i < n; i++)
{
CollectionInfo colInfo = new CollectionInfo();
colInfo.setId("collection_id_"+i);
String val;
try{
val = res.item(i).getAttributes().getNamedItem("name").getNodeValue();
colInfo.setName(val);
}
catch(Exception e){}
try{
val = res.item(i).getAttributes().getNamedItem("description").getNodeValue();
colInfo.setDescription(val);
}
catch(Exception e){}
try{
val = res.item(i).getAttributes().getNamedItem("reference").getNodeValue();
colInfo.setReference(val);
}
catch(Exception e){}
try{
val = res.item(i).getAttributes().getNamedItem("shortname").getNodeValue();
colInfo.setShortName(val);
}
catch(Exception e){}
collections.add(colInfo);
}
logger.debug("***Number of collections:" + collections.size());
}
/**
* Retrieves the hierarchical structure of the available collections. Joins the static and the dynamic search configuration and produces a hierarchical structure containing information about each collection.
* @param VREname the VRE name of the active VRE
* @param doc document which holds the collections
* @param collections the available collections
* @return an array of Lists containing CollectionInfo objects. Each List contains a Collection group. The First element of the list is the CollectionInfo containing info for the Group (name, description etc). The rest of the objects in the list are the actual collections.
* @throws Exception an Exception occurred during processing
*/
protected List<CollectionInfo>[] retrieveCollectionHierarchy(String VREname, Document doc, List<CollectionInfo> collections) throws Exception {
// Retrieving the tree structure of the collection hierarchy
NodeList res = XPathAPI.selectNodeList(doc, "//DL");
Node geo = res.item(0).getAttributes().getNamedItem("geospatial");
if(geo != null && geo.getNodeValue().equals("true"))
geospatial = true;
res = XPathAPI.selectNodeList(doc, "//collections");
int n = res.getLength();
logger.debug("***** number of collection groups:" + n + "*******");
List<CollectionInfo>[] colHierachy = new List[n];
for (int i = 0; i < n; i++)
{//for each collection group:
String val = res.item(i).getAttributes().getNamedItem("name").getNodeValue();
NodeList res2 = XPathAPI.selectNodeList(doc, "//collections[@name=\"" + val + "\"]/collection");
colHierachy[i] = new ArrayList<CollectionInfo>();
CollectionInfo colInfo = getCollectionInfo(val, collections);
if(colInfo != null)
{
colHierachy[i].add(colInfo); // Collection Group Name
for (int j = 0; j < res2.getLength(); j++)
{//for each collection belonging to that group, it stores its name...
colInfo = getCollectionInfo(res2.item(j).getAttributes().getNamedItem("name").getNodeValue(), collections);
if(colInfo != null)
{
findBrowseFields(colInfo, GCUBEScope.getScope(VREname));
colHierachy[i].add(colInfo);
}
}
}
logger.debug("***collection group " + i + " contains " + (colHierachy[i].size()-1) + " collections***");
}
return colHierachy;
}
/**
* Finds the Browseable fields for the given collection
* @param colInfo the CollectionInfo containing info about the current collection
* @param scope the GCUBEScope of the active VRE
*/
private void findBrowseFields(CollectionInfo colInfo, GCUBEScope scope) {
try {
getWSResourceForForward(colInfo, scope);
} catch(Exception e){
e.printStackTrace();
}
}
/**
* Finds the collection info object of the collection with the given name.
* @param collectionName the name of the collection
* @param collections a list containing all the collections
* @return the CollectionInfo of the collection with the corresponding name
*/
protected CollectionInfo getCollectionInfo(String collectionName, List<CollectionInfo> collections)
{
CollectionInfo colInfo = null;
int i, n = collections.size();
for(i=0; i< n; i++)
{
logger.debug("*******" + collections.get(i).getName() + " vs. " + collectionName);
if(collections.get(i).getName().equals(collectionName))
{
colInfo = collections.get(i);
logger.debug("***collection found****");
break;
}
}
return colInfo;
}
/**
* Updates the information regarding the available forward indices for the given content collection
* @param colInfo the CollectionInfo that represents the content collection
* @param scope the scope on which this collection belongs to (currently active VRE)
* @throws Exception an error occurred during execution
*/
private void getWSResourceForForward(CollectionInfo colInfo, GCUBEScope scope) throws Exception {
//Building the query to IS
String filter = "$result/child::*[local-name()='ServiceClass']/string() eq 'Index'";
filter += " and $result/child::*[local-name()='ServiceName']/string() eq 'ForwardIndexLookup'";
filter += " and $result/child::*[local-name()='CollectionID']/string() eq '" + colInfo.getId() + "'";
HashMap<String, List<EndpointReferenceType>> results = colInfo.getForward();
ISClient client = GHNContext.getImplementation(ISClient.class);
WSResourceQuery gquery = client.getQuery(WSResourceQuery.class);
gquery.addGenericCondition(filter);
//For each result:
for(RPDocument d : client.execute(gquery, scope)){
String browseField = d.evaluate("//KeyName/text()").get(0);
List<EndpointReferenceType> ret = results.get(browseField);
if(ret == null)
{
ret = new LinkedList<EndpointReferenceType>();
}
ret.add(d.getEndpoint());
results.put(browseField, ret);
}
}
}