Package practicas

Source Code of practicas.AgenteBusqueda

package practicas;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.*;
import java.util.ArrayList;

import comunicacion.*;


/**
* Agente de búsqueda encargado de descargar el código de una web, procesarlo y replicarse.
* Permanecerá activo mientras su rama lo esté y se comunicará con otros agentes cuando sea necesario.
* @author jacinto
*
*/
public class AgenteBusqueda extends Thread implements Agente {

  // Atributos de la clase:
  public  String id;
  private URL url;
  private String[] keywords;
  private int[] ocurrenciasKW;
  private String codigo;
  private String texto;
  private ArrayList<String> vinculos;
  private ArrayList<String> vinculosNuevos;
 
  private LogFile log;
  private Pizarra pizarra;
 
  private int hijosActivos;
 
  private Agente padre;
  private ArrayList<AgenteBusqueda> hijos;
 
  private double temperatura;
 
 
  // Expresiones Regulares (utilizadas para procesar el código):
 
  private static String REGEX_TAG_VINCULOS   = "<a href[^>]*>";
  private static String REGEX_VINCULOS     = "\"http(s?)://[^\"']*\"";
  private static String REGEX_TEXTO      = "<[^>]*>";
 
 
  // Constantes:
  private static int    PROFUNDIDAD_MAXIMA = 2;
  private static int    MINIMO_OCURRENCIAS = 2;
 
  // De TEMPERATURA
  private static double TEMP_MAX = 2;
  private static double TEMP_CTE_ENFR = 0.5;
  private static double TEMP_CTE_CAL =  1;
 
  /**
   * Constructor para inicializiar un agente:
   *
   * @param p - El padre de dicho agente.
   * @param m - El fichero de log para escribir sus mensajes.
   * @param pi - La pziarra compartida de comunicación.
   * @param i - El identificador de dicho agente.
   * @param u - La url que se le proporciona para buscar.
   * @param kw - La lista de keywords.
   */
  public AgenteBusqueda(Agente p, LogFile m, Pizarra pi, String i, URL u, String[] kw, double tmp) {
   
    // Parametros:
    id      = i;
    url     = u;
    keywords   = kw;
    log      = m;
    pizarra   = pi;
    padre    = p;
    temperatura = tmp;
   
    // Solo incialización:
    codigo       = "";
    texto       = "";
    ocurrenciasKW  = new int[keywords.length];
    vinculos    = new ArrayList<String>();
    vinculosNuevos  = new ArrayList<String>();
    hijos      = new ArrayList<AgenteBusqueda>();
   
  }
 
 
  /**
   * Extrae el código de la URL dada y lo guarda en un String.
   * @throws IOException
   */
  private void cogeCodigo() throws IOException {

    BufferedReader in;
    in = new BufferedReader(new InputStreamReader(url.openStream()));
     
    while (in.ready()) {
      // Leemos linea linea y concatenamos:
      codigo += in.readLine();
    }

  }
 
  /**
   * Utiliza expresiones regulares para extraer los vínculos del código de la página.
   *
   *
   */
  private void buscaVinculos() {
   
    // Primero extraemos las tags que se corresponden con vínculos:
    Pattern patTags = Pattern.compile(REGEX_TAG_VINCULOS, Pattern.CASE_INSENSITIVE);
    Matcher matTags = patTags.matcher(codigo);
   
    // Las concatenamos en esta cadena:
    String tags = "";
   
    while (matTags.find()) {
      tags += matTags.group();
    }
   
    // Ahora extraemos el vínculo en sí de cada tag.
    Pattern patVinculos = Pattern.compile(REGEX_VINCULOS, Pattern.CASE_INSENSITIVE);
    Matcher matVinculos = patVinculos.matcher(tags);
       
    while (matVinculos.find()) {
      String v = matVinculos.group();
      vinculos.add(v.substring(1,v.length()-1));
    }
  }
 
 
  /**
   * Extrae el texto a partir del código de la URL
   */
  private void extraeTexto() {
   
    texto = codigo.replaceAll(REGEX_TEXTO, "");
  }
 
 
  /**
   * Busca ocurrencias en el texto para cada keyword.
   * ALmacena el resultado en el vector de ocurrencias.
   */
  private void buscaKeywords() {
   
    // PAra cada keyword hacemos amtching y guardamos las ocurrencias.
    for (int i = 0; i < keywords.length; i++) {

      Pattern pat = Pattern.compile(keywords[i], Pattern.CASE_INSENSITIVE);

      Matcher mat = pat.matcher(texto);
     
      ocurrenciasKW[i] = 0;
     
      while (mat.find())
        ocurrenciasKW[i]++;
     
    }
  }
 
 
  /**
   * Comprobamos mediante la pizarra que los vínculos no estaban visitados:
   */
  private void compruebaVinculos() {
   
    // Para cada vínculo...
    for (String v:vinculos) {
     
     
      // comprobamos si dicho vínculo no ha sido antes visitado:
      if (pizarra.quieroVisitar(v)) {
       
        vinculosNuevos.add(v);
       
      }
    }
  }
 
 
 
  /**
   * Lanza el hilo y ejecuta la función del agente:
   */
  @Override
  public void run() {
   
      // LOG: Mensajes de Log iniciales:
      log.escribir(String.format("\n[1](Creacion)\t Agente %s:\t He sido creado.", id));           
      log.escribir(String.format("\n[2](URL)\t Agente %s:\t Adquiriendo código de %s.", id, url.toExternalForm()));
     
      try {
       
        // Obtenemos el código:
        cogeCodigo();
     
        // Extraemos el texto:
        extraeTexto();
       
        // Buscamos las keywords:
        buscaKeywords();
       
       
        // Analizamos los resultados de la busqueda:
       
        // LOG: Vamos generando un mensaje Log para mostrarlas:
        String ocu = String.format("\n[3](Ocurr)\t Agente %s: \t found: ", id);   
       
        // Para cada keyword componemos el mensaje en sí:
        for (int i = 0; i < keywords.length; i++) {   
         
          // LOG:
           ocu += String.format("%s(%d), ", keywords[i], ocurrenciasKW[i]);
       
          
           // Solución encontrada: También si las ocurrencias  para esta keyword exceden el mínimo, debemos comunicarselo a nuestro padre para que se lo vayamos enviando a la interfaz:
           if (ocurrenciasKW[i] >= MINIMO_OCURRENCIAS)
             padre.mensaje(new Mensaje("sol", new String[]{String.valueOf(keywords[i]), String.valueOf(ocurrenciasKW[i]), url.toExternalForm()}));
        }
       
        // Si hay alguna ocurrencia nos calentamos
        boolean heat = false;
        for (int i:ocurrenciasKW) {
          if (i >0)
            heat = true;
        }
        if (heat)
          temperatura = Math.max(TEMP_MAX, temperatura + TEMP_CTE_CAL);
       
        // LOG: finalmente imprimimos el mensjae de log:
        log.escribir(ocu);
       
       
       
        // Extraemos los vínculos:
        buscaVinculos();
         
       
        // Comprobamos qué vinculos son nuevos:
        compruebaVinculos();
       
       
        // LOG: Mensaje de log para mosrar el número de vínculos y cuales son nuevos.
        log.escribir(String.format("\n[4](Vinculos)\t Agente %s:\t Tengo %d vinculos de los cuales %d ya estan visitados.", id, vinculos.size(), vinculos.size()-vinculosNuevos.size()));

       
       
       
        ///////////////////////////////////////////////
        //
        // A continuación activar el método para generar la descendencia deseado:
       
        generarDescendenciaTemp();
       
        // generarDescendencia1();
       
       
       
       
        // LOG: Mensaje de log para indicar el volumen de la replicacion de este agente:
        if (hijos.isEmpty()) {
          log.escribir(String.format("\n[5](Clonar)\t Agente %s:\t No me voy a clonar. Temperatura = %f.", id, temperatura));
        } else {
          log.escribir(String.format("\n[5](Clonar)\t Agente %s:\t Me voy a clonar %d veces. Temperatura = %f.", id, hijos.size(), temperatura));
        }
       
       
        // Lanzamos nuestros hijos:
        for (AgenteBusqueda a:hijos)
          a.start();
           
 
        // Final del agente:
           
        // Nos quedaremos activos hasta que nuestros hijos hayan terminado, para poder escuchar y pasar mensajes:
        hijosActivos = hijos.size();
                         
        // Pasamos el control a un monitor interno para controlar los hijos que nos queden:
        seguir();
       
     
      // Control de excepciones para el caso de un mal uso del fichero:
      } catch (IOException e1) {
        // LOG: Si no podemos descargar el código mostramos este error:
        log.escribir(String.format("\n[2](URL)\t Agente %s:\t URL no disponible.", id));
     
     
      // Llegados a este punto el agente muere:
     
      // LOG: lo escribe en el log y
      log.escribir(String.format("\n[6](Muerte)\t Agente %s:\t He terminado, chao.", id));
     
      // Antes envia un mensaje a su padre para comunicarselo:
        padre.mensaje(new Mensaje("fin", null));
  }

 
 
  /**
   * METODOS REFERENTES A COMUNICACIÓN:
   */
 
  /**
   * Este método se utiliza para que el agente no muera hasta que todos sus hijos hayan terminado.
   * Se espera a que todos sus hijos hayan terminado y mientras queda a la espera.
   */
  public synchronized void seguir() {
    while (hijosActivos != 0) {
      try {
        wait()
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
 
 
  /**
   * MÉTODO PARA OBTENER MENSAJES DE OTROS AGENTES Y PROCESARLOS:
   *
   */
  @Override
  public synchronized void mensaje(Mensaje msg) {
   
   
    // Comprobamos que el código del mensaje nos sea reconocido, en caso contrario lo ignoramos:
   
    // Mensajes de fin para comunicarle a tu padre que has terminado y no tienes descendencia:
    if (msg.codigo.equals("fin")) {
      hijosActivos--;     
      notify();
     
     
    // Mensaje para pasar una solución encontrada (o redirigida por tu hijo) hacia arriba:
    } else if (msg.codigo.equals("sol")) {
      padre.mensaje(msg);
    }

  }




    //////////////////////////////////////////////////////////////////////////////////////////////
    //
    //    AQUÍ PODEMOS PONER LOS MÉTODOS DE GENERAR LA DESCENDENCIA QUE VAYAMOS HACIENDO:
    //
    //
    //
   
  /*
   * Los metodos para generar descendencia deben tomar la lista de vinculosNuevos y a partir de los mismos y del resto de atributos del agente
   * que se consideren relevantes introducir nuevos agentes en la lista "hijos", luego el programa se encargará de lanzar dichos hijos.
   *
   * Se ruega que se comente que hace cada metodo y que si indica si lleva a cabo una búsqueda infinita.
   *
   */
 
 
  /**
   * Genera la descendencia incondicionalmente.
   *
   *
   */
  private void generarDescendenciaTrivial() {

    // Un contador para ir construyendo los identificadores de los hijos a partir del nuestro.
    int i = 1;
   
    // Para cada vínculo nuevo en la lista creamos un hijo:
    for (String v:vinculosNuevos) {

      try {
        // Creamos un nuevo hijo:
        hijos.add(new AgenteBusqueda(this, log, pizarra, id+"-"+String.valueOf(i), new URL(v), keywords, 0));
        i++;
       
      } catch (MalformedURLException e) {
        e.printStackTrace();
     
    }
  }
 
 
  /**
   * Genera descendencia acotando la profundidad del árbol a la constante PROFUNDIDAD_MAXIMA
   * Cuando un agente se encuentr en el nivel d = PROFUNDIDAD_MAXIMA no generará ninguna descendencia.
   *
   */
  private void generarDescendencia1() {
   
 
    if (id.split("-").length < PROFUNDIDAD_MAXIMA) {
 
      int i = 1; // Un contador para los identificadores de los hijos:
     
      // Para cada vínculo nuevo creamos un hijo:
      for (String v:vinculosNuevos) {

        try {
          // En cuyo caso creamos un nuevo agente hijo, concatenando nuestro id al que le toque:
          hijos.add(new AgenteBusqueda(this, log, pizarra, id+"-"+String.valueOf(i), new URL(v), keywords, 0));
          i++;
         
        } catch (MalformedURLException e) {
          e.printStackTrace();
       
      }
    }
  }
 
  private void generarDescendenciaTemp() {
   
   
    if (!(temperatura == 0)) {
 
      int i = 1; // Un contador para los identificadores de los hijos:
     
      // Para cada vínculo nuevo creamos un hijo:
      for (String v:vinculosNuevos) {

        try {
          // En cuyo caso creamos un nuevo agente hijo, concatenando nuestro id al que le toque:
          hijos.add(new AgenteBusqueda(this, log, pizarra, id+"-"+String.valueOf(i), new URL(v), keywords, Math.max(0, temperatura-TEMP_CTE_ENFR)));
          i++;
         
        } catch (MalformedURLException e) {
          e.printStackTrace();
       
      }
    }
  }

}
TOP

Related Classes of practicas.AgenteBusqueda

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.