/* 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 com.esri.gpt.framework.search.DcList;
import com.esri.gpt.framework.search.SearchXslProfile;
import com.esri.gpt.framework.util.ResourceXml;
import com.esri.gpt.framework.util.Val;
import com.esri.gpt.framework.xml.XmlIoUtil;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;
import org.xml.sax.SAXException;
/**
* The Class CswProfile. Hold the class statically if you intend to use
* the XSLT templates.
*
*/
public class CswProfile extends
SearchXslProfile<CswSearchCriteria, CswRecord, CswRecords, CswResult> {
// class variables =============================================================
/** The class logger *. */
private static Logger LOG = Logger.getLogger(CswProfile.class
.getCanonicalName());
private static final Pattern XML_TEST_PATTERN = Pattern.compile("^\\p{Space}*(<!--(.|\\p{Space})*?-->\\p{Space}*)+<\\?xml");
// instance variables ==========================================================
/** The filter_extentsearch. */
private boolean filter_extentsearch;
/** The filter_livedatamap. */
private boolean filter_livedatamap;
/** Used to get element with the metadata document during getElementBy Id. */
private final static String SCHEME_METADATA_DOCUMENT =
"urn:x-esri:specification:ServiceType:ArcIMS:Metadata:Document";
// constructors ================================================================
/**
* Instantiates a new csw profile.
*/
public CswProfile() {
}
/**
* The Constructor.
*
* @param sid the sid
* @param sname the sname
* @param sdescription the sdescription
*/
public CswProfile(String sid, String sname, String sdescription) {
}
/**
* The Constructor.
*
* @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
* @param livedatamap the livedatamap
* @param extentsearch the extentsearch
*/
public CswProfile(String id, String name, String description, String kvp,
String requestxslt, String responsexslt, String metadataxslt,
boolean livedatamap, boolean extentsearch) {
this.setId(id);
this.setName(name);
this.setDescription(description);
this.setKvp(kvp);
this.setMetadataxslt(metadataxslt);
this.setResponsexslt(responsexslt);
this.setRequestxslt(requestxslt);
this.filter_livedatamap = livedatamap;
this.filter_extentsearch = extentsearch;
}
// properties ==================================================================
// methods =====================================================================
/**
* Generate a CSW request String to get metadata by ID.
* The CSW request String is built. The request is String is build based
* on the baseurl and record id
*
* @param baseURL the base URL
* @param recordId the record id
*
* @return The request String
*
*
*/
public String generateCSWGetMetadataByIDRequestURL(String baseURL,
String recordId) {
String kvp = this.getKvp();
recordId = Utils.chkStr(recordId);
try {
recordId = URLEncoder.encode(recordId, "UTF-8");
} catch (Exception e) {
LOG.log(Level.WARNING, "Could not encode record Id " + recordId, e);
}
StringBuffer requeststring = new StringBuffer();
requeststring.append(baseURL);
if (baseURL.endsWith("?")){
requeststring.append(Utils.chkStr(kvp));
}
else if (baseURL.contains("?")) {
requeststring = new StringBuffer();
requeststring.append(baseURL.substring(0, baseURL.indexOf("?") + 1) + Utils.chkStr(kvp));
} else if(kvp.contains("{0}") &&
!kvp.contains("=")) {
requeststring.append(kvp);
// taking out need for question mark
}
else {
requeststring.append("?" + Utils.chkStr(kvp));
}
if(requeststring.toString().contains("{0}")) {
String tmp = requeststring.toString().replace("{0}", recordId);
requeststring = new StringBuffer(tmp);
} else {
requeststring.append("&ID=" + recordId);
}
return requeststring.toString();
}
/**
* Generate a CSW request String.
* First, create a simple common form of request xml
* Then, transform the request xml into a real request xml using profile specific xslt
*
* The CSW request String is built. The request is String is build based
* on the request xslt.
*
* @param search the search
*
* @return The request String
*
* @throws TransformerException the transformer exception
* @throws IOException Signals that an I/O exception has occurred.
*
*
*/
public String generateCSWGetRecordsRequest(CswSearchCriteria search)
throws TransformerException, IOException {
// Build xml
String request = "<?xml version='1.0' encoding='UTF-8' ?>";
request += "<GetRecords>" + "<StartPosition>" + search.getStartPosition()
+ "</StartPosition>";
request += "<MaxRecords>" + search.getMaxRecords() + "</MaxRecords>";
request += "<KeyWord>" + this.XmlEscape(search.getSearchText())
+ "</KeyWord>";
request += ("<LiveDataMap>" + search.isLiveDataAndMapsOnly() + "</LiveDataMap>");
if (search.getEnvelope() != null) {
request += ("<Envelope>");
request += "<MinX>" + search.getEnvelope().getMinX() + "</MinX>";
request += "<MinY>" + search.getEnvelope().getMinY() + "</MinY>";
request += "<MaxX>" + search.getEnvelope().getMaxX() + "</MaxX>";
request += "<MaxY>" + search.getEnvelope().getMaxY() + "</MaxY>";
request += "</Envelope>";
request += "<RecordsFullyWithinEnvelope>"+ search.isEnvelopeContains() +"</RecordsFullyWithinEnvelope>";
request += "<RecordsIntersectWithEnvelope>"+ search.isEnvelopeIntersects() +"</RecordsIntersectWithEnvelope>";
}
request += "</GetRecords>";
LOG.fine("Internal CSW Request = \n"+ request);
//Get an XSL Transformer object
String requestStr = this.getRequestxsltobj().transform(request);
return requestStr;
}
/**
* Read a CSW metadata response for search engine local.
* Will populate record referenceList and record metadataResourceUrl
* The CSW metadata response is read. The CSw record is updated with the
* metadata
*
* @param response the response
* @param record the record
*
* @throws TransformerException the transformer exception
*
*/
public void readCSWGetMetadataByIDResponseLocal(String response, CswRecord record)
throws 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(Utils.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);
}
}
/**
* Read a CSW metadata response. Will populate record referenceList and record metadataResourceUrl
* The CSW metadata response is read. The CSw record is updated with the
* metadata
*
* @param recordByIdResponse the response
* @param record the record
*
* @throws TransformerException the transformer exception
* @throws IOException Exception while reading
*
*/
public void readCSWGetMetadataByIDResponse(CswClient cswClient, String recordByIdResponse, CswRecord record)
throws TransformerException, IOException {
String metadataxslt = this.getMetadataxslt();
if (metadataxslt == null || metadataxslt.equals("")) {
record.setFullMetadata(Utils.chkStr(recordByIdResponse));
} else {
LOG.finer("Transforming GetRecordByID intermidiate xml to GetRecordById " +
"Native");
String sRecordByIdXslt = this.getMetadataXsltObj()
.transform(Utils.chkStr(recordByIdResponse));
String xmlUrl = null;
String dctReferences = sRecordByIdXslt;
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);
// T.M. Adds so that xslt for ouput xml for transform Metadata can be
// used
String indirectUrlXml = null;
if(!Val.chkStr(record.getMetadataResourceURL()).equals("")) {
InputStream istRealDoc = cswClient.submitHttpRequest("GET",
Utils.chkStr(record.getMetadataResourceURL()), "", "", "");
indirectUrlXml = Val.chkStr(Utils.getInputString2(istRealDoc));
}
if(!Val.chkStr(indirectUrlXml).equals("")) {
// Indirect xml
record.setFullMetadata(indirectUrlXml);
} else if(!Val.chkStr(sRecordByIdXslt).equals("")) {
try {
// Check if it is an xml document
XmlIoUtil.transform(sRecordByIdXslt);
record.setFullMetadata(sRecordByIdXslt);
} catch(Exception e) {
ResourceXml resourceXml = new ResourceXml();
String fullMetadata = resourceXml.makeResourceFromCswResponse(recordByIdResponse, record.getId());
record.setFullMetadata(fullMetadata);
}
} else {
// The get record by id
record.setFullMetadata(recordByIdResponse);
}
}
}
/**
* Parse a CSW response.
* The CSW response is parsed and the records collection is populated with
* the result.The reponse is parsed based on the response xslt.
*
* @param src the src
* @param recordList the record list
*
* @throws TransformerException the transformer exception
* @throws ParserConfigurationException the parser configuration exception
* @throws IOException Signals that an I/O exception has occurred.
* @throws SAXException the SAX exception
* @throws XPathExpressionException the x path expression exception
*/
public void readCSWGetRecordsResponse(String src, CswRecords recordList)
throws TransformerException, SAXException, IOException,
ParserConfigurationException, XPathExpressionException {
CswResult result = new CswResult();
super.readGetRecordsResponse(src, result);
recordList.addAll(result.getRecords());
}
/**
* Support content type query.
*
* @return true, if successful
*/
@Override
public boolean SupportContentTypeQuery() {
return isSupportsContentTypeQuery();
}
/* (non-Javadoc)
* @see com.esri.gpt.framework.search.SearchXslProfile#SupportSpatialBoundary()
*/
@Override
public boolean SupportSpatialBoundary() {
return isSupportsSpatialBoundary();
}
/**
* Support spatial query.
*
* @return true, if successful
*/
@Override
public boolean SupportSpatialQuery() {
return isSupportsSpatialQuery();
}
/**
* replace special xml character.
* Encode special characters (such as &, ", <, >, ') to percent values.
* </remarks>
* <param name="data
*
* @param data the data
*
* @return the string
*
*
*/
private String XmlEscape(String data) {
data = data.replace("&", "&");
data = data.replace("<", "<");
data = data.replace(">", ">");
data = data.replace("\"", """);
data = data.replace("'", "'");
return data;
}
/**
* Checks if is filter_extentsearch.
*
* @return true, if is filter_extentsearch
*/
@Override
public boolean isFilter_extentsearch() {
return filter_extentsearch;
}
/**
* Sets the filter_extentsearch.
*
* @param filter_extentsearch the new filter_extentsearch
*/
@Override
public void setFilter_extentsearch(boolean filter_extentsearch) {
this.filter_extentsearch = filter_extentsearch;
}
/**
* Checks if is filter_livedatamap.
*
* @return true, if is filter_livedatamap
*/
@Override
public boolean isFilter_livedatamap() {
return filter_livedatamap;
}
/**
* Sets the filter_livedatamap.
*
* @param filter_livedatamap the new filter_livedatamap
*/
@Override
public void setFilter_livedatamap(boolean filter_livedatamap) {
this.filter_livedatamap = filter_livedatamap;
}
/**
* Read get metadata by id response.
*
* @param response the response
* @param record the record
* @throws TransformerException the transformer exception
* @see com.esri.gpt.framework.search.SearchXslProfile#readGetMetadataByIDResponse(java.lang.String, com.esri.gpt.framework.request.Record)
*/
@Override
public void readGetMetadataByIDResponse(String response, CswRecord record)
throws TransformerException {
// TODO Auto-generated method stub
}
}