001/** 002 * Copyright 2005-2016 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 */ 016package org.kuali.rice.kim.api.test; 017 018import javax.xml.bind.JAXBContext; 019import javax.xml.bind.Marshaller; 020import javax.xml.bind.Unmarshaller; 021import java.io.BufferedReader; 022import java.io.IOException; 023import java.io.InputStream; 024import java.io.InputStreamReader; 025import java.io.StringReader; 026import java.io.StringWriter; 027 028import static org.junit.Assert.assertEquals; 029 030/** 031 * A class with some assertion utilities for JAXB-related operations. 032 * 033 * TODO - copied this from the core api test module, find a better way to share this code! 034 * 035 * @author Kuali Rice Team (rice.collab@kuali.org) 036 */ 037public 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 Object expected = unmarshaller.unmarshal(new StringReader(expectedXml.trim())); 075 assertEquals("Unmarshalled objects should be equal.", expected, actual); 076 } catch (Throwable e) { 077 System.err.println("Outputting marshaled XML from failed assertion:\n" + marshaledXml); 078 if (e instanceof RuntimeException) { 079 throw (RuntimeException)e; 080 } else if (e instanceof Error) { 081 throw (Error)e; 082 } 083 throw new RuntimeException("Failed to marshall/unmarshall with JAXB. See the nested exception for details.", e); 084 } 085 } 086 087 public static void assertEqualXmlMarshalUnmarshalWithResource(Object objectToMarshal, InputStream expectedXml, Class<?> ... classesToBeBound) throws IOException { 088 BufferedReader reader = new BufferedReader(new InputStreamReader(expectedXml)); 089 StringWriter writer = new StringWriter(); 090 int data = -1; 091 while ((data = reader.read()) != -1) { 092 writer.write(data); 093 } 094 assertEqualXmlMarshalUnmarshal(objectToMarshal, writer.toString(), classesToBeBound); 095 } 096 097 098}