/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache 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.apache.org/licenses/LICENSE-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 com.esri.gpt.framework.search;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.esri.gpt.catalog.search.SearchCriteria;
import com.esri.gpt.catalog.search.SearchEngineCSW;
import com.esri.gpt.catalog.search.SearchException;
import com.esri.gpt.framework.geometry.Envelope;
import com.esri.gpt.framework.http.HttpClientRequest;
import com.esri.gpt.framework.request.Criteria;
import com.esri.gpt.framework.request.QueryResult;
import com.esri.gpt.framework.request.Record;
import com.esri.gpt.framework.request.Records;
import com.esri.gpt.framework.util.Val;
import com.esri.gpt.framework.xml.XsltTemplate;
import com.esri.gpt.server.csw.client.CswProfile;
import com.esri.gpt.server.csw.client.CswRecord;
import com.esri.gpt.server.csw.client.CswRuntimeException;
import com.esri.gpt.server.csw.client.CswSearchCriteria;
import com.esri.gpt.server.csw.client.InvalidOperationException;
import com.esri.gpt.server.csw.client.NullReferenceException;
import com.esri.gpt.server.csw.client.Utils;
/**
* Search profile.
* @param <C> criteria type
* @param <RD> record type
* @param <RS> collection of records type
* @param <QR> query result type
*/
public abstract class SearchXslProfile<C extends Criteria, RD extends Record,
RS extends Records<RD>, QR extends QueryResult<RS>> {
// class variables =============================================================
/** The class logger *. */
private static Logger LOG = Logger.getLogger(CswProfile.class
.getCanonicalName());
private final static String SCHEME_METADATA_DOCUMENT =
"urn:x-esri:specification:ServiceType:ArcIMS:Metadata:Document";
/**
* Type of search output format.
*/
public static enum FORMAT_SEARCH_TO_XSL {MINIMAL_LEGACY_CSWCLIENT,
FULL_NATIVE_GPTXML, DETAILED_GPT_CSW202};
private static final String XSL_PARAM_HITS_ONLY = "searchQueryDoHitsOnly";
// instance variables ==========================================================
/** The description. */
private String description;
/** The filter_extentsearch. */
private boolean filter_extentsearch;
/** The filter_livedatamap. */
private boolean filter_livedatamap;
/** indicates whether endpoint is harvestable */
private boolean harvestable = true;
/** The id. */
private String id;
/** The kvp. */
private String kvp;
/** The metadataxslt. */
private String metadataxslt;
/** The metadata xslt obj. */
private XsltTemplate metadataXsltObj;
/** The name. */
private String name;
/** The requestxslt. */
private String requestxslt;
/** The request xslt obj. */
private XsltTemplate requestXsltObj;
/** The responsexslt. */
private String responsexslt;
/** The response xslt obj. */
private XsltTemplate responseXsltObj;
/** XSLT factory*. */
private TransformerFactory factory;
/** The supports spatial query. */
private boolean supportsSpatialQuery;
/** The supports content type query. */
private boolean supportsContentTypeQuery;
/** The supports spatial boundary. */
private boolean supportsSpatialBoundary;
//TODO: Put this in the profile, find out which profiles accept this
private boolean supportsFullMetadataAtSearch;
/** The format request to xsl. */
private FORMAT_SEARCH_TO_XSL formatRequestToXsl;
// constructors ================================================================
/**
* Instantiates a new csw profile.
*/
public SearchXslProfile() {
}
/**
* The Constructor.
*
* @param sid
* the sid
* @param sname
* the sname
* @param sdescription
* the sdescription
*/
public SearchXslProfile(String sid, String sname, String sdescription) {
}
/**
* The Constructor.
*
* @param livedatamap
* the livedatamap
* @param extentsearch
* the extentsearch
* @param id
* the id
* @param name
* the name
* @param description
* the description
* @param kvp
* the kvp
* @param requestxslt
* the requestxslt
* @param responsexslt
* the responsexslt
* @param metadataxslt
* the metadataxslt
*/
public SearchXslProfile(String id, String name, String description, String kvp,
String requestxslt, String responsexslt, String metadataxslt,
boolean livedatamap, boolean extentsearch) {
this.id = id;
this.name = name;
this.description = description;
this.kvp = kvp;
this.requestxslt = requestxslt;
this.responsexslt = responsexslt;
this.metadataxslt = metadataxslt;
this.filter_livedatamap = livedatamap;
this.filter_extentsearch = extentsearch;
}
// properties ==================================================================
/**
* Checks if is supports full metadata at search.
*
* @return true, if is supports full metadata at search
*/
public boolean isSupportsFullMetadataAtSearch() {
return supportsFullMetadataAtSearch;
}
/**
* Checks if is harvestable.
*
* @return true, if is harvestable
*/
public boolean isHarvestable() {
return harvestable;
}
/**
* Sets the harvestable.
*
* @param harvestable the new harvestable
*/
public void setHarvestable(boolean harvestable) {
this.harvestable = harvestable;
}
/**
* Sets the supports full metadata at search.
*
* @param supportsFullMetadataAtSearch the new supports full metadata at search
*/
public void setSupportsFullMetadataAtSearch(boolean supportsFullMetadataAtSearch) {
this.supportsFullMetadataAtSearch = supportsFullMetadataAtSearch;
}
/**
* Checks if is supports spatial query.
*
* @return true, if is supports spatial query
*/
public boolean isSupportsSpatialQuery() {
return supportsSpatialQuery;
}
/**
* Sets the supports spatial query.
*
* @param supportsSpatialQuery
* the new supports spatial query
*/
public void setSupportsSpatialQuery(boolean supportsSpatialQuery) {
this.supportsSpatialQuery = supportsSpatialQuery;
}
/**
* Checks if is supports content type query.
*
* @return true, if is supports content type query
*/
public boolean isSupportsContentTypeQuery() {
return supportsContentTypeQuery;
}
/**
* Sets the supports content type query.
*
* @param supportsContentTypeQuery
* the new supports content type query
*/
public void setSupportsContentTypeQuery(boolean supportsContentTypeQuery) {
this.supportsContentTypeQuery = supportsContentTypeQuery;
}
/**
* Checks if is supports spatial boundary.
*
* @return true, if is supports spatial boundary
*/
public boolean isSupportsSpatialBoundary() {
return supportsSpatialBoundary;
}
/**
* Sets the supports spatial boundary.
*
* @param supportsSpatialBoundary
* the new supports spatial boundary
*/
public void setSupportsSpatialBoundary(boolean supportsSpatialBoundary) {
this.supportsSpatialBoundary = supportsSpatialBoundary;
}
// methods =====================================================================
/**
* Read get metadata by id response.
*
* @param response the response
* @param record the record
* @throws TransformerException the transformer exception
*/
public abstract void readGetMetadataByIDResponse(String response, RD record)
throws TransformerException ;
/**
* Read get records response. Puts SearchXslRecord into search
* Result param.
*
* @param responseString the response string
* @param searchResult the search results (will be filled with SearchXslRecords)
* @throws TransformerException the transformer exception
* @throws ParserConfigurationException the parser configuration exception
* @throws SAXException the sAX exception
* @throws IOException Signals that an I/O exception has occurred.
* @throws XPathExpressionException the x path expression exception
*/
@SuppressWarnings("unchecked")
public void readGetRecordsResponse(String responseString,
QueryResult<RS> searchResult) throws TransformerException,
ParserConfigurationException, SAXException, IOException,
XPathExpressionException {
LOG.finer("Transforming response to searchxslrecord native " +
"response. response = " + responseString);
String response = this.getResponsexsltobj().transform(responseString);
RS recordList = searchResult.getRecords();
LOG.finer("CSW Response to CSWClient Native = " + response);
String RECORD_TAG = "Record";
// create xml document object
// XML parser load doc specified by filename
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(response)));
checkForExceptions(doc);
// Get a list of nodes of which root is Profile tag
NodeList recordNodes = doc.getElementsByTagName(RECORD_TAG);
// create CswRecord and convert xml document node to each record
// Get the maximum number of records
XPath xpath = XPathFactory.newInstance().newXPath();
@SuppressWarnings("unused")
NodeList maxRecordNodes = doc.getElementsByTagName("SearchResults");
Node searchResultNode = doc.getDocumentElement();
NamedNodeMap attributes = searchResultNode.getAttributes();
Node node = attributes.getNamedItem("maxRecords");
if(node != null ) {
int maxNum = Utils.chkInt(node.getNodeValue(), Integer.MIN_VALUE);
if(maxNum >= 0) {
recordList.setMaximumQueryHits(maxNum);
searchResult.setMaxQueryHits(maxNum);
}
}
int nLen = recordNodes.getLength();
for (int i = 0; i < nLen; i++) {
LOG.finer("Going through a record node");
Node currNode = recordNodes.item(i);
CswRecord record = new CswRecord();
double maxX = 180;
double maxY = 90;
double minX = -180;
double minY = -90;
String lowerCorner = "";
String upperCorner = "";
record.setDefaultEnvelope(true);
NodeList nlChildren = currNode.getChildNodes();
int nChildren = nlChildren.getLength();
for (int nChild = 0; nChild < nChildren; nChild++) {
Node ndChild = nlChildren.item(nChild);
String nodeName = ndChild.getNodeName();
String nodeValue = ndChild.getTextContent();
if (nodeName.equals("ID")) {
record.setId(nodeValue);
} else if (nodeName.equals("Title")) {
record.setTitle(nodeValue);
} else if (nodeName.equals("Abstract")) {
record.setAbstractData(nodeValue);
} else if (nodeName.equals("ModifiedDate")) {
record.setModifiedDate(nodeValue);
} else if (nodeName.equals("MaxX")) {
maxX = Utils.chkDbl(nodeValue,maxX);
record.setDefaultEnvelope(
Utils.chkDbl(nodeValue,Integer.MIN_VALUE) == Integer.MIN_VALUE);
} else if (nodeName.equals("MaxY")) {
maxY = Utils.chkDbl(nodeValue,maxY);
} else if (nodeName.equals("MinX")) {
minX = Utils.chkDbl(nodeValue,minX);
} else if (nodeName.equals("MinY")) {
minY = Utils.chkDbl(nodeValue,minY);
} else if (nodeName.equals("LowerCorner")) {
lowerCorner = Utils.chkStr(nodeValue);
} else if (nodeName.equals("UpperCorner")) {
upperCorner = Utils.chkStr(nodeValue);
} else if (nodeName.equals("References")) {
record.setReference(nodeValue);
} else if (nodeName.equals("Types")) {
record.setTypes(nodeValue);
} else if (nodeName.equals("ModifiedDate")) {
record.setTypes(nodeValue);
}
}
if (!"".equals(lowerCorner)) {
String lowerCornerPts[] = lowerCorner.split(" ");
String upperCornerPts[] = upperCorner.split(" ");
if (lowerCornerPts != null && lowerCornerPts.length >= 2) {
minY = Utils.chkDbl(lowerCornerPts[1], minY);
minX = Utils.chkDbl(lowerCornerPts[0], minX);
record.setDefaultEnvelope(
Utils.chkDbl(lowerCornerPts[1], Integer.MIN_VALUE)
== Integer.MIN_VALUE);
}
if (upperCornerPts != null && upperCornerPts.length >= 2) {
maxY = Utils.chkDbl(upperCornerPts[1], maxY);
maxX = Utils.chkDbl(upperCornerPts[0], maxX);
}
}
record.setEnvelope(new Envelope(minX, minY, maxX, maxY));
// Attempting to see if this is a livedata record
record.setLiveDataOrMap(false);
Iterator<DcList.Value> iter = record.getTypes().iterator();
while (iter.hasNext()) {
DcList.Value value = iter.next();
if (value.getValue().equalsIgnoreCase("livedata")) {
record.setLiveDataOrMap(true);
}
}
// Links
NodeList nodeList = ((Element)currNode).getElementsByTagName("Link");
for(int j = 0; j < nodeList.getLength(); j++) {
Node linkNode = nodeList.item(j);
NamedNodeMap attrLinkNode = linkNode.getAttributes();
String gptLinkTag = null;
if(attrLinkNode.getNamedItem("gptLinkTag")!= null) {
gptLinkTag = attrLinkNode.getNamedItem("gptLinkTag").getNodeValue();
}
String show = null;
if(attrLinkNode.getNamedItem("show")!= null) {
show = attrLinkNode.getNamedItem("show").getNodeValue();
}
String url = null;
if(linkNode!= null) {
url = linkNode.getTextContent();
}
String label = null;
if(attrLinkNode.getNamedItem("label")!= null) {
label = attrLinkNode.getNamedItem("label").getNodeValue();
}
if(label != null && !"".equals(label)) {
record.getLinks().addCustomLink(label, url);
} else if(gptLinkTag != null && !"".equals(gptLinkTag)){
record.getLinks().addDefaultLinkOptions(gptLinkTag,
Val.chkBool(show, true));
} else {
continue;
}
}
recordList.add((RD)record);
}
}
/**
* Support content type query.
*
* @return true, if successful
*/
public boolean SupportContentTypeQuery() {
return isSupportsContentTypeQuery();
}
public boolean SupportSpatialBoundary() {
return isSupportsSpatialBoundary();
}
/**
* Support spatial query.
*
* @return true, if successful
*/
public boolean SupportSpatialQuery() {
return isSupportsSpatialQuery();
}
public String getDescription() {
return description;
}
/**
* Sets the description.
*
* @param description
* the new description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Checks if is filter_extentsearch.
*
* @return true, if is filter_extentsearch
*/
public boolean isFilter_extentsearch() {
return filter_extentsearch;
}
/**
* Sets the filter_extentsearch.
*
* @param filter_extentsearch
* the new filter_extentsearch
*/
public void setFilter_extentsearch(boolean filter_extentsearch) {
this.filter_extentsearch = filter_extentsearch;
}
/**
* Checks if is filter_livedatamap.
*
* @return true, if is filter_livedatamap
*/
public boolean isFilter_livedatamap() {
return filter_livedatamap;
}
/**
* Sets the filter_livedatamap.
*
* @param filter_livedatamap
* the new filter_livedatamap
*/
public void setFilter_livedatamap(boolean filter_livedatamap) {
this.filter_livedatamap = filter_livedatamap;
}
/**
* Gets the id.
*
* @return the id
*/
public String getId() {
return id;
}
/**
* Sets the id.
*
* @param id
* the new id
*/
public void setId(String id) {
this.id = id;
}
/**
* Gets the kvp.
*
* @return the kvp
*/
public String getKvp() {
return kvp;
}
/**
* Sets the kvp.
*
* @param kvp
* the new kvp
*/
public void setKvp(String kvp) {
this.kvp = kvp;
}
/**
* Gets the metadataxslt.
*
* @return the metadataxslt
*/
public String getMetadataxslt() {
return metadataxslt;
}
/**
* Sets the metadataxslt.
*
* @param metadataxslt
* the new metadataxslt
*/
public void setMetadataxslt(String metadataxslt) {
this.metadataxslt = metadataxslt;
}
/**
* Gets the metadataxsltobj.
*
* @return the metadataxsltobj
*/
public XsltTemplate getMetadataxsltobj() {
return metadataXsltObj;
}
/**
* Sets the metadataxsltobj.
*
* @param metadataxsltobj
* the new metadataxsltobj
*/
public void setMetadataxsltobj(XsltTemplate metadataxsltobj) {
this.metadataXsltObj = metadataxsltobj;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Sets the name.
*
* @param name
* the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the requestxslt.
*
* @return the requestxslt
*/
public String getRequestxslt() {
return requestxslt;
}
/**
* Sets the requestxslt.
*
* @param requestxslt
* the new requestxslt
*/
public void setRequestxslt(String requestxslt) {
this.requestxslt = requestxslt;
}
/**
* Gets the requestxsltobj.
*
* @return the requestxsltobj
* @throws TransformerConfigurationException on xslt template creation error
* @throws IOException Signals that an I/O exception has occurred.
*/
public XsltTemplate getRequestxsltobj()
throws TransformerConfigurationException, IOException {
if (requestXsltObj == null) {
String file = this.getRequestxslt();
try {
this.setRequestxsltobj(XsltTemplate.makeFromResourcePath(file));
} catch (IOException e) {
try {
this.setRequestxsltobj(XsltTemplate.makeFromResourcePath(file));
} catch (IOException f) {
throw f;
}
}
}
return this.requestXsltObj;
}
/**
* Sets the requestxsltobj.
*
* @param requestxsltobj
* the new requestxsltobj
*/
public void setRequestxsltobj(XsltTemplate requestxsltobj) {
this.requestXsltObj = requestxsltobj;
}
/**
* Gets the responsexslt.
*
* @return the responsexslt
*/
public String getResponsexslt() {
return responsexslt;
}
/**
* Sets the response XSLT.
*
* @param responsexslt
* the new response XSLT
*/
public void setResponsexslt(String responsexslt) {
this.responsexslt = responsexslt;
}
/**
* Gets the response XSLT object.
*
* @return the response XSLT object
* @throws CSWException
*/
public XsltTemplate getResponsexsltobj() throws
TransformerConfigurationException, IOException {
if (responseXsltObj == null) {
String file = this.getResponsexslt();
try {
this.setResponsexsltobj(XsltTemplate.makeFromResourcePath(file));
} catch (IOException e) {
try {
this.setResponsexsltobj(XsltTemplate.makeFromResourcePath(file));
} catch (IOException f) {
throw f;
}
}
}
return responseXsltObj;
}
/**
* Gets the response XSLT object.
*
* @return the response XSLT object
* @throws CSWException
*/
public XsltTemplate getMetadataXsltObj() throws TransformerConfigurationException {
if (this.metadataXsltObj == null) {
String file = this.getMetadataxslt();
//InputStream inStream = this.getClass().getResourceAsStream(file);
//if (inStream == null) {
// inStream = this.getClass().getResourceAsStream("/" + file);
// file = "/" + file;
//}
//inStream = null;
try {
this.setMetadataxsltobj(XsltTemplate.makeFromResourcePath(file));
} catch (TransformerConfigurationException e) {
LOG.severe("CSW Client: Could not get xslt template " + file);
throw e;
} catch (IOException e) {
LOG.severe("CSW Client: Could not get xslt template " + file);
throw new TransformerConfigurationException("CSW Client: Could not get xslt template " + file,e);
}
}
return this.metadataXsltObj;
}
/**
* Sets the response XSLT Object.
*
* @param responsexsltobj
* the new response XSLT Object
*/
public void setResponsexsltobj(XsltTemplate responsexsltobj) {
this.responseXsltObj = responsexsltobj;
}
/**
* Gets the transformer factory.
*
* @return the factory
*/
public TransformerFactory getFactory() {
if (factory == null) {
return TransformerFactory.newInstance();
}
return factory;
}
/**
* Transformer convinient method.
*
* @param xml the xml
* @param transformer the transformer
* @return the string
* @throws TransformerException the transformer exception
*/
protected String transform(String xml, Transformer transformer)
throws TransformerException {
StreamSource source = new StreamSource(new StringReader(xml));
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
transformer.transform(source,result);
return result.getWriter().toString();
}
/**
* Check response if there is any exception produced from the server.
*
* @param doc the doc
* @exception CswRuntimeException if exception found in response
*/
private void checkForExceptions(Document doc) {
String exceptionTag = "exception";
StringBuffer exception = null;
NodeList recordNodes = doc.getElementsByTagName(exceptionTag);
if(recordNodes == null || recordNodes.getLength() < 1){
return;
}
exception = new StringBuffer();
XPath xpath = XPathFactory.newInstance().newXPath();
for (int i = 0; i < recordNodes.getLength(); i++) {
try {
exception.append(
Utils.chkStr(xpath.evaluate("exceptionText", recordNodes.item(i))));
} catch (XPathExpressionException e) {
exception.append(e.getMessage());
LOG.log(Level.WARNING, "Problem while parsing execption recieved", e);
e.printStackTrace();
}
}
if(exception != null) {
LOG.severe("Search returned exception. Creating exception report "
+ exception.toString());
throw new CswRuntimeException(exception.toString());
}
}
/**
* Read intermidiate get record by id. GetRecords does only uses the getMetadata
* xslt to get an intermidiate reference to the actual xml
*
* @param response the response
* @param record the record
* @throws TransformerConfigurationException the transformer configuration exception
* @throws TransformerException the transformer exception
*/
protected void readIntermidiateGetRecordById(String response,
SearchXslRecord record)
throws TransformerConfigurationException, TransformerException
{
String metadataxslt = this.getMetadataxslt();
if (metadataxslt == null || metadataxslt.equals("")) {
record.setFullMetadata(Utils.chkStr(response));
} else {
LOG.finer("Transforming GetRecordByID intermidiate xml to GetRecordById " +
"Native");
String result = this.getMetadataXsltObj().transform(Val.chkStr(response));
String xmlUrl = null;
String dctReferences = result;
LOG.finer("Native GetRecordBYID from transform = " + dctReferences);
DcList lstDctReferences = new DcList(dctReferences);
Iterator<DcList.Value> iter = lstDctReferences.iterator();
while(iter.hasNext()) {
DcList.Value value = iter.next();
if(value.getValue().toLowerCase().endsWith(".xml")
|| value.getScheme().equals(SCHEME_METADATA_DOCUMENT)) {
xmlUrl = value.getValue();
}
}
record.setReferences(lstDctReferences);
LOG.finer("URL to view full metadata document found = " + xmlUrl);
record.setMetadataResourceURL(xmlUrl);
}
}
/**
* Gets the record by id.
*
* <ul>
* <li>Url constructed</li>
* <li>XML is gotten from url</li>
* <li>XML put through the getRecordsResponse xsl to make a cswRecord</li>
* <li>if metadataxsl exists, use it to get the use responstr an intermidiate
* response and get the associated reference</li>
* <li>Fills the cswrecord with the responseStr and later with the intermidiate
* xml reference response if there is one
* </li>
* <ul>
*
*
*
* @param responseStr the respons str
* @param uuid the uuid
* @param requestUrl the request url
* @return the record by id
* @throws IOException Signals that an I/O exception has occurred.
* @throws TransformerException the transformer exception
* @throws NullReferenceException the null reference exception
* @throws InvalidOperationException the invalid operation exception
*/
@SuppressWarnings("unchecked")
public SearchXslRecord getRecordById(String responseStr, String uuid,
String requestUrl)
throws IOException, TransformerException,
NullReferenceException, InvalidOperationException, SearchException {
SearchXslRecord record = null;
responseStr = Val.chkStr(responseStr);
try {
LOG.finer("GetRecordById: Making csw record object using g" +
"etRecordsResponse operation");
// making cswObject by going through getrecord response xslt
Records<SearchXslRecord> recordList = new Records<SearchXslRecord>();
QueryResult<RS> results = new QueryResult<RS>();
this.readGetRecordsResponse(responseStr, results);
Iterator<SearchXslRecord> iter = recordList.iterator();
if(iter.hasNext()) {
record = iter.next();
} else {
LOG.log(Level.WARNING,
"Could not get csw metadata of metadata document");
}
} catch (ParserConfigurationException e) {
LOG.log(Level.INFO,
"Could not get csw metadata of metadata document (maybe this csw does "
+ "not have csw metadata on getRecord by id. " + e.getMessage());
} catch (SAXException e) {
LOG.log(Level.INFO,
"Could not get csw metadata of metadata document (maybe this csw does "
+ "not have csw metadata on getRecord by id. " + e.getMessage());
} catch (XPathExpressionException e) {
LOG.log(Level.INFO,
"Could not get csw metadata of metadata document (maybe this csw does "
+ "not have csw metadata on getRecord by id. " + e.getMessage());
}
record.setId(uuid);
LOG.finer("GetRecordByID: Transforming intermidiate xml to populate xml " +
"into csw Record");
this.readIntermidiateGetRecordById(responseStr, record);
if (record == null) {
throw new NullReferenceException("Record not populated.");
}
// check if full metadata or resourceURL has been returned
boolean hasFullMetadata = !(record.getFullMetadata() == null || record
.getFullMetadata() == "");
boolean hasResourceUrl = !(record.getMetadataResourceURL() == null || record
.getMetadataResourceURL() == ""); // TODO: CHECK THE COMPARISONS!
if(!hasResourceUrl && requestUrl != null ) {
record.setMetadataResourceURL(requestUrl);
hasResourceUrl = true;
}
if (!hasFullMetadata && !hasResourceUrl) {
throw new SearchException("Neither full metadata nor metadata"
+ " resource URL was found for the CSW record.");
} else if (hasResourceUrl) {
// need to load metadata from resource URL
URL url = null;
Exception ex = null;
try {
url = new URL(record.getMetadataResourceURL());
HttpClientRequest clientRequest = HttpClientRequest.newRequest(
HttpClientRequest.MethodName.GET, url.toExternalForm());
// clientRequest.setConnectionTimeOut(getConnectionTimeout());
//clientRequest.setResponseTimeOut(getResponseTimeout());
clientRequest.execute();
String response = clientRequest.readResponseAsCharacters();
LOG.finer("Response from get Metadata url = " + url.toExternalForm()
+"\n response = \n"+ response);
record.setFullMetadata(response);
} catch (MalformedURLException e) {
ex = e;
} catch (IOException e) {
ex = e;
}
if(ex != null) {
throw new SearchException("Could not get metadata id url = " + url, ex);
}
}
return record;
}
/**
* Gets the format request to xsl.
*
* @return the format request to xsl (never null, default MINIMAL_LEGACY)
*/
public FORMAT_SEARCH_TO_XSL getFormatRequestToXsl() {
if(this.formatRequestToXsl == null) {
this.formatRequestToXsl = FORMAT_SEARCH_TO_XSL.MINIMAL_LEGACY_CSWCLIENT;
}
return formatRequestToXsl;
}
/**
* Sets the format request to xsl.
*
* @param formatRequestToXsl the new format request to xsl
*/
public void setFormatRequestToXsl(FORMAT_SEARCH_TO_XSL formatRequestToXsl) {
this.formatRequestToXsl = formatRequestToXsl;
}
/**
* Generate get records request.
*
* @param criteria the criteria
* @param xslParams the xsl params
* @param hitsOnly Indicates whether this is a hits only request
* @return the string
* @throws TransformerException the transformer exception
* @throws ParserConfigurationException the parser configuration exception
* @throws SAXException the sAX exception
* @throws IOException Signals that an I/O exception has occurred.
* @throws SearchException the search exception
* @throws XPathExpressionException the x path expression exception
*/
public String generateGetRecordsRequest(SearchCriteria criteria,
Map<String, String> xslParams, boolean hitsOnly)
throws TransformerException, ParserConfigurationException, SAXException,
IOException, SearchException, XPathExpressionException {
if(xslParams == null) {
xslParams = new HashMap<String, String>();
}
xslParams.put(XSL_PARAM_HITS_ONLY, String.valueOf(hitsOnly));
String internalRequestXml = null;
FORMAT_SEARCH_TO_XSL formatRequestToXsl = this.getFormatRequestToXsl();
if (formatRequestToXsl == FORMAT_SEARCH_TO_XSL.FULL_NATIVE_GPTXML) {
internalRequestXml = criteria.toDom2();
} else if (formatRequestToXsl == FORMAT_SEARCH_TO_XSL.DETAILED_GPT_CSW202) {
internalRequestXml = SearchEngineCSW.transformGptToCswRequest(criteria,
SearchEngineCSW.SEARCH_OPERATION.doSearch);
} else {
// Default use the MINIMAL XML
CswSearchCriteria cswSearchCriteria = SearchEngineCSW
.marshallGptToCswClientCriteria2(criteria);
internalRequestXml = cswSearchCriteria.toXml();
}
LOG.finer("Generated internal XML requst input to request xsl "
+ internalRequestXml);
internalRequestXml = getRequestxsltobj().transform(internalRequestXml,
xslParams);
LOG.finer("Transform output from Request xsl " + internalRequestXml);
return internalRequestXml;
}
}