package eu.dnetlib.data.sts.ds;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.xml.ws.Endpoint;

import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import pl.edu.icm.driver.factories.UniBiBeansFactory;
import pl.edu.icm.driver.index.DummyStaticResultSet;
import pl.edu.icm.driver.is.ISUtils;
import pl.edu.icm.driver.tester.TestDescription;
import pl.edu.icm.driver.tester.runner.Parameterized4TestCase;
import pl.edu.icm.driver.tester.runner.TestJobContext;
import pl.edu.icm.driver.utils.PropertiesKeys;
import eu.dnetlib.data.sts.das.DataAccessServiceException;
import eu.dnetlib.data.sts.das.IDataAccessService;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;

/**
 * {@link IDepotService} test class.
 * 
 * TODO implement tests for manageDASReplicas
 * 
 * @author mhorst
 *
 */
@TestDescription(
		name="DataAccess Service test suite",
		description="Performs all required functionality tests of DataAccess service.\n" +
				"Expected properties:\n" +
				"unibi.das.service.location - localisation of DataAccess service for reading data\n" +
				"unibi.depot.service.location - localisation of Depot service to be tested\n" +
				"Optional properties:\n" +
				"is.rs.dataprov.ip - data provider service ip\n" +
				"is.rs.dataprov.port - data provider service port\n" +
				"is.rs.dataprov.location - data provider service location (default: 'IDataProvider?wsdl')\n" +
				"text.txt.location - remote txt file location\n"
)
public class DepotServiceTest extends Parameterized4TestCase {

	protected static final Logger log = Logger.getLogger(DepotServiceTest.class);

	long sleepTime = 1000;
	int triesCount = 5;
	
	IDepotService depotService;
	IDataAccessService dataAccessService;
	
	String depotServiceLocation;
	String dataAccessServiceLocation;
	
	String textTxtLocation = null;
	
	String dataProviderIP = null;
	String dataProviderPort = null;
	String dataProviderLocation = null;
	String dataProviderURL = null;
	
	/**
	 * DMF data provider.
	 */
	ResultSetService dataProvider;
	
	/**
	 * CXF bus containing HTTP server.
	 */
	Bus bus;
	
	/* (non-Javadoc)
	 * @see pl.edu.icm.driver.tester.ParameterizedTest#setParameters(java.util.Map)
	 */
	@Override
	public void setParameters(Map<Object, Object> parameters) {
		depotServiceLocation = (String) parameters.get(
				PropertiesKeys.SERVICE_LOCATION_DEPOT);
		log.info("TestCase depotServiceLocation: " + 
				depotServiceLocation);
		dataAccessServiceLocation = (String) parameters.get(
				PropertiesKeys.SERVICE_LOCATION_DAS);
		log.info("TestCase dataAccessServiceLocation: " + 
				dataAccessServiceLocation);
		
		textTxtLocation = (String) parameters.get(PropertiesKeys.TEXT_TXT_LOCATION);
		
		dataProviderIP = (String) parameters.get(PropertiesKeys.RS_DATA_PROVIDER_IP);
		dataProviderPort = (String) parameters.get(PropertiesKeys.RS_DATA_PROVIDER_PORT);
		dataProviderLocation = (String) parameters.get(PropertiesKeys.RS_DATA_PROVIDER_LOCATION);
	}

	@Before
	public void setUp() throws Exception {
		ResourceBundle bundle = ResourceBundle.getBundle("pl.edu.icm.driver.is.auxiliary");
		if (textTxtLocation==null)
			textTxtLocation = bundle.getString(PropertiesKeys.TEXT_TXT_LOCATION);
		if (dataProviderIP==null)
			dataProviderIP = bundle.getString(PropertiesKeys.RS_DATA_PROVIDER_IP);
		if (dataProviderPort==null)
			dataProviderPort = bundle.getString(PropertiesKeys.RS_DATA_PROVIDER_PORT);
		if (dataProviderLocation==null)
			dataProviderLocation = bundle.getString(PropertiesKeys.RS_DATA_PROVIDER_LOCATION);
		StringBuffer strBuff = new StringBuffer();
		strBuff.append("http://");
		strBuff.append(dataProviderIP);
		strBuff.append(':');
		strBuff.append(dataProviderPort);
		strBuff.append('/');
		strBuff.append(dataProviderLocation);
		dataProviderURL = strBuff.toString();
		log.info("dataProviderURL: "+dataProviderURL);
		
		UniBiBeansFactory ubBeansFactory = new UniBiBeansFactory();
		dataAccessService = ubBeansFactory.getDAS(dataAccessServiceLocation);
		depotService = ubBeansFactory.getDepot(depotServiceLocation);
	}
	
	@After
	public void tearDown() throws Exception {

	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Retrieves version number from identity call in Depot service. " +
					"Stores it in the result with description ''"
			)
	public void testIdentify() throws Exception {
		String identify = depotService.identify();
		assertNotNull(identify);
		assertTrue(identify.length()>0);
		System.out.println("service version: "+identify);
		TestJobContext.storeResult(identify, "service version");
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able to create store"
			)
	public void testCreateStore() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
					"creating store with invalid mime type"
			)
	public void testCreateStoreWithInvalidMimeType() throws Exception {
		String stId = null;
		try {
			List<String> mimeTypes = new ArrayList<String>();
			mimeTypes.add("unknown-mime-type");
			stId = depotService.createStore(mimeTypes, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			fail("exception should be thrown when " +
					"creating store with invalid mime type");
		} catch (DepotServiceException e) {
//			ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"creating store with invalid max size"
			)
	public void testCreateStoreWithInvalidMaxSize() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, -100);
			fail("exception should be thrown when " +
					"creating store with invalid max size");
		} catch (DepotServiceException e) {
//			ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able to update store"
			)
	public void testUpdateStore() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> mimeTypes = new ArrayList<String>();
			mimeTypes.add("text/plain");
			assertTrue(depotService.updateStore(stId, 
					100000, mimeTypes));
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"updating store for invalid id"
			)
	public void testUpdateStoreForInvalidId() throws Exception {
		try {
			depotService.updateStore("invalidId", StorageConstants.DEFAULT_MAX_ST_DS_SIZE, null);
			fail("exception should be thrown when " +
					"updating store for invalid id");
		} catch (DepotServiceException e) {
//			ok
		} 
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"updating store with invalid mime type"
			)
	public void testUpdateStoreWithInvalidMimeType() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> mimeTypes = new ArrayList<String>();
			mimeTypes.add("unknown-mime-type");
			depotService.updateStore(stId, 100000, mimeTypes);
			fail("exception should be thrown when " +
					"updating store with invalid mime type");
		} catch (DepotServiceException e) {
//			ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
		
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"updating store with invalid max size"
			)
	public void testUpdateStoreWithInvalidMaxSize() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			depotService.updateStore(stId, -100, null);
			fail("exception should be thrown when " +
					"updating store with invalid max size");
		} catch (DepotServiceException e) {
//			ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able to delete store"
			)
	public void testDeleteStore() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"deleting store for invalid id"
			)
	public void testDeleteStoreForInvalidId() throws Exception {
		try {
			depotService.deleteStore("invalidId");
			fail("exception should be thrown when " +
					"udeleting store for invalid id");
		} catch (DepotServiceException e) {
//			ok
		} 
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able to delete object"
			)
	public void testDeleteStoreObject() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			String actionId = depotService.storeObjects(
					stId, data, StorageConstants.STORING_TYPE_REFRESH);
//			wait until storing is finished
			boolean actionFinished = false;
			for (int i=0; i<triesCount; i++) {
				Thread.sleep(sleepTime);
				String storingStatus = depotService.storingCallback(
						stId, actionId, false);
				if (DepotServiceHelper.isStoringStatusDone(storingStatus)) {
					actionFinished = true;
					break;
				}
			}
			assertTrue(actionFinished);
//			validate simply via data access
			String dataSDO = dataAccessService.getObjectSDO(dataObjectId, stId);
			assertNotNull(dataSDO);
			assertTrue(dataSDO.length()>0);
			List<String> toBeDeleted = new ArrayList<String>();
			toBeDeleted.add(dataObjectId);
			assertTrue(depotService.deleteStoreObject(stId, toBeDeleted));
			try {
				dataAccessService.getObjectSDO(dataObjectId, stId);
				fail("exception should be thrown when getting deleted object");
			} catch(DataAccessServiceException e) {
//				ok
			}
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"deleting store object for invalid store id"
			)
	public void testDeleteStoreObjectForInvalidStoreId() throws Exception {
		try {
			List<String> toBeDeleted = new ArrayList<String>();
			toBeDeleted.add("someObjId");
			depotService.deleteStoreObject("invalidStId", toBeDeleted);
			fail("exception should be thrown when " +
					"deleting store object for invalid store id");
		} catch(DepotServiceException e) {
//			ok
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"deleting store object for invalid object id"
			)
	public void testDeleteStoreObjectForInvalidObjectId() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> toBeDeleted = new ArrayList<String>();
			toBeDeleted.add("invalidDataObjectId");
			try {
				assertTrue(depotService.deleteStoreObject(stId, toBeDeleted));
				fail("exception should be thrown when " +
					"deleting store object for invalid object id");
			} catch(DepotServiceException e) {
			//	ok
			}
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able to delete object from RS"
			)
	public void testDeleteStoreObjectFromRS() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			String dataObjectId1 = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId1, 
					StorageConstants.STORE_DATATYPE_DATA, "some other data content"));
			String dataObjectId2 = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId2, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			String actionId = depotService.storeObjects(
					stId, data, StorageConstants.STORING_TYPE_REFRESH);
//			wait until storing is finished
			boolean actionFinished = false;
			for (int i=0; i<triesCount; i++) {
				Thread.sleep(sleepTime);
				String storingStatus = depotService.storingCallback(
						stId, actionId, false);
				if (DepotServiceHelper.isStoringStatusDone(storingStatus)) {
					actionFinished = true;
					break;
				}
			}
			assertTrue(actionFinished);
//			validate simply via data access
			String dataSDO1 = dataAccessService.getObjectSDO(dataObjectId1, stId);
			assertNotNull(dataSDO1);
			assertTrue(dataSDO1.length()>0);
			List<String> toBeDeleted = new ArrayList<String>();
			toBeDeleted.add(dataObjectId1);
			toBeDeleted.add(dataObjectId2);
			serverStartup(new Integer(dataProviderPort).intValue(), 
					toBeDeleted.toArray(new String[toBeDeleted.size()]));
			
			int expiryTime = 10000;
			String bdId = String.valueOf(System.currentTimeMillis());
			int initialPageSize = 10;
			assertTrue(depotService.deleteStoreObjectFromRS(stId, 
					dataProvider.createPullRS(dataProviderURL, bdId, 
							initialPageSize, expiryTime, null, null, null)));
			try {
				dataAccessService.getObjectSDO(dataObjectId1, stId);
				fail("exception should be thrown when getting deleted object");
			} catch(DataAccessServiceException e) {
//				ok
			}
		} finally {
			serverShutdown();
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"deleting store object from RS for invalid store id"
			)
	public void testDeleteStoreObjectFromRSForInvalidStoreId() throws Exception {
		try {
			List<String> toBeDeleted = new ArrayList<String>();
			serverStartup(new Integer(dataProviderPort).intValue(), 
					toBeDeleted.toArray(new String[toBeDeleted.size()]));
			
			int expiryTime = 10000;
			String bdId = String.valueOf(System.currentTimeMillis());
			int initialPageSize = 10;
			depotService.deleteStoreObjectFromRS("invalidStoreId", 
					dataProvider.createPullRS(dataProviderURL, bdId, 
							initialPageSize, expiryTime, null, null, null));
			fail("exception should be thrown when " +
					"deleting store object from RS for invalid store id");
		} catch (DepotServiceException e) {
//			ok
		} finally {
			serverShutdown();
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"deleting store object from RS for invalid EPR"
			)
	public void testDeleteStoreObjectFromRSForInvalidEPR() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			String dataProviderServiceAddress = "http://localhost:1234/nonExisting";
			depotService.deleteStoreObjectFromRS(stId, 
					ISUtils.buildEPR(dataProviderServiceAddress, 
							"unknownID", dataProviderServiceAddress+"?wsdl", "RSName"));
			fail("exception should be thrown when " +
					"deleting store object from RS for invalid EPR");
		} catch (DepotServiceException e) {
//			ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able to store objects"
			)
	public void testStoreObjects() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			String uriObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(uriObjectId, 
					StorageConstants.STORE_DATATYPE_URI, textTxtLocation));
			String actionId = depotService.storeObjects(
					stId, data, StorageConstants.STORING_TYPE_REFRESH);
//			wait until storing is finished
			boolean actionFinished = false;
			for (int i=0; i<triesCount; i++) {
				Thread.sleep(sleepTime);
				String storingStatus = depotService.storingCallback(
						stId, actionId, false);
				if (DepotServiceHelper.isStoringStatusDone(storingStatus)) {
					actionFinished = true;
					break;
				}
			}
			assertTrue(actionFinished);
//			validate simply via data access
			String dataSDO = dataAccessService.getObjectSDO(dataObjectId, stId);
			assertNotNull(dataSDO);
			assertTrue(dataSDO.length()>0);
			String uriSDO = dataAccessService.getObjectSDO(uriObjectId, stId);
			assertNotNull(uriSDO);
			assertTrue(uriSDO.length()>0);
			
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"storing objects for invalid store id"
			)
	public void testStoreObjectsForInvalidId() throws Exception {
		try {
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			depotService.storeObjects("invalidId", data, StorageConstants.STORING_TYPE_REFRESH);
			fail("exception should be thrown when " +
					"storing objects for invalid store id");
		} catch (DepotServiceException e) {
//			ok
		} 
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"storing objects for invalid objects"
			)
	public void testStoreObjectsWithInvalidObjects() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			data.add("invalidDataContent");
			depotService.storeObjects(
					stId, data, StorageConstants.STORING_TYPE_REFRESH);
			fail("exception should be thrown when " +
				"storing objects for invalid objects");
		} catch (DepotServiceException e) {
//			ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"storing objects for invalid storing type"
			)
	public void testStoreObjectsWithInvalidStoringType() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			depotService.storeObjects(
					stId, data, "unsupportedStoringType");
			fail("exception should be thrown when " +
				"storing objects for invalid storing type");
		} catch (DepotServiceException e) {
//			ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able to store objects from RS"
			)
	public void testStoreObjectsFromRS() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			String uriObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(uriObjectId, 
					StorageConstants.STORE_DATATYPE_URI, textTxtLocation));
			serverStartup(new Integer(dataProviderPort).intValue(), 
					data.toArray(new String[data.size()]));
			
			int expiryTime = 10000;
			String bdId = String.valueOf(System.currentTimeMillis());
			int initialPageSize = 10;
			String actionId = depotService.storeObjectsFromRS(stId, 
					dataProvider.createPullRS(dataProviderURL, bdId, 
							initialPageSize, expiryTime, null, null, null), 
							StorageConstants.STORING_TYPE_REFRESH);
			assertNotNull(actionId);
//			wait until storing is finished
			boolean actionFinished = false;
			for (int i=0; i<triesCount; i++) {
				Thread.sleep(sleepTime);
				String storingStatus = depotService.storingCallback(
						stId, actionId, false);
				if (DepotServiceHelper.isStoringStatusDone(storingStatus)) {
					actionFinished = true;
					break;
				}
			}
			assertTrue(actionFinished);
//			validate simply via data access
			String dataSDO = dataAccessService.getObjectSDO(dataObjectId, stId);
			assertNotNull(dataSDO);
			assertTrue(dataSDO.length()>0);
			String uriSDO = dataAccessService.getObjectSDO(uriObjectId, stId);
			assertNotNull(uriSDO);
			assertTrue(uriSDO.length()>0);
			
		} finally {
			serverShutdown();
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"storing objects from RS for invalid id"
			)
	public void testStoreObjectsFromRSForInvalidId() throws Exception {
		try {
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			String uriObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(uriObjectId, 
					StorageConstants.STORE_DATATYPE_URI, textTxtLocation));
			serverStartup(new Integer(dataProviderPort).intValue(), 
					data.toArray(new String[data.size()]));
			
			int expiryTime = 10000;
			String bdId = String.valueOf(System.currentTimeMillis());
			int initialPageSize = 10;
			depotService.storeObjectsFromRS("invalidId", 
					dataProvider.createPullRS(dataProviderURL, bdId, 
							initialPageSize, expiryTime, null, null, null), 
							StorageConstants.STORING_TYPE_REFRESH);
			fail("exception should be thrown when " +
				"storing objects from RS for invalid id");
		} catch (DepotServiceException e) {
	//		ok
		} finally {
			serverShutdown();
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"storing objects from RS for invalid EPR"
			)
	public void testStoreObjectsFromRSWithInvalidEPR() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			String dataProviderServiceAddress = "http://localhost:1234/nonExisting";
			depotService.storeObjectsFromRS(stId, 
					ISUtils.buildEPR(dataProviderServiceAddress, 
							"unknownID", dataProviderServiceAddress+"?wsdl", "RSName"), 
							StorageConstants.STORING_TYPE_REFRESH);
			fail("exception should be thrown when " +
				"storing objects from RS for invalid EPR");
		} catch (DepotServiceException e) {
	//		ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"storing objects from RS for invalid storing type"
			)
	public void testStoreObjectsFromRSWithInvalidStoringType() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			serverStartup(new Integer(dataProviderPort).intValue(), 
					data.toArray(new String[data.size()]));
			
			int expiryTime = 10000;
			String bdId = String.valueOf(System.currentTimeMillis());
			int initialPageSize = 10;
			depotService.storeObjectsFromRS(stId, 
					dataProvider.createPullRS(dataProviderURL, bdId, 
							initialPageSize, expiryTime, null, null, null), 
					"invalidStoringType");
			fail("exception should be thrown when " +
				"storing objects from RS for invalid storing type");
		} catch (DepotServiceException e) {
	//		ok
		} finally {
			serverShutdown();
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able return proper status callback"
			)
	public void testStoringCallback() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			String uriObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(uriObjectId, 
					StorageConstants.STORE_DATATYPE_URI, textTxtLocation));
			serverStartup(new Integer(dataProviderPort).intValue(), 
					data.toArray(new String[data.size()]));
			
			int expiryTime = 10000;
			String bdId = String.valueOf(System.currentTimeMillis());
			int initialPageSize = 10;
			String actionId = depotService.storeObjectsFromRS(stId, 
					dataProvider.createPullRS(dataProviderURL, bdId, 
							initialPageSize, expiryTime, null, null, null), 
							StorageConstants.STORING_TYPE_REFRESH);
			assertNotNull(actionId);
//			wait until storing is finished
			boolean actionFinished = false;
			for (int i=0; i<triesCount; i++) {
				Thread.sleep(sleepTime);
				String storingStatus = depotService.storingCallback(
						stId, actionId, false);
				if (DepotServiceHelper.isStoringStatusDone(storingStatus)) {
					actionFinished = true;
					break;
				}
			}
			assertTrue(actionFinished);
			
		} finally {
			serverShutdown();
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Tests if service is able return proper " +
					"complete callback profile"
			)
	public void testStoringCallbackWithCompleteProfile() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			List<String> data = new ArrayList<String>();
			String dataObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(dataObjectId, 
					StorageConstants.STORE_DATATYPE_DATA, "some data content"));
			String uriObjectId = "test_id_"+System.currentTimeMillis();
			data.add(DepotServiceHelper.buildStoreRecord(uriObjectId, 
					StorageConstants.STORE_DATATYPE_URI, textTxtLocation));
			serverStartup(new Integer(dataProviderPort).intValue(), 
					data.toArray(new String[data.size()]));
			
			int expiryTime = 10000;
			String bdId = String.valueOf(System.currentTimeMillis());
			int initialPageSize = 10;
			String actionId = depotService.storeObjectsFromRS(stId, 
					dataProvider.createPullRS(dataProviderURL, bdId, 
							initialPageSize, expiryTime, null, null, null), 
							StorageConstants.STORING_TYPE_REFRESH);
			assertNotNull(actionId);
			String profile = depotService.storingCallback(
					stId, actionId, true);
			assertNotNull(profile);
			assertTrue(profile.contains("STORING_STATUS"));
			assertTrue(profile.contains(stId));
			assertTrue(profile.contains(actionId));
			
		} finally {
			serverShutdown();
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"storing callback for invalid store id"
			)
	public void testStoringCallbackForInvalidId() throws Exception {
		try {
			depotService.storingCallback(
					"invalidStoreId", "someActionId", false);
			fail("exception should be thrown when " +
				"storing callback for invalid store id");
		} catch (DepotServiceException e) {
	//		ok
		}
	}
	
	@Test
	@TestDescription(
			planId="depot.functionality",
			description="Checks whether service fails smoothly when " +
				"storing callback for invalid action id"
			)
	public void testStoringCallbackForInvalidActionId() throws Exception {
		String stId = null;
		try {
			stId = depotService.createStore(null, StorageConstants.DEFAULT_MAX_ST_DS_SIZE);
			assertNotNull(stId);
			depotService.storingCallback(
					stId, "invalidActionId", false);
			fail("exception should be thrown when " +
				"storing callback for invalid action id");
		} catch (DepotServiceException e) {
	//		ok
		} finally {
			if (stId!=null) {
				depotService.deleteStore(stId);
			}
		}
	}
	
	
	
	/**
	 * Starts up cxf jetty server.
	 * @param dataProviderPort
	 * @throws Exception
	 */
	void serverStartup(int dataProviderPort, String[] data) throws Exception {
//		 Create CXF Service
		bus = BusFactory.getDefaultBus();
		dataProvider = new DummyStaticResultSet(data);
		StringBuffer strBuff = new StringBuffer();
		strBuff.append("http://");
		strBuff.append(dataProviderIP);
		strBuff.append(':');
		strBuff.append(dataProviderPort);
		strBuff.append('/');
		strBuff.append(dataProviderLocation);
		Endpoint.publish(strBuff.toString(), dataProvider);
		log.info("cxf service started...");
	}
	
	/**
	 * Shuts down cxf jetty server.
	 * @throws Exception
	 */
	void serverShutdown() throws Exception {
		if (bus!=null) {
			log.info("shutting down cxf service...");
			bus.shutdown(true);
		}
	}

}
