/*
 * Copyright 2003, 2004  The Apache Software Foundation
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.

 */
package org.apache.ws.jaxme.junit;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.apache.ws.jaxme.JMElement;
import org.apache.ws.jaxme.JMUnmarshaller;
import org.apache.ws.jaxme.impl.JAXBContextImpl;
import org.apache.ws.jaxme.impl.JMMarshallerImpl;
import org.apache.ws.jaxme.impl.JMSAXDriver;
import org.apache.ws.jaxme.test.misc.enumeration.AllSimpleTypes;
import org.apache.ws.jaxme.test.misc.enumeration.AllTypesElement;
import org.apache.ws.jaxme.test.misc.enumeration.MyDoubleTypeClass;
import org.apache.ws.jaxme.test.misc.enumeration.MyFloatTypeClass;
import org.apache.ws.jaxme.test.misc.enumeration.MyIntTypeClass;
import org.apache.ws.jaxme.test.misc.enumeration.MyLongTypeClass;
import org.apache.ws.jaxme.test.misc.enumeration.MyShortTypeClass;
import org.apache.ws.jaxme.test.misc.enumeration.MyStringTypeClass;
import org.apache.ws.jaxme.test.misc.enumeration.impl.AllSimpleTypesImpl;
import org.apache.ws.jaxme.test.misc.enumeration.impl.AllTypesElementImpl;
import org.apache.ws.jaxme.test.misc.enumeration.impl.AllTypesElementTypeDriver;
import org.xml.sax.InputSource;


/** Test suite for enumerations generated by <code>xs:enum</code>.
 */
public class EnumerationTest extends BaseTestCase {
	private JAXBContextImpl factory;

	/** Creates a new test instance with the given name.
	 */
	public EnumerationTest(String arg) { super(arg); }

	public void setUp() throws JAXBException {
		factory = (JAXBContextImpl) JAXBContext.newInstance("org.apache.ws.jaxme.test.misc.enumeration");
	}

	private JAXBContextImpl getFactory() {
		return factory;
	}

	private AllSimpleTypes getAllSimpleTypesElement() {
		AllSimpleTypes element = new AllSimpleTypesImpl();
		element.setStringElem(MyStringTypeClass.FOO);
		element.setIntElem(MyIntTypeClass.INT3);
		element.setLongElem(MyLongTypeClass.LONG_NEGATIVE);
		element.setShortElem(MyShortTypeClass.SHORT_POSITIVE);
		element.setDoubleElem(MyDoubleTypeClass.DOUBLE_POSITIVE);
		element.setFloatElem(MyFloatTypeClass.FLOAT_NEGATIVE);
		return element;
	}

	private AllTypesElement getAllTypesElement() throws JAXBException {
		AllTypesElement element = (AllTypesElement) getFactory().getManager(AllTypesElement.class).getElementJ();
		element.setAllSimpleTypesElement(getAllSimpleTypesElement());
		return element;
	}

	private String getAllTypesElementString() {
		AllTypesElementImpl elem = new AllTypesElementImpl();
		String uri = elem.getQName().getNamespaceURI();
		return
		"<ex:AllTypesElement xmlns:ex=\"" + uri + "\">\n" +
		"  <ex:AllSimpleTypesElement>\n" +
		"    <ex:StringElem>FOO</ex:StringElem>\n" +
		"    <ex:IntElem>3</ex:IntElem>\n" +
		"    <ex:LongElem>-23987982739273989</ex:LongElem>\n" +
		"    <ex:ShortElem>3468</ex:ShortElem>\n" +
		"    <ex:DoubleElem>3249239847982.234</ex:DoubleElem>\n" +
		"    <ex:FloatElem>-24234.234</ex:FloatElem>\n" +
		"  </ex:AllSimpleTypesElement>\n" +
		"</ex:AllTypesElement>";
	}

	private void verifyAllSimpleTypesElement(AllSimpleTypes pElement) {
		assertEquals(MyStringTypeClass.FOO, pElement.getStringElem());
		assertEquals("FOO", pElement.getStringElem().getValue());
		assertEquals("FOO", pElement.getStringElem().toString());
		assertEquals(MyIntTypeClass.INT3, pElement.getIntElem());
		assertEquals(3, pElement.getIntElem().getValue());
		assertEquals("INT3", pElement.getIntElem().getName());
		assertEquals("3", pElement.getIntElem().toString());
		assertEquals(MyLongTypeClass.LONG_NEGATIVE, pElement.getLongElem());
		assertEquals(-23987982739273989L, pElement.getLongElem().getValue());
		assertEquals("LONG_NEGATIVE", pElement.getLongElem().getName());
		assertEquals("-23987982739273989", pElement.getLongElem().toString());
		assertEquals(MyShortTypeClass.SHORT_POSITIVE, pElement.getShortElem());
		assertEquals(3468, pElement.getShortElem().getValue());
		assertEquals("SHORT_POSITIVE", pElement.getShortElem().getName());
		assertEquals("3468", pElement.getShortElem().toString());
		assertEquals(MyDoubleTypeClass.DOUBLE_POSITIVE, pElement.getDoubleElem());
		assertTrue(3249239847982.234 == pElement.getDoubleElem().getValue());
		assertEquals("DOUBLE_POSITIVE", pElement.getDoubleElem().getName());
		assertEquals("3249239847982.234", pElement.getDoubleElem().toString());
		assertEquals(MyFloatTypeClass.FLOAT_NEGATIVE, pElement.getFloatElem());
		assertTrue(Float.parseFloat("-24234.234") == pElement.getFloatElem().getValue());
		assertEquals("FLOAT_NEGATIVE", pElement.getFloatElem().getName());
		assertEquals("-24234.234", pElement.getFloatElem().toString());
	}

	private void verifyAllTypesElement(AllTypesElement pElement) {
		verifyAllSimpleTypesElement(pElement.getAllSimpleTypesElement());
	}

	/** Test for unmarshalling of simple elements.
	 */
	public void testUnmarshalSimpleElements() throws Exception {
		JMUnmarshaller jmUnmarshaller = (JMUnmarshaller) getFactory().createUnmarshaller();
		StringReader sr = new StringReader(getAllTypesElementString());
		AllTypesElement result = (AllTypesElement) jmUnmarshaller.unmarshal(new InputSource(sr));
		verifyAllSimpleTypesElement(result.getAllSimpleTypesElement());
	}

	/** Test for unmarshalling of complex elements.
	 */
	public void testUnmarshalComplexElements() throws Exception {
		JAXBContext myFactory = getFactory();
		Unmarshaller unmarshaller = myFactory.createUnmarshaller();
		StringReader sr = new StringReader(getAllTypesElementString());
		AllTypesElement result = (AllTypesElement) unmarshaller.unmarshal(new InputSource(sr));
		verifyAllTypesElement(result);
	}

	/** Test for marshalling of simple elements.
	 */
	public void testMarshalSimpleElements() throws Exception {
		StringWriter sw = new StringWriter();
		AllTypesElement element = getAllTypesElement();
		Marshaller m = getFactory().createMarshaller();
		m.setProperty(JMMarshallerImpl.JAXME_XML_DECLARATION, Boolean.FALSE);
		m.marshal(element, sw);
		String expected = getAllTypesElementString();
		String got = sw.toString();
		assertEquals(expected, got);
	}

	/** Test for marshalling of complex elements.
	 */
	public void testMarshalComplexElements() throws Exception {
		JAXBContext myFactory = getFactory();
		Marshaller marshaller = myFactory.createMarshaller();
		marshaller.setProperty(JMMarshallerImpl.JAXME_XML_DECLARATION, Boolean.FALSE);
		StringWriter sw = new StringWriter();
		JMElement jmElement = (JMElement) getAllTypesElement();
		assertNotNull(jmElement.getQName());
		marshaller.marshal(jmElement, sw);
		assertEquals(getAllTypesElementString(), sw.toString());
	}

	/** Test for proper creation of prefixes.
	 */
	public void testPrefixes() throws Exception {
		AllTypesElementImpl el = new AllTypesElementImpl();
		JMSAXDriver driver = new AllTypesElementTypeDriver();
		assertEquals("ex", driver.getPreferredPrefix(el.getQName().getNamespaceURI()));
		assertNull(driver.getPreferredPrefix("dummyURI"));
	}
}
