<commit_before>package com.indexdata.mkjsf.pazpar2;

import static com.indexdata.mkjsf.utils.Utils.nl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.indexdata.masterkey.config.MissingMandatoryParameterException;
import com.indexdata.masterkey.config.ModuleConfigurationGetter;
import com.indexdata.masterkey.pazpar2.client.ClientCommand;
import com.indexdata.masterkey.pazpar2.client.Pazpar2Client;
import com.indexdata.masterkey.pazpar2.client.Pazpar2ClientConfiguration;
import com.indexdata.masterkey.pazpar2.client.Pazpar2ClientGeneric;
import com.indexdata.masterkey.pazpar2.client.Pazpar2HttpResponse;
import com.indexdata.masterkey.pazpar2.client.exceptions.Pazpar2ErrorException;
import com.indexdata.masterkey.pazpar2.client.exceptions.ProxyErrorException;
import com.indexdata.mkjsf.config.Configuration;
import com.indexdata.mkjsf.config.ConfigurationReader;
import com.indexdata.mkjsf.errors.ConfigurationException;
import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Command;
import com.indexdata.mkjsf.pazpar2.data.CommandError;
import com.indexdata.mkjsf.utils.Utils;

public class Pz2Client implements SearchClient {

  private static final long serialVersionUID = 5414266730169982028L;
  private static Logger logger = Logger.getLogger(Pz2Client.class);
  private transient Pazpar2Client client = null;
  private Pazpar2ClientConfiguration cfg = null;
  public static final String MODULENAME = "pz2client";
  public static Map<String,String> DEFAULTS = new HashMap<String,String>();
  Configuration config = null;  
  
  static {    
    DEFAULTS.put("PAZPAR2_URL", "");
    DEFAULTS.put("PROXY_MODE","1");
    DEFAULTS.put("SERIALIZE_REQUESTS", "false");
    DEFAULTS.put("STREAMBUFF_SIZE", "4096");
    DEFAULTS.put("PARSE_RESPONSES", "true");    
  }
  
  public Pz2Client() {}
  
  @Override
  public void configure(ConfigurationReader configReader) throws ConfigurationException {    
    logger.info(Utils.objectId(this) + " is configuring using the provided " + Utils.objectId(configReader));
    try {
      config = configReader.getConfiguration(this);      
      cfg = new Pazpar2ClientConfiguration(new ConfigurationGetter(config));
    } catch (ProxyErrorException pe) {
      logger.error("Could not configure Pazpar2 client: " + pe.getMessage());
      throw new ConfigurationException("Could not configure Pz2Client:  "+ pe.getMessage(),pe);
    } 
    if (cfg != null) {
      try {
        client = new Pazpar2ClientGeneric(cfg);  
      } catch (ProxyErrorException pe) {
        logger.error("Could not configure Pazpar2 client: " + pe.getMessage());
        throw new ConfigurationException("Could not configure Pz2Client:  "+ pe.getMessage(),pe);
      }
    } else {
      logger.error("There was a problem creating Pz2Client. Client is null after configuration.");
      throw new ConfigurationException("Pazpar2Client is null after configuration");
    } 
  }
  
  public boolean isAuthenticatingClient () {
    return false;
  }
  
  public boolean isAuthenticated() {
    return false;
  }
  
  public boolean authenticate() {
    throw new UnsupportedOperationException("No authentication mechanism for straight pazpar2 client");
  }
  
  @Override
  public void setSearchCommand(Pazpar2Command command) {
    ClientCommand clientCommand = new ClientCommand(command.getCommandName(), command.getEncodedQueryString());
    client.setSearchCommand(clientCommand);    
  }

  @Override
  public HttpResponseWrapper executeCommand(Pazpar2Command command) {
    ClientCommandResponse commandResponse = null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ClientCommand clientCommand = new ClientCommand(command.getCommandName(), command.getEncodedQueryString());
    Pazpar2HttpResponse pz2HttpResponse = null;
    long start = System.currentTimeMillis();
    try {
      pz2HttpResponse = client.executeCommand(clientCommand, baos);
      if (pz2HttpResponse.getStatusCode()==200) {
        commandResponse = new ClientCommandResponse(pz2HttpResponse,baos);
      } else if (pz2HttpResponse.getStatusCode()==417) {
        logger.error("Pazpar2 status code 417: " + baos.toString("UTF-8"));
        commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.insertErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()) ,"Pazpar2: Expectation failed (417)", baos.toString("UTF-8")),"text/xml");                       
      } else {
        String resp = baos.toString("UTF-8");
        logger.error("Pazpar2 status code was " + pz2HttpResponse.getStatusCode() + ": " + resp);
        commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.insertErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "Pazpar2 error occurred", baos.toString("UTF-8")),"text/xml");
        throw new Pazpar2ErrorException(resp,pz2HttpResponse.getStatusCode(),resp,null);
      }       
    } catch (IOException e) {
      logger.error(e.getMessage());
      e.printStackTrace();
      commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "io", e.getMessage()),"text/xml");      
    } catch (Pazpar2ErrorException e) {
      logger.error(e.getMessage());
      e.printStackTrace();
      logger.error("Creating error XML");
      commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "io", e.getMessage()),"text/xml");
    }
    long end = System.currentTimeMillis();      
    logger.debug("Executed " + command.getCommandName() + " in " + (end-start) + " ms." );
    return commandResponse;
  }

  public Pz2Client cloneMe() {
    logger.debug("Cloning Pz2Client");
    Pz2Client clone = new Pz2Client();
    clone.client = this.client;
    clone.cfg = this.cfg;
    return clone;
  }

  @Override
  public Map<String, String> getDefaults() {
    return DEFAULTS;
  }

  @Override
  public String getModuleName() {
    return MODULENAME;
  }
  
  class ConfigurationGetter implements ModuleConfigurationGetter {
    Configuration config = null;<commit_msg>Tries to pick up wrong Pazpar2 address errors for errxml<commit_after>package com.indexdata.mkjsf.pazpar2;

import static com.indexdata.mkjsf.utils.Utils.nl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.indexdata.masterkey.config.MissingMandatoryParameterException;
import com.indexdata.masterkey.config.ModuleConfigurationGetter;
import com.indexdata.masterkey.pazpar2.client.ClientCommand;
import com.indexdata.masterkey.pazpar2.client.Pazpar2Client;
import com.indexdata.masterkey.pazpar2.client.Pazpar2ClientConfiguration;
import com.indexdata.masterkey.pazpar2.client.Pazpar2ClientGeneric;
import com.indexdata.masterkey.pazpar2.client.Pazpar2HttpResponse;
import com.indexdata.masterkey.pazpar2.client.exceptions.Pazpar2ErrorException;
import com.indexdata.masterkey.pazpar2.client.exceptions.ProxyErrorException;
import com.indexdata.mkjsf.config.Configuration;
import com.indexdata.mkjsf.config.ConfigurationReader;
import com.indexdata.mkjsf.errors.ConfigurationException;
import com.indexdata.mkjsf.pazpar2.commands.Pazpar2Command;
import com.indexdata.mkjsf.pazpar2.data.CommandError;
import com.indexdata.mkjsf.utils.Utils;

public class Pz2Client implements SearchClient {

  private static final long serialVersionUID = 5414266730169982028L;
  private static Logger logger = Logger.getLogger(Pz2Client.class);
  private transient Pazpar2Client client = null;
  private Pazpar2ClientConfiguration cfg = null;
  public static final String MODULENAME = "pz2client";
  public static Map<String,String> DEFAULTS = new HashMap<String,String>();
  Configuration config = null;  
  
  static {    
    DEFAULTS.put("PAZPAR2_URL", "");
    DEFAULTS.put("PROXY_MODE","1");
    DEFAULTS.put("SERIALIZE_REQUESTS", "false");
    DEFAULTS.put("STREAMBUFF_SIZE", "4096");
    DEFAULTS.put("PARSE_RESPONSES", "true");    
  }
  
  public Pz2Client() {}
  
  @Override
  public void configure(ConfigurationReader configReader) throws ConfigurationException {    
    logger.info(Utils.objectId(this) + " is configuring using the provided " + Utils.objectId(configReader));
    try {
      config = configReader.getConfiguration(this);      
      cfg = new Pazpar2ClientConfiguration(new ConfigurationGetter(config));
    } catch (ProxyErrorException pe) {
      logger.error("Could not configure Pazpar2 client: " + pe.getMessage());
      throw new ConfigurationException("Could not configure Pz2Client:  "+ pe.getMessage(),pe);
    } 
    if (cfg != null) {
      try {
        client = new Pazpar2ClientGeneric(cfg);  
      } catch (ProxyErrorException pe) {
        logger.error("Could not configure Pazpar2 client: " + pe.getMessage());
        throw new ConfigurationException("Could not configure Pz2Client:  "+ pe.getMessage(),pe);
      }
    } else {
      logger.error("There was a problem creating Pz2Client. Client is null after configuration.");
      throw new ConfigurationException("Pazpar2Client is null after configuration");
    } 
  }
  
  public boolean isAuthenticatingClient () {
    return false;
  }
  
  public boolean isAuthenticated() {
    return false;
  }
  
  public boolean authenticate() {
    throw new UnsupportedOperationException("No authentication mechanism for straight pazpar2 client");
  }
  
  @Override
  public void setSearchCommand(Pazpar2Command command) {
    ClientCommand clientCommand = new ClientCommand(command.getCommandName(), command.getEncodedQueryString());
    client.setSearchCommand(clientCommand);    
  }

  @Override
  public HttpResponseWrapper executeCommand(Pazpar2Command command) {
    ClientCommandResponse commandResponse = null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ClientCommand clientCommand = new ClientCommand(command.getCommandName(), command.getEncodedQueryString());
    Pazpar2HttpResponse pz2HttpResponse = null;
    long start = System.currentTimeMillis();
    try {
      pz2HttpResponse = client.executeCommand(clientCommand, baos);
      if (pz2HttpResponse.getStatusCode()==200 && pz2HttpResponse.getContentType().contains("xml")) {
        commandResponse = new ClientCommandResponse(pz2HttpResponse,baos);
      } else if (pz2HttpResponse.getStatusCode()==417) {
        logger.error("Pazpar2 status code 417: " + baos.toString("UTF-8"));
        commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.insertErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()) ,"Pazpar2: Expectation failed (417)", baos.toString("UTF-8")),"text/xml");                       
      } else if (pz2HttpResponse.getContentType().contains("html")) {
        String resp = baos.toString("UTF-8");
        logger.error("HTML response where XML was expected. Status code was " + pz2HttpResponse.getStatusCode() + ": " + resp);
        String htmlStrippedOfTags = resp.replaceAll("\\<[^>]*>","");
        String errorXml = "";
        if (htmlStrippedOfTags.toLowerCase().contains("domain")) {
          errorXml = CommandError.createErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "Error: Expected XML response from Pazpar2, got HTML with the word domain. Could be unrecognized address for Pazpar2.", htmlStrippedOfTags);
        } else {  
          errorXml = CommandError.createErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "Error: Expected XML response from Pazpar2, got HTML", htmlStrippedOfTags);
        } 
        commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),errorXml,"text/xml");        
      } else {
        String resp = baos.toString("UTF-8");
        logger.error("Pazpar2 status code was " + pz2HttpResponse.getStatusCode() + ": " + resp);
        commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.insertErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "Pazpar2 error occurred", baos.toString("UTF-8")),"text/xml");        
      }       
    } catch (IOException e) {
      logger.error(e.getMessage());
      e.printStackTrace();
      commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.createErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "io", e.getMessage()),"text/xml");      
    } catch (Pazpar2ErrorException e) {
      logger.error(e.getMessage());
      e.printStackTrace();
      logger.error("Creating error XML");
      commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml(command.getCommandName(), "-1", "Pazpar2Error", e.getMessage()),"text/xml");
    }
    long end = System.currentTimeMillis();      
    logger.debug("Executed " + command.getCommandName() + " in " + (end-start) + " ms." );
    return commandResponse;
  }

  public Pz2Client cloneMe() {
    logger.debug("Cloning Pz2Client");
    Pz2Client clone = new Pz2Client();
    clone.client = this.client;
    clone.cfg = this.cfg;
    return clone;
  }

  @Override
  public Map<String, String> getDefaults() {
    return DEFAULTS;
  }

  @Override
  public String getModuleName() {
    return MODULENAME;
  }
  
  class ConfigurationGetter implements ModuleConfigurationGetter {
    Configuration config = null;
{'fraction_non_alphanumeric': 0.11035333381702096, 'fraction_numerical': 0.015381266777914822, 'mean_word_length': 4.428909019298937, 'pattern_counts': {'":': 3, '<': 10, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 11}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6342673', 'n_tokens_mistral': 4027, 'n_tokens_neox': 4015, 'n_words': 772}