+/*****************************************************************************
+ * Company EURIWARE
+ * Application SIMAN
+ * File $Id$
+ * Creation date 12 Oct 2012
+ * @author $Author$
+ * @version $Revision$
+ *****************************************************************************/
+
+package test.splat.common;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Abstract class for specific search functionality tests. It is necessary to
+ * define method, returning expected search list size, array of properties.
+ *
+ * @author <a href="mailto:vera.polyanskikh@opencascade.com">Vera POLYANSKIKH (VPH)</a>
+ * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
+ */
+@Test(sequential=true, groups = {"service", "functional", "business"})
+public class TestListingAndOrder extends AbstractTransactionalTestNGSpringContextTests {
+
+
+
+ /**
+ * Current Specific method name.
+ */
+ protected String _methodName;
+ /**
+ * Common message suffix used to inform that corresponding method should be overridden if this common functionality is used.
+ */
+ private static final String NO_METHOD_OVERRIDEN_MSG_SUFFIX = " should be overridden in test class if common test pagination and order engine is used";
+
+ /**
+ * Error message has been appeared when null object exist in business method result set.
+ */
+ private static final String NULL_OBJECT_EXIST_IN_RESULTSET = "Null object exist in business method result set";
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////
+ /**METHODS TO BE OVERRIDDEN**/
+ /**Throw UnsupportedOperationException if not**/
+ //////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Return expected size of the whole retrieved list or a page of the objects.
+ * @param methodName - specific search method to be called
+ * @return size of list
+ */
+ @Test(enabled = false)
+ public int getExpectedWholeListSize(final String methodName){
+ // empty default implementation
+ // should be overridden if test of pagination or order is necessary
+ throw new UnsupportedOperationException("TestListingAndOrder.getExpectedWholeListSize"+NO_METHOD_OVERRIDEN_MSG_SUFFIX);
+ }
+
+
+ /**
+ * Returns array of DTO properties which can be used to test order of page or list.
+ * @param methodName - specific search method to be called
+ * @return array of order criteria.
+ */
+ @Test(enabled = false)
+ public String[][] getOrderCriteria(final String methodName){
+ // empty default implementation
+ // should be overridden if test of pagination or order is necessary
+ throw new UnsupportedOperationException("TestListingAndOrder.getOrderCriteria"+NO_METHOD_OVERRIDEN_MSG_SUFFIX);
+ }
+
+ /**
+ * Wrapper for call of specific not paginated search method.
+ * @param <T> object type class
+ * @param methodName - specific search method to be called
+ * @return template list
+ */
+ @Test(enabled = false)
+ public <T>List<T> searchListWrapper(final String methodName){
+ // empty default implementation
+ // should be overridden if test of pagination or order is necessary
+ throw new UnsupportedOperationException("TestListingAndOrder.searchListWrapper"+NO_METHOD_OVERRIDEN_MSG_SUFFIX);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////
+ /**END OF SECTION**/
+ //////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Returns result of default comparison of two objects by given array of properties.
+ * @param o1 - object 1
+ * @param o2 - object 2
+ * @param methodName - specific search method name
+ * @param propertyNames - properties to be compared by
+ * @param ascDirection - order direction (asc if true, desc - otherwise)
+ * @return result of comparison.
+ */
+ @Test(enabled = false)
+ protected int specificCompare(final Object o1, final Object o2, final String methodName,final String[] propertyNames,final boolean ascDirection){
+ int result = 0;
+ int i=0;
+ while(result==0 && i<propertyNames.length){
+ result =internalCompare(o1,o2, propertyNames[i]);
+ i++;
+ }
+
+ if(!ascDirection){
+ result = result*(-1);
+ }
+ return result;
+ }
+
+ /**
+ * Perform test of not paginated search method.
+ * @param <T> object type class
+ * @param methodName - specific search method to be called
+ */
+ @Test(enabled = false)
+ protected <T> void internalTestSearchList(final String methodName) {
+ setMethodName(methodName);
+ try {
+ // compare the whole set size with expected
+ List<T> list = searchList();
+ Assert.assertEquals(list.size(), getExpectedWholeListSize(methodName),"The whole list size is unexpected!");
+
+ // check ordering by all given criteria
+ String[] orderCriteria = getOrderCriteria(_methodName)[0];
+
+ Assert.assertTrue(checkOrdering(list,orderCriteria,true),"Asc Ordering of list by properties "+orderCriteria[0].toString()+" is wrong!");
+
+ } catch (Exception e) {
+ Assert.fail("Exception occured", e);
+ }
+ }
+
+ /**
+ * Get the methodName.
+ * @return the methodName
+ */
+ @Test(enabled = false)
+ private String getMethodName() {
+ return _methodName;
+ }
+
+
+
+
+ /**
+ * Set the methodName.
+ * @param methodName the methodName to set
+ */
+ @Test(enabled = false)
+ private void setMethodName(final String methodName) {
+ this._methodName = methodName;
+ }
+
+
+ /**
+ * Test of not paginated search method. Specific service method to be called for tests.
+ * @param <T> object type class
+ * @return list -template list
+ */
+ @Test(enabled = false)
+ private <T>List<T> searchList() {
+ return searchListWrapper(_methodName);
+ }
+
+ /**
+ * Order list given list by given order criteria.
+ * @param <T> - object type class
+ * @param list - list of the objects
+ * @param orderCriteria - property to order by
+ * @param ascDirection - order direction (asc if true, desc - otherwise)
+ * @return ordered list
+ */
+ @Test(enabled = false)
+ private <T>List<T> getOrderedList(final List<T> list,
+ final String[] orderCriteria,
+ final boolean ascDirection){
+ // check ordering
+
+ Collections.sort(list,new Comparator<T>(){
+ public int compare(final T o1, final T o2){
+ return specificCompare(o1,o2,null,orderCriteria,ascDirection);
+ }
+ });
+ return list;
+ }
+
+ /**
+ * Check if given list is ordered by given criteria.
+ * @param <T> - object type class
+ * @param list - list of the objects
+ * @param orderCriteria - property to order by
+ * @param ascDirection - order direction (asc if true, desc - otherwise)
+ * @return boolean
+ */
+ @Test(enabled = false)
+ private <T> boolean checkOrdering(final List<T> list,
+ final String[] orderCriteria,
+ final boolean ascDirection){
+ boolean result = true;
+
+ List<T> oldList = new ArrayList<T>();
+ for(T item:list){
+ oldList.add(item);
+ }
+ List<T> sortedList = getOrderedList(list,orderCriteria,ascDirection);
+ int i = 0 ;
+ for(i=0;i<sortedList.size();i++){
+ if(oldList.get(i)==null){
+ Assert.fail(NULL_OBJECT_EXIST_IN_RESULTSET);
+ }
+ if(!oldList.get(i).equals(sortedList.get(i))){
+ result = false;
+ break;
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Performs internal default compare by given property.
+ * @param o1 - object 1
+ * @param o2 - object 2
+ * @param propertyName - property to be compared by
+ * @return result
+ */
+ @Test(enabled = false)
+ private int internalCompare(final Object o1, final Object o2, final String propertyName){
+ int result = -2;
+ try {
+ // Use getter method for the given property name.
+ Method getter = o1.getClass().getMethod(
+ "get" + propertyName.substring(0, 1).toUpperCase()
+ + propertyName.substring(1));
+ // Get property values by means of the getter method.
+ Object v1 = getter.invoke(o1);
+ Object v2 = getter.invoke(o2);
+ // Compare values.
+ if(v1==null && v2==null) {
+ result = 0;
+ }else{
+ if(v1==null && v2!=null) {
+ result = 1;
+ }else{
+ if(v1!=null && v2==null){
+ result = -1;
+ }else{
+ if (v1 instanceof Comparable) {
+ result = ((Comparable)v1).compareTo(v2);
+ }
+ }
+ }
+ }
+ }catch (IllegalAccessException e) {
+
+ Assert.fail("IllegalAccessException was thrown by BeanUtils.getProperty ", e);
+ } catch (InvocationTargetException e) {
+
+ Assert.fail("InvocationTargetException was thrown by BeanUtils.getProperty ", e);
+ } catch (NoSuchMethodException e) {
+
+ Assert.fail("NoSuchMethodException was thrown by BeanUtils.getProperty: " + e.getMessage(), e);
+ }
+ return result;
+ }
+}