Package com.esri.gpt.catalog.search

Source Code of com.esri.gpt.catalog.search.SearchEngineRest

/* 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.catalog.search;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathExpressionException;

import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


import com.esri.gpt.framework.collection.StringSet;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.http.CredentialProvider;
import com.esri.gpt.framework.http.HttpClientRequest;
import com.esri.gpt.framework.isodate.IsoDateFormat;
import com.esri.gpt.framework.jsf.MessageBroker;
import com.esri.gpt.framework.search.SearchXslProfile;
import com.esri.gpt.framework.search.SearchXslRecord;
import com.esri.gpt.framework.util.ResourcePath;
import com.esri.gpt.framework.util.Val;
import com.esri.gpt.framework.xml.DomUtil;
import com.esri.gpt.framework.xml.XmlIoUtil;
import java.text.ParseException;
import java.util.Date;

/**
* The class SearchEngineCSW. Accesses a CSW repository to send searTch
* and parse back results.  works closely with the csw client jar.
*
*/
public class SearchEngineRest extends ASearchEngine {

// class variables =============================================================
/** The Class Logger. */
private static final Logger LOG = Logger.getLogger(
    SearchEngineRest.class.getCanonicalName());

/** The Constant DELIMETER key value pair */
public final static String DELIMETER_KVP = "\u2715";

/** The Constant DELIMETER_VALUES between key value*/
public final static String DELIMETER_KV = "\u2714";

/** Xsl Param opensearch URL **/
private static final String XSL_PARAM_OPENSEARCH_URL = "searchQueryUrl";

/** The Constant JSFBEAN_SEARCH_CONTROLLER. */
private static final String JSFBEAN_SEARCH_CONTROLLER = "SearchController";

// instance variables ==========================================================
/** The search xsl req res. */

/** The get record by id kvpurl. */
private String recordByIdKvpurl = null;

/** The profile id *. */
private String profileId = "";

/** The end point url. */
private String endPointSearchUrl;

/** The end point metadata url. */
private String endPointMetadataUrl;

/** The xsl profile. */
private SearchGptXslProfiles xslProfiles;

/** The default search text. */
private String defaultParamValues;

/** The replace url values. */
private String replaceUrlValues;



// constructor =================================================================

private SearchEngineRest() {
 
}
/**
* Instantiates a new search engine rest.
*
* @param context the context
*/
public SearchEngineRest(RequestContext context) {
    super(context);
}
// properties ==================================================================

/**
* Sets the default param values.
*
* @param defaultParamValues the new default param values
*/
public void setDefaultParamValues(String defaultParamValues) {
  this.defaultParamValues = defaultParamValues;
}

/**
* Gets the end point url.
*
* @return the end point url (trimmed, never null)
*/
public String getEndPointSearchUrl() {
  return Val.chkStr(endPointSearchUrl);
}

/**
* Sets the end point url.
*
* @param endPointUrl the new end point url
*/
public void setEndPointSearchUrl(String endPointUrl) {
  this.endPointSearchUrl = endPointUrl;
}


/**
* Gets the profile id.
*
* @return the profile id (trimmed, never null)
*/
public String getProfileId() {
  return Val.chkStr(profileId);
}

/**
* Sets the profile id.
*
* @param profileId the new profile id
*/
public void setProfileId(String profileId) {
  this.profileId = profileId;
}

/**
* Gets the record by id kvpurl.
*
* @return the record by id kvpurl (trimmed, never null)
* @throws SearchException
*/
public String getRecordByIdKvpurl() throws SearchException {
  if("".equals(Val.chkStr(recordByIdKvpurl))) {
    return Val.chkStr(this.readXslProfile().getKvp());
  }
  return Val.chkStr(recordByIdKvpurl);
}

/**
* Sets the record by id kvpurl.
*
* @param recordByIdKvpurl the new record by id kvpurl
*/
public void setRecordByIdKvpurl(String recordByIdKvpurl) {
  this.recordByIdKvpurl = recordByIdKvpurl;
}

/**
* Sets the replace url values.
*
* @param replaceUrlValues the new replace url values
*/
public void setReplaceUrlValues(String replaceUrlValues) {
  this.replaceUrlValues = replaceUrlValues;
}

/**
* Gets the xsl profiles.
*
* @return the xsl profiles
* @throws SearchException the search exception
*/
public SearchGptXslProfiles getXslProfiles() throws SearchException {
  if(xslProfiles == null) {
    xslProfiles = SearchConfig.getConfiguredInstance().getGptXslProfiles();
  }
  return xslProfiles;
}


/**
* Sets the xsl profiles.
*
* @param xslProfiles the new xsl profiles
*/
public void setXslProfiles(SearchGptXslProfiles xslProfiles) {
  this.xslProfiles = xslProfiles;
}

/**
* Gets the end point metadata url.
*
* @return the end point metadata url (trimmed, never null)
*/
public String getEndPointMetadataUrl() {
  return Val.chkStr(endPointMetadataUrl);
}


/**
* Sets the end point metadata url.
*
* @param endPointMetadataUrl the new end point metadata url
*/
public void setEndPointMetadataUrl(String endPointMetadataUrl) {
  this.endPointMetadataUrl = endPointMetadataUrl;
}

/**
* Gets the metadata url for record.
*
* @param uuid the uuid
*
* @return the metadata url
*
* @throws SearchException the search exception
*/
@Override
public String getMetadataUrl(String uuid) throws SearchException  {
  return this.getRecordByIdKvpurl().replaceFirst("\\{id\\}", uuid);
}

/**
* Get the connection uri
*
* @return uri representing the search
*/
@Override
public URI getConnectionUri() throws SearchException {
  Exception ex = null;
  try {
    return new URL(this.getSearchQuery()).toURI();
  } catch (MalformedURLException e) {
    ex = e;
  } catch (SearchException e) {
    ex = e;
  } catch (URISyntaxException e) {
    ex = e;
  }
  throw new SearchException("Could not get the connection uri", ex);
 
}

// methods =====================================================================
/*
* Sets items that may have been handed from the factory (from gpt.xml)
* <br/>
* Assigns value of endPointUrl to setEndPointUrl
* <br/>
* Assigns profileId to setProfileId
*
* Uses attributes connectionUrl, profileId, metadataUrl attributes for
* searchengine in gpt.xml
*
*
* @see com.esri.gpt.catalog.search.ASearchEngine#init()
*/
/*@Override
public void init() throws SearchException {
  super.init();
  this.class.
  Map<String, String> factoryAttributes =  this.getFactoryAttributes();
  if(factoryAttributes == null) {
    return; 
  }
  Object obj = factoryAttributes.get(ATTRIBUTE_CONNECTION_URL);
  if(obj != null) {
    this.setEndPointSearchUrl(obj.toString());
    LOG.finer("Init Connection url: " + obj.toString());
  }
  obj = factoryAttributes.get(ATTRIBUTE_PROFILE_ID);
  if(obj != null) {
    this.setProfileId(obj.toString());
    LOG.finer("Init Profile id: " + obj.toString());
  }
  obj = factoryAttributes.get(ATTRIBUTE_METADATA_URL);
  if(obj != null) {
    this.setEndPointMetadataUrl(obj.toString());
    LOG.finer("Init Metadata Profile id: " + obj.toString());
  }
  obj = factoryAttributes.get(ATTRIBUTE_DEFAULT_PARAMVALS);
  if(obj != null) {
    this.setDefaultParamValues(obj.toString());
    LOG.finer("Init Default Param values: " + obj.toString());
  }
}*/




/*
* Does a search
*
* @param hitsOnly Only the hits
* @see com.esri.gpt.catalog.search.ASearchEngine#doSearch()
*/
@Override
public void doSearch() throws SearchException {
  Exception ex = null;
 
 
  try {
    URI uri = this.getConnectionUri();
    URL url = uri.toURL();
    HttpClientRequest clientRequest =
      HttpClientRequest.newRequest(HttpClientRequest.MethodName.GET,
          url.toExternalForm());
    clientRequest.setConnectionTimeMs(getConnectionTimeoutMs());
    clientRequest.setResponseTimeOutMs(getResponseTimeoutMs());
   
    Map map = (Map)
      this.getRequestContext().extractFromSession(SEARCH_CREDENTIAL_MAP);
    if(map != null) {
      CredentialProvider credProvider = (CredentialProvider)
        map.get(this.getKey());
      if(credProvider  != null) {
        clientRequest.setCredentialProvider(credProvider);
      }
    }       
   
    clientRequest.execute();
    String response = clientRequest.readResponseAsCharacters();
    InputStream is = null;
    try {
      SearchXslProfile profile = this.readXslProfile();
      String js = Val.chkStr(profile.getResponsexslt());
      //String js = Val.chkStr(this.getFactoryAttributes().get("searchResponseJsT"));
      String xml = null;
      if(js.toLowerCase().endsWith(".js")) {
        try {
          ResourcePath rPath = new ResourcePath();
          URL fileUrl = rPath.makeUrl(js);
          is = fileUrl.openStream();
          String jsTransFile = IOUtils.toString(is, "UTF-8");
          jsTransFile = "var jsGptInput =" + response + ";" + jsTransFile;
          HttpServletRequest servletRequest = (HttpServletRequest)
              this.getRequestContext().getServletRequest();
          if(servletRequest != null) {
            jsTransFile = "var jsGptQueryString = '"
              + servletRequest.getQueryString() + "';" + jsTransFile;           
          }
          jsTransFile = "var jsGptEndpointSearchQuery = '" +
            url.toExternalForm() + "';" + jsTransFile;
          ScriptEngineManager manager = new ScriptEngineManager();
          ScriptEngine engine = manager.getEngineByName("JavaScript");
          //manager.put("jsGptInput", response);
            Object obj = engine.eval(jsTransFile);
            xml = obj.toString();
          parseResponse(xml);// has to work before the finally. dont move
        } catch (Exception e) {
          throw new SearchException(e.getMessage() + ":" +
              "Error when doing transformation from javascript", e);
        }
      } else {
        xml = XmlIoUtil.jsonToXml(response, "gptJsonXml");
        parseResponse(xml);
      }
     
      checkPagination();
    } catch(SearchException e) {
      throw e;
    } catch (Exception e) {
      parseResponse(response);
      checkPagination();
    } finally {
      if(is != null) {
          IOUtils.closeQuietly(is);
        }
    }
      
  } catch (MalformedURLException e) {
    ex = e;
  } catch (IOException e) {
    ex = e;
  } finally {
 
  }
  if(ex != null) {
    throw new SearchException(ex.getMessage() + ": Could not perform search",
        ex);
  }
}

/**
* Parses the response.
*
* @param xml the xml
* @throws SearchException
*/
@SuppressWarnings("unchecked")
public void parseResponse(String xml) throws SearchException {
 
  SearchResult searchResult = new SearchResult();
  SearchResultRecords searchResultRecords =
    this.getRequestDefinition().getResult().getRecords();
  try {
    this.readXslProfile().readGetRecordsResponse(xml, searchResult);
    this.getRequestDefinition().getResult().setMaxQueryHits(
        searchResult.getMaxQueryHits());
    SearchResultRecords records = searchResult.getRecords();
   
    HttpServletRequest servletRequest = (HttpServletRequest)
      this.getRequestContext().getServletRequest();
  if (servletRequest != null) {
    String queryString = Val
        .chkStr(servletRequest.getQueryString());
    if (records.size() > searchResult.getPageCursor()
            .getRecordsPerPage()) {
      // must be one of those endpoints that do not have a number
     
    }
  }
    Iterator iter = records.iterator();
    while(iter.hasNext()) {
     
      Object obj = iter.next();
     
      if(obj instanceof SearchResultRecord) {
        SearchResultRecord searchResultRecord =(SearchResultRecord) obj;
        searchResultRecord.setExternal(this.readIsExternalSearch())
        searchResultRecord.setExternalId(this.getKey());
        searchResultRecords.add(searchResultRecord);
      } else if (obj instanceof SearchXslRecord) {
        SearchResultRecord searchResultRecord =
          ((SearchXslRecord)obj).readAsSearchResult(
              this.getResourceLinkBuilder(),
              this.readIsExternalSearch(),
              this.getKey()
            );
        searchResultRecords.add(searchResultRecord);
      } else {
        throw new SearchException("Did not understand the parsed object " +
            obj.getClass().getCanonicalName());
      }
    }
  } catch (Exception e) {
    throw new SearchException(e.getMessage() + ":" +
        "Could not parse getRecordsResponse", e);
  }
 
}

private SearchXslRecord getMetadataAsObjectX(String uuid) throws SearchException {
  SearchResultRecord record = new SearchResultRecord();
  String metaUrl = this.getMetadataUrl(uuid);
  SearchXslRecord recordX = null;

  URL url = null;
  Exception ex = null;
  try {
    url = new URL(metaUrl);

    HttpClientRequest clientRequest = HttpClientRequest.newRequest(
        HttpClientRequest.MethodName.GET, url.toExternalForm());
    clientRequest.setConnectionTimeMs(getConnectionTimeoutMs());
    clientRequest.setResponseTimeOutMs(getResponseTimeoutMs());
    clientRequest.execute();
    String response = clientRequest.readResponseAsCharacters();
    LOG.log(Level.FINER, "Response from get Metadata url = {0}\n response = \n{1}", new Object[]{url.toExternalForm(), response});
    recordX = new SearchXslRecord();
    this.readXslProfile().readGetMetadataByIDResponse(response, recordX);
  } catch (MalformedURLException e) {
    ex = e;
  } catch (IOException e) {
    ex = e;
  } catch(TransformerException e) {
    ex = e;
  }
  if(ex != null) {
    throw new SearchException("Could not get metadata id url = " + url, ex);
  }
  return recordX;
}

/**
* Gets the metadata as object.
*
* @param uuid the uuid
* @return the metadata as object
* @throws SearchException the search exception
* @see com.esri.gpt.catalog.search.ASearchEngine#getMetadataAsSearchResultRecord(java.lang.String)
*/
@Override
public SearchResultRecord getMetadataAsSearchResultRecord(String uuid) throws
SearchException {
  return this.getMetadataAsObjectX(uuid)
    .readAsSearchResult(this.getResourceLinkBuilder()
        this.readIsExternalSearch(),
        this.getKey());
}

@Override
public ARecord getARecord(String uuid) throws SearchException {
  final SearchXslRecord record = getMetadataAsObjectX(uuid);
  ARecord aRecord = new ARecord() {
    @Override
    public String getMetadataAsText() {
      return record.getFullMetadata();
    }

    @Override
    public Date getModifiedDate() {
      String modifedDateAsString = record.getModifiedDate();
      try {
        return new IsoDateFormat().parseObject(modifedDateAsString);
      } catch (ParseException ex) {
        return null;
      }
    }
  };
  return aRecord;
}

/**
* Gets the metadata as text.
*
* @param uuid the uuid
* @return the metadata as text
* @throws SearchException the search exception
* @see com.esri.gpt.catalog.search.ASearchEngine#getMetadataAsText(java.lang.String)
*/
@Override
public String getMetadataAsText(String uuid) throws SearchException {
  this.getMetadataAsObjectX(uuid).getFullMetadata();
  return null;
}

/**
* Gets the default param values as map.
*
* @return the default param values (never null)
*/
public Map<String, String> readDefaultParamValues() {
  return readParamValues(Val.chkStr(this.defaultParamValues));
}

/**
* Read replace param values as map.
*
* @return the map
*/
public Map<String, String> readReplaceParamValues() {
  return readParamValues(Val.chkStr(this.replaceUrlValues));
}

/**
* Read param values as maps.
*
* @param param the param
* @return the map
*/
private Map<String, String>readParamValues(String param) {
  Map<String, String> defVals = new HashMap<String, String>();
  String vals = Val.chkStr(defaultParamValues);
  String kvp[] = vals.split(DELIMETER_KVP);
  for (int i = 0; kvp != null && i < kvp.length; i++) {
    String kv[] = (kvp[i]).split(DELIMETER_KV);
    if(kv == null) {
      continue;
    }
    String key = "";
    String value = "";
    if(kv.length < 1) {
      continue;
    }
    key = Val.chkStr(kv[0]);
    if("".equals(kv)) {
      continue;
    }
    if(kv.length > 1) {
      value = Val.chkStr(kv[1]);
    }
    defVals.put(key, value);   
  }
  return defVals;
}
/**
* Read xsl profile.
*
* @return the search xsl profile
* @throws SearchException the search exception
*/
@SuppressWarnings("unchecked")
public SearchXslProfile readXslProfile() throws SearchException {
  return  this.getXslProfiles().getProfileById(this.getProfileId());
 
}

/**
* Gets the search query.
*
* @return the search query
* @throws SearchException the search exception
*/
@SuppressWarnings("unchecked")
@Override
public String getSearchQuery() throws SearchException {
  String searchQuery = null;
  Exception ex = null;
  Map<String, String> map = this.getFactoryAttributes();
  map.put(XSL_PARAM_OPENSEARCH_URL,this.getEndPointSearchUrl());
   
  try {
    searchQuery = this.readXslProfile().generateGetRecordsRequest(this
        .getRequestDefinition().getCriteria(), map, this.getHitsOnly());
    String searchEndPoint = this.getEndPointSearchUrl();
    // assign values from the xslt
    Document doc = DomUtil.makeDomFromString(searchQuery, false);
    NodeList paramList = doc.getElementsByTagName("parameter");
    for(int i = 0; i < paramList.getLength(); i++ ) {
      Node paramNode = paramList.item(i);
      String key = paramNode.getAttributes().getNamedItem("key")
        .getNodeValue();
      String value = paramNode.getAttributes().getNamedItem("value")
        .getNodeValue();
     
      String paramValue = this.getFactoryAttributes().get(key);
      if (paramValue != null) {
        String paramValues[] = paramValue.split(DELIMETER_KVP);
        for (int j = 0; j < paramValues.length; j++) {
          String paramValueValues[] = Val.chkStr(paramValues[j]).split(
              DELIMETER_KV);
          if (paramValueValues.length < 2) {
            continue;
          }
          if (Val.chkStr(paramValueValues[0]).equalsIgnoreCase(value)) {
            value = paramValueValues[1];
          }
        }
      }
      key = key.replaceAll("([\\\\*+\\[\\](){}\\$.?\\^|])", "\\\\$1");
      searchEndPoint = searchEndPoint.replaceAll("(?i)" +  key,
          URLEncoder.encode(value, "UTF-8"));
    }
   
    // assign default values input
    Map<String, String> paramVals = this.readDefaultParamValues();
    Iterator<String> keyIter =  paramVals.keySet().iterator();
    while(keyIter.hasNext()) {
      String key = keyIter.next();
      if(searchEndPoint.contains(key + "=&") || searchEndPoint.endsWith(key + "=")) {
        searchEndPoint = searchEndPoint.replaceAll(key + "=",
            key + "=" + URLEncoder.encode(paramVals.get(key), "UTF-8"));
      }
    }
   
    // replace sections of the url
    paramVals = this.readReplaceParamValues();
    keyIter =  paramVals.keySet().iterator();
    while(keyIter.hasNext()) {
      String key = Val.chkStr(keyIter.next());
      String value = Val.chkStr(paramVals.get(key));
      searchEndPoint.replaceAll(key, value);
    }
   
    LOG.log(Level.FINER, "Search Query: {0}", searchEndPoint);
    return searchEndPoint;
  } catch (XPathExpressionException e) {
    ex = e;
  } catch (TransformerException e) {
    ex = e;
  } catch (ParserConfigurationException e) {
    ex = e;
  } catch (SAXException e) {
    ex = e;
  } catch (IOException e) {
    ex = e;
  }
  if (ex == null) {
    throw new SearchException("Error when generating search query", ex);
  }

  return searchQuery;

}

/**
* Read is external search.
*
* @return true, if successful
* @see com.esri.gpt.catalog.search.ASearchEngine#readIsExternalSearch()
*/
@Override
protected boolean readIsExternalSearch() {
  return true;
}

/**
*
* Creates instances of this search engines from the rids
*@param rids
*@return mapping between rids and search engines instances
*@throws SearchException
*/
@Override
public Map<String, Object> createInstances(StringSet rids)
throws SearchException{
  Map<String, Object> mapRid2Engine = new HashMap<String, Object>();
  for(String rid: rids) {
    SearchEngineRest searchEngineRest = new SearchEngineRest();
    searchEngineRest.setKey(rid);
    mapRid2Engine.put(rid, searchEngineRest);
  }
  return mapRid2Engine;
}

/**
* Gets the abstract associated with the key
*
* @return the abstract
* @throws SearchException
*/
@Override
public String getKeyAbstract() throws SearchException {
 
  Map<String, String> map = this.getFactoryAttributes();
  String absKey = null;
  if(map != null) {
     absKey = map.get("abstractResourceKey");
  }
  MessageBroker bundle = new MessageBroker();
  bundle.setBundleBaseName(MessageBroker.DEFAULT_BUNDLE_BASE_NAME);
  return bundle.retrieveMessage(absKey);
}

}
TOP

Related Classes of com.esri.gpt.catalog.search.SearchEngineRest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.