001    /**
002     * Copyright 2005-2014 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.coreservice.test;
017    
018    import org.apache.commons.lang.StringUtils;
019    
020    import javax.xml.bind.JAXBContext;
021    import javax.xml.bind.Marshaller;
022    import javax.xml.bind.Unmarshaller;
023    import java.io.BufferedReader;
024    import java.io.IOException;
025    import java.io.InputStream;
026    import java.io.InputStreamReader;
027    import java.io.StringReader;
028    import java.io.StringWriter;
029    
030    import static org.junit.Assert.assertEquals;
031    
032    /**
033     * A class with some assertion utilities for JAXB-related operations. 
034     * 
035     * @author Kuali Rice Team (rice.collab@kuali.org)
036     */
037    public final class JAXBAssert {
038            
039            private JAXBAssert() {}
040            
041            /**
042             * Performs the following steps and assertions:
043             * 
044             * <ol>
045             *   <li>Creates a new JAXBContext with the given list of classesToBeBound.</li>
046             *   <li>Marshals the provided objectToMarshall to XML.</li>
047             *   <li>Unmarshals the marshaled XML to recreate the original object.<li>
048             *   <li>Asserts that the newly unmarhsaled object and the original provided object are equal by invoking {@link Object#equals(Object)}.</li>
049             *   <li>Unmarshals the given expectedXml to an object and asserts that it is equal with the original unmarshaled object by invoking {@link Object#equals(Object)}.</li>
050             * </ol>  
051             *  
052             * @param objectToMarshal the object to marshal to XML using JAXB
053             * @param expectedXml an XML string that will be unmarshaled to an Object and compared with objectToMarshal using {@link Object#equals(Object)}
054             * @param classesToBeBound - list of java classes to be recognized by the created JAXBContext
055             * 
056             */
057            public static void assertEqualXmlMarshalUnmarshal(Object objectToMarshal, String expectedXml, Class<?> ... classesToBeBound) {
058                    String marshaledXml = null;
059                    try {
060                      JAXBContext jaxbContext = JAXBContext.newInstance(classesToBeBound);
061                      Marshaller marshaller = jaxbContext.createMarshaller();
062                      
063                      StringWriter stringWriter = new StringWriter();
064                      
065                      marshaller.marshal(objectToMarshal, stringWriter);
066    
067                      marshaledXml = stringWriter.toString();
068                      
069                      Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
070                      
071                      Object actual = unmarshaller.unmarshal(new StringReader(stringWriter.toString()));
072                      assertEquals("Unmarshalled object should be equal to original objectToMarshall.", objectToMarshal, actual);
073    
074              if (StringUtils.isBlank(expectedXml)) {
075                  throw new IllegalArgumentException("Expected XML must be specified.");
076              }
077    
078                      Object expected = unmarshaller.unmarshal(new StringReader(expectedXml.trim()));
079                      assertEquals("Unmarshalled objects should be equal.", expected, actual);
080                    } catch (Throwable e) {
081                            System.err.println("Outputting marshaled XML from failed assertion:\n" + marshaledXml);
082                            if (e instanceof RuntimeException) {
083                                    throw (RuntimeException)e;
084                            } else if (e instanceof Error) {
085                                    throw (Error)e;
086                            }
087                            throw new RuntimeException("Failed to marshall/unmarshall with JAXB.  See the nested exception for details.", e);
088                    }
089            }
090            
091            public static void assertEqualXmlMarshalUnmarshalWithResource(Object objectToMarshal, InputStream expectedXml, Class<?> ... classesToBeBound) throws IOException {
092                    BufferedReader reader = new BufferedReader(new InputStreamReader(expectedXml));
093                    StringWriter writer = new StringWriter();
094                    int data = -1;
095                    while ((data = reader.read()) != -1) {
096                            writer.write(data);
097                    }
098                    assertEqualXmlMarshalUnmarshal(objectToMarshal, writer.toString(), classesToBeBound);
099            }
100            
101    
102    }