/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.test.xml;

import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import junit.framework.TestCase;
import org.jboss.logging.Logger;
import org.jboss.test.xml.person.Address;
import org.jboss.test.xml.person.Person;
import org.jboss.xb.binding.DtdMarshaller;
import org.jboss.xb.binding.MappingObjectModelFactory;
import org.jboss.xb.binding.MappingObjectModelProvider;
import org.jboss.xb.binding.Marshaller;
import org.jboss.xb.binding.SimpleTypeBindings;
import org.jboss.xb.binding.TypeConverter;
import org.jboss.xb.binding.Unmarshaller;
import org.jboss.xb.binding.UnmarshallerFactory;


/**
 *
 * @version <tt>$Revision: 1.2.2.4 $</tt>
 * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
 */
public class MappingTestCase
   extends TestCase
{
   private static final Logger log = Logger.getLogger(MappingTestCase.class);
   
   public MappingTestCase(String name)
   {
      super(name);
   }

   public void testUnmarshalling() throws Exception
   {
      Reader xmlReader = new FileReader("resources/xml/person.xml");

      Person person = unmarshalPerson(xmlReader);
      xmlReader.close();

      assertNotNull("Person is null", person);
      assertEquals(person.getFirstName(), "Vasiliy");
      assertEquals(person.getLastName(), "Poupkin");
      assertEquals(person.getDateOfBirth(), TypeConverter.JAVA_UTIL_DATE.unmarshal("1980-01-01"));

      assertEquals(person.getPhones(), Arrays.asList(new Object[]{"01", "02"}));

      ArrayList list = new ArrayList();
      Address addr1 = new Address();
      addr1.setStreet("prosp. Rad. Ukr. 11A, 70");
      list.add(addr1);
      addr1 = new Address();
      addr1.setStreet("Sky 7");
      list.add(addr1);
      assertEquals(person.getAddresses(), list);
   }

   public void testMarshalling() throws Exception
   {
      log.debug("<test-mapping-marshalling>");

      final Person person = Person.newInstance();
      StringWriter xmlOutput = new StringWriter();

      InputStream is = getResource("xml/person.dtd");
      Reader dtdReader = new InputStreamReader(is);

      // create an instance of DTD marshaller
      Marshaller marshaller = new DtdMarshaller();

      // map publicId to systemId as it should appear in the resulting XML file
      marshaller.mapPublicIdToSystemId("-//DTD Person//EN", "resources/xml/person.dtd");

      // create an instance of ObjectModelProvider with the book instance to be marshalled
      MappingObjectModelProvider provider = new MappingObjectModelProvider();
      provider.mapFieldToElement(Person.class, "dateOfBirth", "", "date-of-birth", SimpleTypeBindings.JAVA_UTIL_DATE);

      // marshal the book
      marshaller.marshal(dtdReader, provider, person, xmlOutput);

      // close DTD reader
      dtdReader.close();

      final String xml = xmlOutput.getBuffer().toString();
      log.debug("marshalled: " + xml);

      // check unmarshalled person
      Person unmarshalled = unmarshalPerson(new StringReader(xml));
      assertEquals(person, unmarshalled);

      log.debug("</test-mapping-marshalling>");
   }

   private Person unmarshalPerson(Reader xmlReader)
      throws Exception
   {
      MappingObjectModelFactory factory = new MappingObjectModelFactory();
      factory.mapElementToClass("person", Person.class);
      factory.mapElementToField("date-of-birth", Person.class, "dateOfBirth", SimpleTypeBindings.JAVA_UTIL_DATE);
      factory.mapElementToClass("phones", ArrayList.class);
      factory.mapElementToClass("addresses", ArrayList.class);
      factory.mapElementToClass("address", Address.class);

      Unmarshaller unmarshaller = UnmarshallerFactory.newInstance()
            .newUnmarshaller();

      return (Person)unmarshaller.unmarshal(xmlReader, factory, null);
   }

   private static InputStream getResource(String name)
   {
      InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
      if(is == null)
         throw new IllegalStateException("Resource not found: " + name);
      return is;
   }
}