/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.webservices.rest.web;
import static org.hamcrest.core.Is.is;
import org.junit.Assert;
import static org.junit.Assert.assertThat;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Test;
import org.openmrs.api.ConceptNameType;
import org.openmrs.module.webservices.rest.web.representation.Representation;
import org.openmrs.web.test.BaseModuleWebContextSensitiveTest;
public class ConversionUtilTest extends BaseModuleWebContextSensitiveTest {
/**
* @see ConversionUtil#convert(Object,Type)
* @verifies String to Date conversion for multiple formatted date/dateTime strings
*/
@Test
public void convert_shouldReturnEqualsDateFromString() throws Exception {
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").parse("2011-05-01T00:00:00.000");
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.setTimeZone(TimeZone.getDefault());
Date expected = cal.getTime();
String[] dateFormats = { "2011-05-01", "2011-05-01 00:00:00", "2011-05-01T00:00:00.000", "2011-05-01T00:00:00.000" };
for (int i = 0; i < dateFormats.length; i++) {
Date result = (Date) ConversionUtil.convert(dateFormats[i], Date.class);
Assert.assertEquals(result, expected);
}
}
/**
* @see ConversionUtil#convert(Object,Type)
* @verifies String to Date conversion for multiple formatted date/dateTime strings having
* timezone
*/
@Test
public void convert_shouldReturnCorrectDateWhenParsingStringHavingTimeZone() throws Exception {
Date expectedDate1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse("2016-01-12T06:00:00+0530");
//Added to check against more ISO8601 format dates im 'dates2' array
Date expectedDate2 = (Date) ConversionUtil.convert("2014-02-20T11:00:00.000-0500", Date.class);
String[] dates1 = { "2016-01-12T06:00:00+05:30", "2016-01-12T06:00:00+0530" };
String[] dates2 = { "2014-02-20T11:00:00.000-05:00", "2014-02-20T11:00:00.000-05" };
for (String date : dates1) {
Date actualDate = (Date) ConversionUtil.convert(date, Date.class);
Assert.assertEquals(expectedDate1, actualDate);
}
for (String date : dates2) {
Date actualDate = (Date) ConversionUtil.convert(date, Date.class);
Assert.assertEquals(expectedDate2, actualDate);
}
}
/**
* @see ConversionUtil#convert(Object,Type)
* @verifies String to Date conversion by assert false for date mismatches
*/
@Test
public void convert_shouldReturnFalseOnIncorrectDateFromString() throws Exception {
Date expected = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").parse("2011-05-01T00:00:00.000+0530");
String[] dateFormats = { "2011-05-01T00:00:00.000+0200", "2012-05-01T00:00:00.000" };
for (int i = 0; i < dateFormats.length; i++) {
Date result = (Date) ConversionUtil.convert(dateFormats[i], Date.class);
Assert.assertTrue(result != expected);
}
}
/**
* @see ConversionUtil#convert(Object,Type)
* @verifies String format and its representation are equal
*/
@Test
public void convertToRepresentation_shouldReturnSameStringForToday() throws Exception {
Date today = new Date();
String expected = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(today);
String result = (String) ConversionUtil.convertToRepresentation(today, Representation.REF);
Assert.assertEquals(result, expected);
}
/**
* @see {@link ConversionUtil#convert(Object,Type)}
*/
@Test
public void convert_shouldSConvertStringsToEnumsValues() throws Exception {
Object conceptNameType = ConversionUtil.convert("FULLY_SPECIFIED", ConceptNameType.class);
Assert.assertNotNull(conceptNameType);
Assert.assertTrue(conceptNameType.getClass().isAssignableFrom(ConceptNameType.class));
}
/**
* @see {@link ConversionUtil#convert(Object,Type)}
*/
@Test
public void convert_shouldConvertStringsToLocales() throws Exception {
Object locale = ConversionUtil.convert("en", Locale.class);
Assert.assertNotNull(locale);
Assert.assertTrue(locale.getClass().isAssignableFrom(Locale.class));
}
/**
* @see {@link ConversionUtil#convert(Object,Type)}
* @verifies convert to an array
*/
@Test
public void convert_shouldConvertToAnArray() throws Exception {
List<String> input = Arrays.asList("en", "fr");
Locale[] converted = (Locale[]) ConversionUtil.convert(input, Locale[].class);
assertThat(converted.length, is(2));
assertThat(converted[0], is(Locale.ENGLISH));
assertThat(converted[1], is(Locale.FRENCH));
}
/**
* @see {@link ConversionUtil#convert(Object,Type)}
* @verifies convert to a class
*/
@Test
public void convert_shouldConvertToAClass() throws Exception {
String input = "java.lang.String";
Class converted = (Class) ConversionUtil.convert(input, Class.class);
Assert.assertTrue(converted.isAssignableFrom(String.class));
}
public void convert_shouldConvertIntToDouble() throws Exception {
assertThat((Double) ConversionUtil.convert(5, Double.class), is(5d));
}
public void convert_shouldConvertDoubleToInt() throws Exception {
assertThat((Integer) ConversionUtil.convert(5d, Integer.class), is(5));
}
/**
* @verifies resolve TypeVariables to actual type
* @see ConversionUtil#convert(Object, java.lang.reflect.Type)
*/
@Test
public void convert_shouldResolveTypeVariablesToActualType() throws Exception {
ChildGenericType_Int i = new ChildGenericType_Int();
Method setter = PropertyUtils.getPropertyDescriptor(i, "value").getWriteMethod();
Object result = ConversionUtil.convert("25", setter.getGenericParameterTypes()[0], i);
Assert.assertNotNull(result);
Assert.assertEquals(25, result);
}
/**
* @verifies return the actual type if defined on the parent class
* @see ConversionUtil#getTypeVariableClass(Class, java.lang.reflect.TypeVariable)
*/
@Test
public void getTypeVariableClass_shouldReturnTheActualTypeIfDefinedOnTheParentClass() throws Exception {
ChildGenericType_Int i = new ChildGenericType_Int();
ChildGenericType_String s = new ChildGenericType_String();
ChildGenericType_Temp t = new ChildGenericType_Temp();
Method setter = PropertyUtils.getPropertyDescriptor(i, "value").getWriteMethod();
Type type = ConversionUtil.getTypeVariableClass(ChildGenericType_Int.class,
(TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNotNull(type);
Assert.assertEquals(Integer.class, type);
setter = PropertyUtils.getPropertyDescriptor(s, "value").getWriteMethod();
type = ConversionUtil.getTypeVariableClass(ChildGenericType_String.class,
(TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNotNull(type);
Assert.assertEquals(String.class, type);
setter = PropertyUtils.getPropertyDescriptor(t, "value").getWriteMethod();
type = ConversionUtil.getTypeVariableClass(ChildGenericType_Temp.class,
(TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNotNull(type);
Assert.assertEquals(Temp.class, type);
}
/**
* @verifies return the actual type if defined on the grand-parent class
* @see ConversionUtil#getTypeVariableClass(Class, java.lang.reflect.TypeVariable)
*/
@Test
public void getTypeVariableClass_shouldReturnTheActualTypeIfDefinedOnTheGrandparentClass() throws Exception {
GrandchildGenericType_Int i = new GrandchildGenericType_Int();
GreatGrandchildGenericType_Int i2 = new GreatGrandchildGenericType_Int();
Method setter = PropertyUtils.getPropertyDescriptor(i, "value").getWriteMethod();
Type type = ConversionUtil.getTypeVariableClass(GrandchildGenericType_Int.class,
(TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNotNull(type);
Assert.assertEquals(Integer.class, type);
setter = PropertyUtils.getPropertyDescriptor(i2, "value").getWriteMethod();
type = ConversionUtil.getTypeVariableClass(GreatGrandchildGenericType_Int.class,
(TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNotNull(type);
Assert.assertEquals(Integer.class, type);
}
/**
* @verifies return null when actual type cannot be found
* @see ConversionUtil#getTypeVariableClass(Class, java.lang.reflect.TypeVariable)
*/
@Test
public void getTypeVariableClass_shouldReturnNullWhenActualTypeCannotBeFound() throws Exception {
GrandchildGenericType_Int i = new GrandchildGenericType_Int();
Method setter = PropertyUtils.getPropertyDescriptor(i, "value").getWriteMethod();
Type type = ConversionUtil.getTypeVariableClass(Temp.class, (TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNull(type);
}
/**
* @verifies return the correct actual type if there are multiple generic types
* @see ConversionUtil#getTypeVariableClass(Class, java.lang.reflect.TypeVariable)
*/
@Test
public void getTypeVariableClass_shouldReturnTheCorrectActualTypeIfThereAreMultipleGenericTypes() throws Exception {
ChildMultiGenericType i = new ChildMultiGenericType();
Method setter = PropertyUtils.getPropertyDescriptor(i, "first").getWriteMethod();
Type type = ConversionUtil.getTypeVariableClass(ChildMultiGenericType.class,
(TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNotNull(type);
Assert.assertEquals(Integer.class, type);
setter = PropertyUtils.getPropertyDescriptor(i, "second").getWriteMethod();
type = ConversionUtil.getTypeVariableClass(ChildMultiGenericType.class,
(TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNotNull(type);
Assert.assertEquals(String.class, type);
setter = PropertyUtils.getPropertyDescriptor(i, "third").getWriteMethod();
type = ConversionUtil.getTypeVariableClass(ChildMultiGenericType.class,
(TypeVariable<?>) setter.getGenericParameterTypes()[0]);
Assert.assertNotNull(type);
Assert.assertEquals(Temp.class, type);
}
/**
* @verifies throw IllegalArgumentException when instance class is null
* @see ConversionUtil#getTypeVariableClass(Class, java.lang.reflect.TypeVariable)
*/
@Test(expected = IllegalArgumentException.class)
public void getTypeVariableClass_shouldThrowIllegalArgumentExceptionWhenInstanceClassIsNull() throws Exception {
GrandchildGenericType_Int i = new GrandchildGenericType_Int();
Method setter = PropertyUtils.getPropertyDescriptor(i, "value").getWriteMethod();
Type type = ConversionUtil.getTypeVariableClass(null, (TypeVariable<?>) setter.getGenericParameterTypes()[0]);
}
/**
* @verifies throw IllegalArgumentException when typeVariable is null
* @see ConversionUtil#getTypeVariableClass(Class, java.lang.reflect.TypeVariable)
*/
@Test(expected = IllegalArgumentException.class)
public void getTypeVariableClass_shouldThrowIllegalArgumentExceptionWhenTypeVariableIsNull() throws Exception {
ConversionUtil.getTypeVariableClass(Temp.class, null);
}
public abstract class BaseGenericType<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public abstract class BaseMultiGenericType<F, S, T> {
private F first;
private S second;
private T third;
public F getFirst() {
return first;
}
public void setFirst(F first) {
this.first = first;
}
public S getSecond() {
return second;
}
public void setSecond(S second) {
this.second = second;
}
public T getThird() {
return third;
}
public void setThird(T third) {
this.third = third;
}
}
public class Temp {}
public class ChildGenericType_Int extends BaseGenericType<Integer> {}
public class ChildGenericType_String extends BaseGenericType<String> {}
public class ChildGenericType_Temp extends BaseGenericType<Temp> {}
public class GrandchildGenericType_Int extends ChildGenericType_Int {}
public class GreatGrandchildGenericType_Int extends GrandchildGenericType_Int {}
public class ChildMultiGenericType extends BaseMultiGenericType<Integer, String, Temp> {}
}