/////////////////////////////////////////////////////////////////////////
//
// © Institute for Software Science, University of Vienna, 2004
//
// Copyright in this software belongs to Institute for Software Science, 
// University of Vienna, Nordbergstrasse 15/C/3, 1090 Vienna, Austria
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//	Created By :		Nikolay Terziev
//	Created Date :		2004/04/20
//	Created for Project:	GEMSS
//
////////////////////////////////////////////////////////////////////////
//
// Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//	Last commit info:	$Author: niki $
//					$Date: 2004/07/21 14:14:40 $
//					$Revision: 1.4 $
//
/////////////////////////////////////////////////////////////////////////

package at.ac.univie.iss.descriptors.qos;


import java.io.StringReader;
import java.io.StringWriter;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Level;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.UnmarshalException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import at.ac.univie.iss.descriptors.qos.jaxb.reqdesc.*; 

/**
*	A Request Descriptor is an XML document containing application specific
*	meta information about a service request. This meta information may 
*	inlcude mesh size, image resolution, etc.
*	A <code>RequestDescriptorImpl</code> implements the interface <code>
*	RequestDescriptor</code> which represents an XML Request Descriptor in Java. 
*	Internally this class uses JAXB to access the content of the XML Request
*	Descriptor. 
*
*	@author Gerhard Engelbrecht
*	@author Nikolay Terziev
*/
public class RequestDescriptorImpl implements RequestDescriptor {
    
    private static Logger logger = Logger.getLogger("at.ac.univie.iss.descriptors.qos");
    
    private Unmarshaller unmarshaller = null;
    private Marshaller   marshaller = null;
    private ObjectFactory objFactory = null;
    private JAXBContext jc;
    
    private at.ac.univie.iss.descriptors.qos.jaxb.reqdesc.RequestDescriptor requestDescriptor = null;
    
    /**
    *	Creates an empty Request Descriptor.
    */
    public RequestDescriptorImpl() {
    
        try {
         
            jc = JAXBContext.newInstance("at.ac.univie.iss.descriptors.qos.jaxb.reqdesc");
                    
            unmarshaller = jc.createUnmarshaller();
            unmarshaller.setValidating(true);

            marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

            objFactory = new ObjectFactory(); 
            
            requestDescriptor = objFactory.createRequestDescriptor();
            
            requestDescriptor.setRequestInfo(createRequestInfoType("serviceCategory"));
            
            requestDescriptor.setPerformanceParameters(createPerformanceParametersType());
              
        } catch (JAXBException je) {
        	logger.log(Level.SEVERE, "An error occured while creating a new Request Descriptor (see details below)!", je);
        }  
    }

	/**
	*	Creates a Request Descriptor based on the given XML-based document.
	*/
    public RequestDescriptorImpl(String reqDesc) {
    
        try {
         
            jc = JAXBContext.newInstance("at.ac.univie.iss.descriptors.qos.jaxb.reqdesc");
                    
            unmarshaller = jc.createUnmarshaller();
            unmarshaller.setValidating(true);

            marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

            objFactory = new ObjectFactory(); 
            
            requestDescriptor = (at.ac.univie.iss.descriptors.qos.jaxb.reqdesc.RequestDescriptor) unmarshaller.unmarshal(
                    new StreamSource(new StringReader(reqDesc)));
     
        } catch (UnmarshalException ue) {  
            
        	logger.log(Level.SEVERE, "An error occured while creating a new Request Descriptor based on a given String (see details below)!", ue);

        } catch (JAXBException je) {

        	logger.log(Level.SEVERE, "An error occured while creating a new Request Descriptor based on a given String (see details below)!", je);
            
        } catch (Exception e) {

        	logger.log(Level.SEVERE, "An error occured while creating a new Request Descriptor based on a given String (see details below)!", e);
        }  
               
    }
    
    public void setServiceCategory(String serviceCategory) {
     
        RequestInfoType requestInfo = requestDescriptor.getRequestInfo();
      
        if (requestInfo != null) {
          
            requestInfo.setServiceCategory(serviceCategory); 
        }
       
    }
    
    public String getServiceCategory() {
         
        RequestInfoType requestInfo = requestDescriptor.getRequestInfo();
      
        if (requestInfo != null) {
          
            return requestInfo.getServiceCategory(); 
        }
      
        return null;    
    }
   
    public void setPerformanceParameter(String name, String value) {
    
        PerformanceParametersType performanceParametersType = requestDescriptor.getPerformanceParameters();
        
        List listParam = performanceParametersType.getPerformanceParameter();
        Iterator iter = listParam.iterator();
      
        while (iter.hasNext()) {
            PerformanceParameterType perfParam = (PerformanceParameterType) iter.next();

            if (perfParam.getName().equals(name)) {
                perfParam.setValue(value);
                return;
            }    
        }
      
        try {
            PerformanceParameterType newParam = objFactory.createPerformanceParameterType();

            newParam.setName(name);
            newParam.setValue(value);
            listParam.add(newParam);
        } catch (JAXBException je) {

        	logger.log(Level.SEVERE, "An error occured while setting a performance parameter (see details below)!", je);
        } 
    }
    
    public String getPerformanceParameter(String name) {
        String value = null;
        PerformanceParametersType performanceParametersType = requestDescriptor.getPerformanceParameters();
 
        if (performanceParametersType == null) { 
            return null;
        }
      
        List listParam = performanceParametersType.getPerformanceParameter();
        Iterator iter = listParam.iterator();
      
        while (iter.hasNext()) {
            PerformanceParameterType perfParam = (PerformanceParameterType) iter.next();

            if (perfParam.getName().equals(name)) {
                return perfParam.getValue();
            }
        }
        return value;
    }

    public String toString() {
            
        StringWriter slaWriter = new StringWriter(); 
            
        try {
             
            marshaller.marshal(requestDescriptor, slaWriter);
             
            return slaWriter.toString();
           
        } catch (javax.xml.bind.MarshalException me) { 

        	logger.log(Level.SEVERE, "An error occured while converting the Request Descriptor to a String (see details below)!", me);

        } catch (JAXBException je) {

        	logger.log(Level.SEVERE, "An error occured while converting the Request Descriptor to a String (see details below)!", je);
        }
        return null;  
    }
  
    // Create Methods
    
    private RequestInfoType createRequestInfoType(String serviceCategory) {
     
        RequestInfoType requestInfoType = null;

        try {
            requestInfoType = objFactory.createRequestInfoType();
            requestInfoType.setServiceCategory(serviceCategory);
      
        } catch (JAXBException je) {

        	logger.log(Level.SEVERE, "An error occured while creating the the Request Descriptors Info section (see details below)!", je);
        }
     
        return requestInfoType;
    }

    private PerformanceParametersType createPerformanceParametersType() {
     
        PerformanceParametersType performanceParametersType = null;

        try {
            performanceParametersType = objFactory.createPerformanceParametersType(); 
      
        } catch (JAXBException je) {

        	logger.log(Level.SEVERE, "An error occured while creating the the Request Descriptors performance parameters section (see details below)!", je);
        }
  
        return performanceParametersType; 
    }
  
}
