/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 
 * 
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License("CDDL") (the "License").  You may not use this file
 * except in compliance with the License. 
 * 
 * You can obtain a copy of the License at:
 *     https://jersey.dev.java.net/license.txt
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * When distributing the Covered Code, include this CDDL Header Notice in each
 * file and include the License file at:
 *     https://jersey.dev.java.net/license.txt
 * If applicable, add the following below this CDDL Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 *     "Portions Copyrighted [year] [name of copyright owner]"
 */

package com.sun.jersey.samples.jaxb;

import com.sun.grizzly.http.SelectorThread;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;


public class Main {

    @Path("/XmlRootElement")
    @Produces({"application/xml", "application/json"})
    @Consumes({"application/xml", "application/json"})
    public static class JAXBXmlRootElementResource {
        @POST
        public JAXBXmlRootElement post(JAXBXmlRootElement r) {
            return r;
        }
        
        @Path("{path}")
        public JAXBXmlRootElementResource getSubResource(@PathParam("path") String path) {
            return new JAXBXmlRootElementResource();
        }
    }

    @Path("/XmlType")
    @Produces({"application/xml","application/json"})
    @Consumes({"application/xml","application/json"})
    public static class JAXBXmlTypeResource {
        @POST
        public JAXBElement<JAXBXmlType> post(JAXBXmlType r) {
            return new JAXBElement<JAXBXmlType>(
                    new QName("jaxbXmlRootElement"), JAXBXmlType.class, r);
        }
        
        @Path("{path}")
        public JAXBXmlTypeResource getSubResource(@PathParam("path") String path) {
            return new JAXBXmlTypeResource();
        }
    }

    @Path("/JAXBElement")
    @Produces({"application/xml","application/json"})
    @Consumes({"application/xml","application/json"})
    public static class JAXBElementResource {
        @POST
        public JAXBElement<JAXBXmlType> post(JAXBElement<JAXBXmlType> e) {
            return e;
        }
        
        @Path("{path}")
        public JAXBElementResource getSubResource(@PathParam("path") String path) {
            return new JAXBElementResource();
        }
    }

    public static void client() throws Exception {
        Client c = Client.create();
        WebResource r = c.resource("http://localhost:9998/");
        
        JAXBXmlRootElement re;
        JAXBXmlType t;
        JAXBElement<JAXBXmlType> e;

        
        // Tests for resource JAXBXmlRootElementResource
        test(r, "XmlRootElement", "application/xml");
        test(r, "XmlRootElement/something", "application/xml");
                
        test(r, "XmlRootElement", "application/json");
        test(r, "XmlRootElement/something", "application/json");

        // Tests for resource JAXBXmlTypeResource
        test(r, "XmlType", "application/xml");
        test(r, "XmlType/something", "application/xml");
                
        test(r, "XmlType", "application/json");
        test(r, "XmlType/something", "application/json");
                
        // Tests for resource JAXBElementResource
        test(r, "JAXBElement", "application/xml");        
        test(r, "JAXBElement/something", "application/xml");

        test(r, "JAXBElement", "application/json");        
        test(r, "JAXBElement/something", "application/json");
    }

    private static void test(WebResource r, String path, String mimeType) {
        JAXBXmlRootElement re;
        JAXBXmlType t;
        JAXBElement<JAXBXmlType> e;
        
        // Tests for resource JAXBXmlRootElementResource
        
        // Send an instance of JAXBXmlRootElement
        // Receieve an instance of JAXBXmlRootElement
        re = r.path(path).type(mimeType).
                post(JAXBXmlRootElement.class, new JAXBXmlRootElement("content"));
        assertEquals("content", re.value);

        // Send an instance of JAXBXmlRootElement
        // Receieve an instance of JAXBXmlType
        t = r.path(path).type(mimeType).
                post(JAXBXmlType.class, new JAXBXmlRootElement("content"));
        assertEquals("content", re.value);
        
        // Send an instance of JAXBElement<JAXBXmlType>
        // Receieve an instance of JAXBXmlType
        t = r.path(path).type(mimeType).
                post(JAXBXmlType.class, 
                new JAXBElement<JAXBXmlType>(new QName("jaxbXmlRootElement"),
                JAXBXmlType.class,
                new JAXBXmlType("content")));
        assertEquals("content", re.value);        
    }
    
    private static void assertEquals(String expected, String value) {
        if (!expected.equals(value)) {
            throw new RuntimeException("Expected " + expected + " but have " + value);
        }
    }
    
    public static void main(String[] args) throws Exception {
        try {
            final Map<String, String> initParams = new HashMap<String, String>();
            initParams.put("com.sun.jersey.config.property.packages",
                    "com.sun.jersey.samples.jaxb");
            SelectorThread threadSelector = GrizzlyWebContainerFactory.create(
                    "http://localhost:9998/",
                    initParams);
            try {
                client();
            } finally {
                threadSelector.stopEndpoint();
                System.exit(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        
    }    
}