/* 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.server.csw.client;
import java.io.*;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;
import org.xml.sax.SAXException;
/**
* CswSearchRequest class.
*
* CswSearchRequest class is used to submit CSW search queries and to
* return CSW search results. Before submiting a request, you need to specify a
* catalog and provide search criteria.
*/
public class CswSearchRequest {
private static final Logger LOG =
Logger.getLogger(CswSearchRequest.class.getCanonicalName());
private CswCatalog catalog;
private CswSearchCriteria criteria;
private CswClient cswClient;
private CswSearchResponse response;
public CswSearchRequest() {
this(null, null);
}
public CswSearchRequest(CswCatalog catalog, String searchText) {
this.catalog = catalog;
// Initialize the neccessary objects
// create search criteria
this.criteria = new CswSearchCriteria();
this.criteria.setSearchText(searchText);
// create csw client
this.cswClient = new CswClient();
this.response = new CswSearchResponse();
}
/**
* Accessor methods
*/
public CswCatalog getCatalog() {
return this.catalog;
}
public void setCatalog(CswCatalog catalog) {
this.catalog = catalog;
this.cswClient.setBatchHttpClient(catalog.getBatchHttpClient());
}
public CswSearchCriteria getCriteria() {
return this.criteria;
}
public void setCriteria(CswSearchCriteria criteria) {
this.criteria = criteria;
}
public CswClient getCswClient() {
return this.cswClient;
}
public void setCswClient(CswClient cswClient) {
this.cswClient = cswClient;
}
public CswSearchResponse getCswSearchResponse() {
return this.response;
}
public void setCswSearchResponse(CswSearchResponse response) {
this.response = response;
}
/**
* Retrieve metadata from CSW service by its ID
*
* @param DocID Metadata document ID
*/
public void getMetadataByID(String DocID) throws NullReferenceException,
IOException, InvalidOperationException, TransformerException {
if (DocID == null || DocID.length() == 0) {
throw new NullReferenceException("No DocID specified");
}
if (catalog == null) {
throw new NullReferenceException("Catalog not specified.");
}
if (catalog.getCapabilities() == null) {
throw new NullReferenceException("Catalog capabilities not initialized.");
}
if (catalog.getProfile() == null) {
throw new NullReferenceException("Catalog profile not specified.");
}
if (catalog.getCapabilities().get_getRecordByIDGetURL() == null
|| catalog.getCapabilities().get_getRecordByIDGetURL().length() == 0) {
throw new NullReferenceException(
"GetRecordByID URL not specified for the catalog capabilities.");
}
CswProfile profile = catalog.getProfile();
// generate request url
String getRecordByIDBaseUrl = catalog.getCapabilities()
.get_getRecordByIDGetURL();
CswRecord record = this.getRecordById(getRecordByIDBaseUrl, DocID, profile);
// add record to the response
CswRecords records = new CswRecords();
if (record != null) {
records.add(record);
}
response.setRecords(records);
}
/**
* Gets the record by id.
*
* @param requestURL the request URL (CSW service url)
* @param DocID the doc ID (GUID or UUID)
* @param profile the profile
*
* @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 CswRecord getRecordById(String requestURL, String DocID,
CswProfile profile) throws IOException, TransformerException,
NullReferenceException, InvalidOperationException {
String requestUrl = profile.generateCSWGetMetadataByIDRequestURL(requestURL,
DocID);
if (cswClient == null) {
cswClient = new CswClient();
cswClient.setBatchHttpClient(catalog.getBatchHttpClient());
}
BufferedInputStream bStream = null;
InputStream istIntermidiateDoc = null;
InputStream istRealDoc = null;
CswRecord record = null;
try {
istIntermidiateDoc =
cswClient.submitHttpRequest("GET", requestUrl,
"");
String responseStr = Utils.getInputString2(istIntermidiateDoc);
LOG.log(Level.FINER, "Get Record By Id intermidiate XML = {0}", responseStr);
response.setResponseXML(Utils.chkStr(responseStr));
record = new CswRecord();
CswRecords recordList = null;
try {
LOG.finer("GetRecordById: Making csw record object using g" +
"etRecordsResponse operation");
// making cswObject by going through getrecord response xslt
CswResult results = new CswResult();
profile.readGetRecordsResponse(responseStr, results);
recordList = results.getRecords();
Iterator iter = recordList.iterator();
if(iter.hasNext()) {
Object obj = iter.next();
if(obj instanceof CswRecord ) {
record = (CswRecord) obj;
}
} 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. " + "{0}", 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. " + "{0}", 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. " + "{0}", e.getMessage());
}
record.setId(DocID);
LOG.finer("GetRecordByID: Transforming intermidiate xml to populate xml " +
"into csw Record");
profile.readCSWGetMetadataByIDResponse(getCswClient(),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().equals(""));
boolean hasResourceUrl = !(record.getMetadataResourceURL() == null || record
.getMetadataResourceURL().equals(""));
if(!hasResourceUrl && requestUrl != null ) {
record.setMetadataResourceURL(requestUrl);
hasResourceUrl = true;
}
if (!hasFullMetadata && !hasResourceUrl) {
throw new InvalidOperationException("Neither full metadata nor metadata"
+ " resource URL was found for the CSW record.");
}
}
finally {
Utils.close(istIntermidiateDoc);
Utils.close(bStream);
}
return record;
}
/**
* Gets the record by id.
*
* @param requestURL the request URL (CSW service url)
* @param DocID the doc ID (GUID or UUID)
* @param profile the profile
*
* @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 CswRecord getRecordById(String requestURL, String DocID,
CswProfile profile, String username, String password)
throws IOException, TransformerException,
NullReferenceException, InvalidOperationException {
String requestUrl = profile.generateCSWGetMetadataByIDRequestURL(requestURL,
DocID);
if (cswClient == null) {
cswClient = new CswClient();
cswClient.setBatchHttpClient(catalog.getBatchHttpClient());
}
BufferedInputStream bStream = null;
InputStream istIntermidiateDoc = null;
InputStream istRealDoc = null;
CswRecord record = null;
try {
istIntermidiateDoc =
cswClient.submitHttpRequest("GET", requestUrl,
"", username, password);
String responseStr = Utils.getInputString2(istIntermidiateDoc);
LOG.log(Level.FINER, "Get Record By Id intermidiate XML = {0}", responseStr);
response.setResponseXML(Utils.chkStr(responseStr));
record = new CswRecord();
CswRecords recordList = new CswRecords();
try {
LOG.finer("GetRecordById: Making csw record object using g" +
"etRecordsResponse operation");
// making cswObject by going through getrecord response xslt
profile.readCSWGetRecordsResponse(responseStr, recordList);
Iterator iter = recordList.iterator();
if(iter.hasNext()) {
Object obj = iter.next();
if(obj instanceof CswRecord ) {
record = (CswRecord) obj;
}
} 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. " + "{0}", 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. " + "{0}", 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. " + "{0}", e.getMessage());
}
record.setId(DocID);
LOG.finer("GetRecordByID: Transforming intermidiate xml to populate xml " +
"into csw Record");
profile.readCSWGetMetadataByIDResponse(getCswClient(), 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() == "");
if(!hasResourceUrl && requestUrl != null ) {
record.setMetadataResourceURL(requestUrl);
hasResourceUrl = true;
}
if (!hasFullMetadata && !hasResourceUrl) {
throw new InvalidOperationException("Neither full metadata nor metadata"
+ " resource URL was found for the CSW record.");
} else if (hasResourceUrl) {
// need to load metadata from resource URL
istRealDoc = cswClient.submitHttpRequest("GET", Utils.chkStr(record
.getMetadataResourceURL()), "", username, password);
responseStr = Utils.getInputString2(istRealDoc);
record.setFullMetadata(responseStr);
}
}
finally {
Utils.close(istIntermidiateDoc);
Utils.close(bStream);
}
return record;
}
/**
* Get the CSW search response of a CSW search request
*
* Get the CSW search response of a CSW search request
* @return a CswSearchResponse object.
*/
public CswSearchResponse getResponse() {
return this.response;
}
/**
* Search CSW catalog using the provided criteria. Search result can be accessed
* by calling GetResponse().
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
* @throws XPathExpressionException
* @throws TransformerException
*/
public void search() throws NullReferenceException, XPathExpressionException,
ParserConfigurationException, SAXException, IOException,
TransformerException {
// Check the necessary info. to search csw
if (catalog == null) {
throw new NullReferenceException("No catalog specified");
}
if (criteria == null) {
throw new NullReferenceException("No specified Criteria");
}
if (catalog.getUrl() == null || catalog.getUrl().length() == 0) {
throw new NullReferenceException("No specified url");
}
if (catalog.getProfile() == null) {
throw new NullReferenceException("No specified profile");
}
// Generate getRecords query
CswProfile profile = catalog.getProfile();
catalog.connect();
CswCatalogCapabilities capabilities = catalog.getCapabilities();
String requestUrl = capabilities.get_getRecordsPostURL();
String requestQuery = profile.generateCSWGetRecordsRequest(criteria);
// Submit search query and get response as an InputStream object
InputStream responseStream = cswClient.submitHttpRequest("POST", requestUrl,
requestQuery);
BufferedInputStream bIStream = new BufferedInputStream(responseStream);
try {
// String responseStr = Utils.getInputString(bIStream);
String responseStr = readCharacters(bIStream, "UTF-8");
// Transform input xml to output xml with Profile
CswRecords records = new CswRecords();
profile.readCSWGetRecordsResponse(responseStr, records);
response.set_requestStr(requestQuery);
response.setRecords(records);
response.setResponseXML(responseStr);
} finally {
Utils.close(bIStream);
Utils.close(responseStream);
}
}
/**
* Fully reads the characters from an input stream.
* @param stream the input stream
* @param charset the encoding of the input stream
* @return the characters read
* @throws IOException if an exception occurs
*/
private String readCharacters(InputStream stream, String charset)
throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
InputStreamReader ir = null;
try {
if ((charset == null) || (charset.trim().length() == 0)) charset = "UTF-8";
char cbuf[] = new char[2048];
int n = 0;
int nLen = cbuf.length;
ir = new InputStreamReader(stream,charset);
br = new BufferedReader(ir);
while ((n = br.read(cbuf,0,nLen)) > 0) sb.append(cbuf,0,n);
} finally {
try {if (br != null) br.close();} catch (Exception ef) {}
try {if (ir != null) ir.close();} catch (Exception ef) {}
}
return sb.toString();
}
}