/*
 * Copyright (C) 2007 JasperSoft http://www.jaspersoft.com
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed WITHOUT ANY WARRANTY; and without the 
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see http://www.gnu.org/licenses/gpl.txt 
 * or write to:
 * 
 * Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330,
 * Boston, MA  USA  02111-1307
 */
 
#include "marshaller.h"
#include <libxml/xmlwriter.h>

int jasperserver_resource_descriptor_marshal(xmlTextWriterPtr writer, jasperserver_resource_descriptor_t *res);
int jasperserver_resource_property_marshal(xmlTextWriterPtr writer, jasperserver_resource_property_t *res);
int jasperserver_parameter_marshal(xmlTextWriterPtr writer, jasperserver_parameter_t *param);


int jasperserver_request_marshal(jasperserver_request_t *request, jasperserver_string_t *buffer)
{
     int rc;
     xmlTextWriterPtr writer;
     xmlBufferPtr buf;
     jasperserver_argument_t *argument;
     jasperserver_resource_descriptor_t *res;

     /* Create a new XML buffer, to which the XML document will be
     * written */
     buf = xmlBufferCreate();
     if (buf == NULL) {
        printf("testXmlwriterMemory: Error creating the xml buffer\n");
        return -1;
     }    
     
     /* Create a new XmlWriter for memory, with no compression.
     * Remark: there is no compression for this kind of xmlTextWriter */
     writer = xmlNewTextWriterMemory(buf, 0);
     if (writer == NULL) {
        printf("testXmlwriterMemory: Error creating the xml writer\n");
        return -1;
     }
     xmlTextWriterSetIndent(writer, 1);
     xmlTextWriterSetIndentString(writer, BAD_CAST "  ");
     /* Start the document with the xml default for the version,
     * encoding ISO 8859-1 and the default for the standalone
     * declaration. */
    rc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
    if (rc < 0) {
        printf("testXmlwriterMemory: Error at xmlTextWriterStartDocument\n");
        return -1;
    }
    
    /* request tag */
    rc = xmlTextWriterStartElement(writer, BAD_CAST "request");
    if (rc < 0) {
        printf("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
        return -1;
    }
    /* request -> operationName */
    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "operationName",
                                     JS_UTFSTR( request->opertation ));
    if (rc < 0) {
        printf("testXmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
        return -1;
    }
    
    if (JS_NOTNULL( request->locale ))
    {
          rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "locale",
                                      JS_UTFSTR( request->locale ));
          if (rc < 0) {
                printf("testXmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
                return -1;
           }             
    }
    
    for (argument = request->arguments; argument; argument = argument->next)
    {
         rc = xmlTextWriterStartElement(writer, BAD_CAST "argument");
         if (rc < 0) {
            printf("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
            return -1;
         }
         
         /* argument -> name */
        rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name", JS_UTFSTR(argument->name) );
        if (rc < 0) {
            printf("testXmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
            return -1;
        }
         
         if (JS_NOTNULL(argument->value))
         {
             rc = xmlTextWriterWriteCDATA(writer, JS_UTFSTR(argument->value));
             if (rc < 0) {
                printf("xmlTextWriterWriteCDATA: Error at xmlTextWriterWriteCDATA\n");
                return -1;
             }
             
         }

         rc = xmlTextWriterEndElement(writer); // End element argument
         if (rc < 0) {
            printf("testXmlwriterMemory: Error at xmlTextWriterEndElement\n");
            return -1;
         }
     }  
     
     for (res = request->resource; res; res = res->next)
     {
        rc = jasperserver_resource_descriptor_marshal(writer, res); // End element request
        if (rc < 0) {
           printf("jasperserver_resource_descriptor_marshall: Error at jasperserver_resource_descriptor_marshall\n");
           return -1;
        }
     }
     
     rc = xmlTextWriterEndElement(writer); // End element request
     if (rc < 0) {
        printf("testXmlwriterMemory: Error at xmlTextWriterEndElement\n");
        return -1;
     }
     rc = xmlTextWriterEndDocument(writer);
     if (rc < 0) {
        printf("testXmlwriterMemory: Error at xmlTextWriterEndDocument\n");
        return -1;
     }

     xmlFreeTextWriter(writer);   
     jasperserver_string_append(buffer, BAD_CAST buf->content);
     return buffer->buffer->use;
}

/**
   Create an xml string representing the resource_descriptor.
   The xml is encoded in  UTF8 and is stored in buffer.
   
   \param writer must be not NULL.
   \param res must be not NULL. It is the resource_descriptor to save

   \return the length of buffer or -1 if an error occurs.
   
   \code
   <!ELEMENT resourceDescriptor (label, description?, resourceProperty*, resourceDescriptor*, parameter*)>
   <!ATTLIST resourceDescriptor
        name CDATA #REQUIRED
	    wsType CDATA #REQUIRED
	    uriString CDATA #REQUIRED
	    isNew ( true | false ) false>
   \endcode
*/
int jasperserver_resource_descriptor_marshal(xmlTextWriterPtr writer, jasperserver_resource_descriptor_t *res)
{
    int rc = 0;
    jasperserver_resource_property_t *resourceProperty = NULL;
    jasperserver_resource_descriptor_t *resourceDescriptor = NULL;
    jasperserver_parameter_t *parameter = NULL;
    
    /* resourceDescriptor tag */
    rc = xmlTextWriterStartElement(writer, BAD_CAST "resourceDescriptor");
    if (rc < 0) {
        printf("xmlTextWriterStartElement resourceDescriptor: Error at xmlTextWriterStartElement\n");
        return -1;
    }
    
    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name", JS_UTFSTR( res->name ) );
    if (rc < 0) {
        printf("xmlTextWriterWriteAttribute name: Error at xmlTextWriterWriteAttribute\n");
        return -1;
    }
    
    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "wsType", JS_UTFSTR(res->wsType) );
    if (rc < 0) {
        printf("xmlTextWriterWriteAttribute wsType: Error at xmlTextWriterWriteAttribute\n");
        return -1;
    }
    
    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "uriString", JS_UTFSTR(res->uriString) );
    if (rc < 0) {
        printf("xmlTextWriterWriteAttribute uriString: Error at xmlTextWriterWriteAttribute\n");
        return -1;
    }
    
    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "isNew",  BAD_CAST ((res->isNew) ?  "true" : "false") );
    if (rc < 0) {
        printf("xmlTextWriterWriteAttribute isNew: Error at xmlTextWriterWriteAttribute\n");
        return -1;
    }
    
    rc = xmlTextWriterWriteElement(writer, BAD_CAST "label", JS_UTFSTR(res->label) );
    if (rc < 0) {
        printf("xmlTextWriterWriteElement label: Error at xmlTextWriterWriteElement\n");
        return -1;
    }
    
    if (JS_NOTNULL( res->description ))
    {
          rc = xmlTextWriterWriteElement(writer, BAD_CAST "description",
                                      JS_UTFSTR(res->description));
          if (rc < 0) {
                printf("xmlTextWriterWriteElement: Error at xmlTextWriterWriteElement\n");
                return -1;
           }             
    }
    
    for (resourceProperty = res->properties; resourceProperty; resourceProperty = resourceProperty->next)
     {
        rc = jasperserver_resource_property_marshal(writer, resourceProperty); // End element request
        if (rc < 0) {
           printf("jasperserver_resource_property_marshall: Error at jasperserver_resource_property_marshall\n");
           return -1;
        }
     }
     
   for (resourceDescriptor = res->children; resourceDescriptor; resourceDescriptor = resourceDescriptor->next)
     {
        rc = jasperserver_resource_descriptor_marshal(writer, resourceDescriptor); // End element request
        if (rc < 0) {
           printf("jasperserver_resource_descriptor_marshall: Error at jasperserver_resource_descriptor_marshall\n");
           return -1;
        }
     }
     
   for (parameter = res->parameters; parameter; parameter = parameter->next)
     {
        rc = jasperserver_parameter_marshal(writer, parameter); // End element request
        if (rc < 0) {
           printf("jasperserver_parameter_marshall: Error at jasperserver_parameter_marshall\n");
           return -1;
        }
     }
        
   rc = xmlTextWriterEndElement(writer); // End element resourceDescriptor
    if (rc < 0) {
        printf("xmlTextWriterStartElement resourceDescriptor: Error at xmlTextWriterStartElement\n");
        return -1;
    }
    
   return 0; 
}


/**
   Create an xml string representing the resourceProperty.
   The xml is encoded in  UTF8 and is stored in buffer.
   
   \param writer must be not NULL.
   \param res must be not NULL. It is the resourceProperty to save

   \return the length of buffer or -1 if an error occurs.
   
   \code
   <!ELEMENT resourceProperty (value?, resourceProperty*)>
    <!ATTLIST resourceProperty
            name CDATA #REQUIRED
    >
   \endcode
*/
int jasperserver_resource_property_marshal(xmlTextWriterPtr writer, jasperserver_resource_property_t *res)
{
    int rc = 0;
    jasperserver_resource_property_t *resourceProperty = NULL;
    /* resourceDescriptor tag */
    rc = xmlTextWriterStartElement(writer, BAD_CAST "resourceProperty");
    if (rc < 0) {
        printf("xmlTextWriterStartElement resourceDescriptor: Error at xmlTextWriterStartElement\n");
        return -1;
    }
    
    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name", JS_UTFSTR( res->name ) );
    if (rc < 0) {
        printf("xmlTextWriterWriteAttribute name: Error at xmlTextWriterWriteAttribute\n");
        return -1;
    }
    
    if (JS_NOTNULL( res->value ))
    {
          rc = xmlTextWriterWriteElement(writer, BAD_CAST "value", JS_UTFSTR(res->value));
          if (rc < 0) {
                printf("xmlTextWriterWriteElement value: Error at xmlTextWriterWriteElement\n");
                return -1;
           }             
    }
    
    for (resourceProperty = res->properties; resourceProperty; resourceProperty = resourceProperty->next)
     {
        rc = jasperserver_resource_property_marshal(writer, resourceProperty); // End element request
        if (rc < 0) {
           printf("jasperserver_resource_property_marshall: Error at jasperserver_resource_property_marshall\n");
           return -1;
        }
     }
     
    rc = xmlTextWriterEndElement(writer);  // End element resourceProperty
    if (rc < 0) {
        printf("xmlTextWriterStartElement resourceDescriptor: Error at xmlTextWriterStartElement\n");
        return -1;
    }
   
   return 0; 
}



/**
   Create an xml string representing the parameter.
   The xml is encoded in  UTF8 and is stored in buffer.
   
   \param writer must be not NULL.
   \param res must be not NULL. It is the parameter to save

   \return the length of buffer or -1 if an error occurs.
   
   \code
   <!ELEMENT parameter (#PCDATA)>
    <!ATTLIST parameter
            name CDATA #REQUIRED
            isListItem ( true | false ) false
    >
   \endcode
*/
int jasperserver_parameter_marshal(xmlTextWriterPtr writer, jasperserver_parameter_t *param)
{
    int rc = 0;
    /* parameter tag */
    rc = xmlTextWriterStartElement(writer, BAD_CAST "parameter");
    if (rc < 0) {
        printf("xmlTextWriterStartElement resourceDescriptor: Error at xmlTextWriterStartElement\n");
        return -1;
    }
    
    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name", JS_UTFSTR( param->name ) );
    if (rc < 0) {
        printf("xmlTextWriterWriteAttribute name: Error at xmlTextWriterWriteAttribute\n");
        return -1;
    }
    
    if (param->isListItem)
    {
        rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "isListItem", BAD_CAST "true" );
        if (rc < 0) {
            printf("xmlTextWriterWriteAttribute isListItem: Error at xmlTextWriterWriteAttribute\n");
            return -1;
        }
    }
    
    if (JS_NOTNULL( param->value ))
    {
          rc = xmlTextWriterWriteCDATA(writer, JS_UTFSTR(param->value));
          if (rc < 0) {
                printf("xmlTextWriterWriteElement value: Error at xmlTextWriterWriteElement\n");
                return -1;
           }             
    }
    
    rc = xmlTextWriterEndElement(writer);  // End element parameter
    if (rc < 0) {
        printf("xmlTextWriterStartElement parameter: Error at xmlTextWriterStartElement\n");
        return -1;
    }
   
   return 0; 
}

