/**
 * pSHIELD
 * Service Discovery
 *
 @author Vincenzo Suraci
 @author Silvano Mignanti
 * Department of System and Computer Science (DIS)
 * University of Rome "Sapienza"
 * Via Ariosto, 25
 * 00184, Rome, IT
 *
 * phone: +39 340 156 22 58 / +39 329 11 38 610
 * email: vincenzo.suraci@dis.uniroma1.it / silvano.mignanti@dis.uniroma1.it
 
 *
 * Created on 16-May-2007
 * Version 1.0
 
 */

package eu.artemis.shield.overlay.securityagent.impl;

/**

 
 * The present class shows how a pSHIELD 2 OSGi component
 * could use the potentiality offered by the pSHIELD 2
 * Service Discovery Framework. It interfaces with the 
 * Generic Discovery Manager to discover the services
 * available in the (pSHIELD 2) network.  
 */

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import eu.artemis.shield.discovery.gdm.interfaces.IGenericDiscovery;

import eu.artemis.shield.discovery.pdm.IService;
import eu.artemis.shield.discovery.pdm.IServiceList;
import eu.artemis.shield.discovery.pdm.IServiceProperty;
import eu.artemis.shield.discovery.pdm.IServicePropertyList;

import eu.artemis.shield.overlay.securityagent.ISecurityAgent;
import eu.artemis.shield.overlay.securityagent.impl.SAGUI;
import eu.artemis.shield.overlay.semanticknowledge.ISemanticKnowledge;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.Hashtable;


public class SA implements ISecurityAgent
{
  private BundleContext bc;
  private IGenericDiscovery gd = null;
  private SAGUI gui = null;
  public List fileOWL = new LinkedList()
  public ISemanticKnowledge sk;
  public Hashtable h_bundle = new Hashtable();

  public SA(BundleContext bc)
  {
    this.bc = bc;
    
    gui = new SAGUI(bc, this);
    gui.setVisible(true);
                
  }    
  
  public Vector serviceTypeDiscovery()
  {
    Vector types_vector = new Vector();
    try
    {
      gui.append("Discovering Service Types ...");
      ServiceReference[] gdmList = findGenericDiscoveryModuleImplementations();    
      if (gdmList != null)
      {
        /*
         * We ignore the possibility to have more than one GDM implementation.
         * JUST USE THE FIRST ONE...
         */                  
        gd = (IGenericDiscoverybc.getService(gdmList[0]);        
        
        /*
         * We are ready to start the discovery process!
         */
        
        // Obatin in the proper way the user agent VIDID
        String vid = null;
        
        /*
         * LET pSHIELD DISCOVER THE TYPES OF SERVICES
         */
        
        LinkedList ll = gd.findServiceTypes(vid);
        
        if (ll != null)
        {          
          if (ll.isEmpty())
          {
            // NO SERVICES HAVE BEEN DISCOVERED
            gui.append("No Service Types Found !");
          }
          else
          {

            Iterator it = ll.iterator();
            while (it.hasNext())
            {        
              String types = (String)it.next();
              types_vector.addtypes );
            }
          }
        
        }
        else
        {
          // NO SERVICE TYPES HAVE BEEN DISCOVERED
          gui.append("No Service Types Found !");
        }
      }
      else
      {
        /*
         * It was not possible to find a suitable implementation of IGenericDiscovery 
         */
        gui.append("No Bundles implement the IGenericDiscovery interface!\n");
      }
      gui.append("Done.");
      return types_vector;
    
    }    
    catch (Exception e)
    {
      /*
       * Something went wrong!
       * It was not possible to find a suitable implementation of IGenericDiscovery 
       */
      gui.append(e.getMessage());
      return types_vector;
    }
  }
  
  /**
   * This function takes a URL and a service Type and create the Service URL
   *
   @param type service type
   @param url URL
   @return Service URL
   */
  private String serviceurl(String type, String url)
  {
    
    int index = type.lastIndexOf(":");
    if (index > 0)
    {
      String protocol = type.substring(index+1);
      if (url.startsWith(protocol))
      {
        String serviceurl = type + url.substring(protocol.length());
        return serviceurl;
      }
      else
      {
        gui.append("SA.java::serviceurl -> Trying to merge different protocols:\nurl = " + url + "\ntype = " + type);
      }
    }
    return null;
  }
  
  /**
   * This function find the service available for a specified service type
   @param type : the service type to search
   @return : a vector of found services ( with no API bundles )
   @throws PShieldEngineException 
   @throws Exception 
   */
  public Vector serviceDiscoveryString type )  {
    
    return serviceDiscoverytype, null );
    
  
  
  
  /**
   * This function find the service available for a specified service type and an array of keywords to do a better filter
   @param type : the service type to search
   @param kw : an array of keywords to search
   @return : a vector of found services ( with no API bundles )
   @throws PShieldEngineException 
   */
  public Vector serviceDiscoveryString type, String[] kw ) {
    return serviceDiscovery(type, kw, true);
  
  
  /**
   * This function find the service available for a specified service type and an array of keywords to do a better filter 
   @param type : the service type to search
   @param kw : an array of keywords to search
   @param filter_api : set false if you need all the available bundles, true if you want only the API bundles
   @return a vector of found services ( with no API bundles )
   @throws PShieldEngineException 
   @throws Exception 
   */
    
  public Vector serviceDiscoveryString type, String[] kw, boolean filter_api 
  {
      
      Vector discovered_services = new Vector();
      try
      {        
        
        gui.append("Service discovery with a specified service type");
        ServiceReference[] gdmList = findGenericDiscoveryModuleImplementations();
        
        if (gdmList != null)
        {
          /*
           * We ignore the possbility to have more than one GDM implementation.
           * JUST USE THE FIRST ONE...
           */                  
          gd = (IGenericDiscoverybc.getService(gdmList[0]);
          /*
           * We are ready to start the discovery process!
           */
          
          // Obatin in the proper way the user agent VIDID
          String vid = null;
        
          
          /*
           * Set an array of keywords, useful to better filter 
           * the services
           */  
          if kw == null 
            kw = new String[0];
          
          for(int i = 0; i<kw.length; i++)
          {
            gui.append("KEYWORDS " + i + "--> " + kw[i].toString() "\n");
          }
          /*
           * LET pSHIELD DISCOVER THE SERVICES
           */
          
          gui.append("Looking for Services ...");
          
          String CDQL =         
            "SELECT default" +
            "FROM default" +
            "SERVICETYPE " + type +
            "LANGUAGE en_gb" +
            "WHERE " +
            "USING slp";
          String SPARQL = "";
          LinkedList query_output = null;
          IServiceList sl = gd.findServices(CDQL, SPARQL, query_output);        
          
          if sl != null )
          {           
            if sl.isEmpty() )
            {
              // NO SERVICES HAVE BEEN DISCOVERED
              gui.append("No services found !");
            }
            else
            {                                        
                for (int i = 0; i < sl.size(); i++)
                {                
                  try
                  {
                    IService s = sl.getService(i);                  
                    String url = s.getOWLSURL();
                    System.out.println("service URL #" + i + " = " + url);
                    IServicePropertyList spl = s.getProperties();
                    Hashtable ht = new Hashtable();
                    String owl = null;
                    for (int j=0; j<spl.size(); j++)
                    {
                      try
                      {
                        
                        Object obj = null;
                        IServiceProperty sp = spl.getServiceProperty(j);
                        System.out.print("> attribute #" + j + " --> " + sp.getName() "=");
                        
                        //sp.getName() --> attribute's name
                        
                        Vector values = sp.getValues();
                        if (values != null)
                        {
                          
                          for (int k=0; k<values.size(); k++)
                          {
                            obj = values.get(k);
                            if (sp.getName().equals("ontologyURI")){
                              System.out.println("Ottengo le chiavi" + obj + " " + sp.getName() " " + values.toString());
                              owl = obj.toString();
                            }
                          
                          }

                        }
                        ht.put(sp.getName(), values);
                        
                        
                        System.out.println("Valore attributo" + values);                      
                      }
                      
                    
                      catch (IndexOutOfBoundsException ioobe)
                      {
                        ioobe.printStackTrace();
                      }                    
                    }
                    
                    if (owl != null && ht != null){

                        h_bundle.put(owl, ht);
                        System.out.println("Numero Bundle" + h_bundle.size() " " + ht.get("Service Name"" " + owl);
                          
                    }
                    
                    if (ht.containsKey("Impl"&& ht.containsKey("Api"))
                    {
                      if (filter_api
                      {                  
                        boolean has_impl = ((Boolean)((Vector)ht.get("Impl")).elementAt(0)).booleanValue();
                        if (has_impldiscovered_services.add(ht);                                  
                      }      
                      else
                      {
                        // Insert an HashTable for each discovered service
                        discovered_services.addht );                    
                      }
                    }                  
                  }
                  catch (IndexOutOfBoundsException ioobe)
                  {
                    ioobe.printStackTrace();
                  }                
                }              
            }
          }
          else
          {
            //NO SERVICES HAVE BEEN DISCOVERED
            gui.append("NO SERVICE FOUND!");          
          }
          
        }
        else
        {
          /*
           * It was not possible to find a suitable implementation of IGenericDiscovery 
           */
          gui.append("No Bundles implement the IGenericDiscovery interface!\n");        
        }            
      }    
      catch (Exception e)
      {
        /*
         * Something went wrong!
         * It was not possible to find a suitable implementation of IGenericDiscovery 
         */
        gui.append(e.getMessage());
        e.printStackTrace();      
      }
      
      
      List l = getServices(11);
      System.out.println("Numero bundle da avviare" + l.size());
      Hashtable prova = getBundle(l);
      
      try
      {
        ServiceReference[] skList = findSemanticKnoledgeImplementations();
        if (skList != null)
        {
          sk = (ISemanticKnowledgebc.getService(skList[0]);
          
          return discovered_services;
        }
        
      }
      catch (Exception e)
      {
        /*
         * Something went wrong!
         * It was not possible to find a suitable implementation of ISemanticKnowledge 
         */
        gui.append(e.getMessage());
      }
      
      return discovered_services;
      
  }
  
  

  /**
   
   @param type
   @param kw
   @param filter_api
   @return The list of OWLfiles of bundles with a SPD level 
   */
  public List getListString type, String[] kw, boolean filter_api )
  {
    
    ServiceReference[] gdmList;
    try {
      gdmList = findGenericDiscoveryModuleImplementations();
      
      if (gdmList != null)
      {
      gd = (IGenericDiscoverybc.getService(gdmList[0]);
      
      String CDQL =         
        "SELECT default" +
        "FROM default" +
        "SERVICETYPE " + type +
        "LANGUAGE en_gb" +
        "WHERE " +
        "USING slp";
      String SPARQL = "";
      LinkedList query_output = null;
      
      IServiceList sl = gd.findServices(CDQL, SPARQL, query_output);        
      
      if sl != null )
      {           
        if sl.isEmpty() )
        {
          // NO SERVICES HAVE BEEN DISCOVERED
          gui.append("No services found !");
        }
        else
        {                                        
            for (int i = 0; i < sl.size(); i++)
            {                
                IService s = sl.getService(i);                  
                String url = s.getOWLSURL();
                IServicePropertyList spl = s.getProperties();
                for (int j=0; j<spl.size(); j++)
                {
                    IServiceProperty sp = spl.getServiceProperty(j);
                    
                    Vector values = sp.getValues();
                    if (values != null)
                    {
                      for (int k=0; k<values.size(); k++)
                      {
                        Object obj = values.get(k);
                        if (obj != null)
                        {
                          if (k > 0System.out.print(",");
                          
                          if (sp.getName().equals("OntologyURI"&& !obj.toString().equals(null))
                          {
                          System.out.println(sp.getName());
                          System.out.print(obj.toString());  
                          System.out.println("Added" " " + obj.toString());
                          fileOWL.add(obj.toString());
                          
                          }
                        }
                      }
                    }
                }
            }
        }
      }
      }
    catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    
    
    return fileOWL;
  }
  
/**
 * This function returns the list of OWL files belonging to the bundles to start
 @param i = security level
 @return List of ontologies belonging to the bundles that have an SPD Level that respect security level i
 */

public List getServices(int i)
{
  
  List services = new LinkedList();
  
  services.add("http://www.owl-ontologies.com/Ontology1300273978.owl#CHAP");
  services.add("http://www.owl-ontologies.com/Ontology1300273978.owl#AES");
  services.add("http://www.owl-ontologies.com/Ontology1300273978.owl#PIN");
  
  return services;      
}
  
/**
 * This function returns an HashMap with type of service and its security level
 @param l List of ontologies
 @return HashMap with type of service and its security level
 */

public HashMap getParameters(List l){
  
  HashMap ht = new HashMap();
  
  ht.put("Authentication"8);
  ht.put("Accounting"2);
  ht.put("Cryptography"1);
  
  return ht;
  
  
}


  /**
   @author Vincenzo Suraci
   
   * This function uses the internal OSGi service discovery to find a suitable implementation
   * of the IGenericDiscovery interface.
   */
  public ServiceReference[] findGenericDiscoveryModuleImplementations() throws Exception
  {
    ServiceReference[] gdmi = null;
    try 
    {
      gdmi = bc.getServiceReferences("eu.artemis.shield.discovery.gdm.interfaces.IGenericDiscovery"null);
    
    catch (Exception e
    {
      throw e;
    }
    return gdmi;
  
  
  /**
   @author Vincenzo Suraci
   
   * This function uses the internal OSGi service discovery to find a suitable implementation
   * of the ISemanticKnoledge interface.
   */
  public ServiceReference[] findSemanticKnoledgeImplementations() throws Exception
  {
    ServiceReference[] gdmi = null;
    try 
    {
      gdmi = bc.getServiceReferences("eu.artemis.shield.overlay.semanticknowledge.ISemanticKnowledge"null);
    
    catch (Exception e
    {
      throw e;
    }
    return gdmi;
  }

  
  
  public void exit()
  {
    /*
     * Close GUI
     */
    gui.setVisible(false);
    gui.dispose();
  }
}