package eu.dnetlib.dlms.union.objects;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openrdf.repository.RepositoryException;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.ExpectedException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import eu.dnetlib.dlms.impl.ops.DorotyExecutor;
import eu.dnetlib.dlms.lowlevel.ImporterInterface;
import eu.dnetlib.dlms.lowlevel.LowLevelException;
import eu.dnetlib.dlms.lowlevel.objects.Atom;
import eu.dnetlib.dlms.lowlevel.objects.AtomDAO;
import eu.dnetlib.dlms.lowlevel.objects.LLDigitalObject;
import eu.dnetlib.dlms.lowlevel.objects.Set;
import eu.dnetlib.dlms.lowlevel.objects.SetDAO;
import eu.dnetlib.dlms.lowlevel.objects.Wrapper;
import eu.dnetlib.dlms.lowlevel.objects.WrapperDAO;
import eu.dnetlib.dlms.lowlevel.types.AtomType;
import eu.dnetlib.dlms.lowlevel.types.AtomTypeDAO;
import eu.dnetlib.dlms.lowlevel.types.SetType;
import eu.dnetlib.dlms.lowlevel.types.SetTypeDAO;
import eu.dnetlib.dlms.union.types.UnionDorotyOperation;
import eu.dnetlib.dlms.union.types.UnionSetType;
import eu.dnetlib.dlms.union.types.UnionSetTypeDAO;
import eu.dnetlib.dlms.union.types.UnionType;
import eu.dnetlib.dlms.union.types.UnionTypeDAO;

/**
 * Test class for UnionSetDAO.
 * 
 * @author lexis
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class UnionSetDAOTest {

	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(UnionSetDAOTest.class);

	/** DAO for UnionSet, entity under test. */
	@Resource
	private UnionSetDAO unionSetDAO;

	/** DAO for Set. */
	@Resource
	private SetDAO setDAO;
	/** DAO for UnionType. */
	@Resource
	private UnionTypeDAO unionTypeDAO;
	/** DAO for AtomTypes. */
	@Resource
	private AtomTypeDAO atomTypeDAO;
	/** DAO for SetType. */
	@Resource
	private SetTypeDAO setTypeDAO;
	/** DAO for UnionSetType. */
	@Resource
	private UnionSetTypeDAO unionSetTypeDAO;
	/** AtomTypes. */
	@Resource
	private AtomType atomType1, atomType2, atomType3;
	/** The UnionType. */
	@Resource
	private UnionType unionType;

	/**
	 * SetTypes for Sets that contain atoms. setType1 has contentType atomType1; setType2 has contentType atomType2,
	 * setType3 has contentType atomType3, setType4 has contentType atomType1.
	 */
	@Resource
	private SetType setType1, setType2, setType3, setType4;
	/** The union set type. */
	@Resource
	private UnionSetType unionSetType;
	/** UnionSetType of a set with wrong setTypes list. */
	@Resource
	private UnionSetType unionSetType2;
	/**
	 * Sets to contain atoms. atomSet1 has setType setType1; atomSet2 has setType setType2; atomSet3 has contentType
	 * setType3; atomSet4 has contentType setType4 and is compatible with atomSet1.
	 */
	@Resource
	private Set atomSet1, atomSet2, atomSet3, atomSet4;
	/**
	 * atoms. atom1 has objectType atomType1, thus can be added to atomSet1 and atomSet4; atom2 has objectType atomType2
	 * and can be added to atomSet2.
	 */
	@Resource
	private Atom atom1, atom2;
	/** DAO for atoms. */
	@Resource
	private AtomDAO atomDAO;
	/** Executor to use to execute operation in a single transaction. It must be used when handling with DorotyList. */
	@Resource
	private DorotyExecutor executor;

	/** DAO for Wrappers. */
	@Resource
	private WrapperDAO wrapperDAO;
	/** Importer instance. */
	@Resource
	private ImporterInterface importer;

	/** The union set. */
	private UnionSet unionSet;
	/** An object to add to the unionset. */
	private Wrapper atom1Wrapper;

	/**
	 * Before each methods save all needed entities to work with a union set, i.e: at least two sets with different
	 * types to put in the union and with at least one object in each set.
	 */
	@Before
	public void init() {
		this.atomTypeDAO.save(this.atomType1);
		this.atomTypeDAO.save(this.atomType2);
		this.atomTypeDAO.save(this.atomType3);
		this.setTypeDAO.save(this.setType1);
		this.setTypeDAO.save(this.setType2);
		this.setTypeDAO.save(this.setType3);
		this.setTypeDAO.save(this.setType4);
		this.atomDAO.save(this.atom1);
		this.atomDAO.save(this.atom2);
		this.setDAO.save(this.atomSet1);
		this.setDAO.save(this.atomSet2);
		this.setDAO.addToSet(this.atomSet1, this.atom1);
		this.setDAO.addToSet(this.atomSet2, this.atom2);
		this.setDAO.save(this.atomSet1);
		this.setDAO.save(this.atomSet2);
		this.setDAO.save(this.atomSet4);
		this.unionType.addType(this.atomType1);
		this.unionType.addType(this.atomType2);
		this.unionTypeDAO.save(this.unionType);
		this.unionSetType.addSetType(this.setType1);
		this.unionSetType.addSetType(this.setType2);
		this.unionSetType2.addSetType(this.setType1);
		this.unionSetType2.addSetType(this.setType2);
		this.unionSetTypeDAO.save(this.unionSetType);
		this.unionSetTypeDAO.save(this.unionSetType2);
	}

	/**
	 * Test for exception when using wrong set in UnionSet.
	 */
	@Test(expected = LowLevelException.class)
	@DirtiesContext
	public void testUnionSetTypeWrong() {
		log.info(this.getClass() + ".testUnionSetTypeWrong");
		//unionSetType2 has setType1 and setType2 in its list of setTypes. atomSet3 is of type setType3, so I expect exception when adding it
		UnionSet us = this.unionSetDAO.create();
		us.setObjectType(this.unionSetType2);
		us.addSet(this.atomSet1);
		us.addSet(this.atomSet2);
		us.addSet(this.atomSet3);
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#addToSet(eu.dnetlib.dlms.union.objects.UnionSet, eu.dnetlib.dlms.lowlevel.objects.LLDigitalObject, eu.dnetlib.dlms.lowlevel.objects.Set)}
	 * .
	 */
	@Test
	@DirtiesContext
	public void testAddToSetUnionSetLLDigitalObjectSet() {
		log.info(this.getClass() + ".testAddToSetUnionSetLLDigitalObjectSet");
		UnionDorotyOperation add2UnionSet = new UnionDorotyOperation() {
			@Override
			public void execute() {
				UnionSetDAOTest.this.unionSet = this.getUnionSetDAO().create();
				UnionSetDAOTest.this.unionSet.setObjectType(UnionSetDAOTest.this.unionSetType);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet2);
				UnionSetDAOTest.this.unionSet.setInfo("UnionSetForAddObject3");
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
				this.getUnionSetDAO().addToSet(UnionSetDAOTest.this.unionSet, UnionSetDAOTest.this.atom1, UnionSetDAOTest.this.atomSet1);
				this.getUnionSetDAO().addToSet(UnionSetDAOTest.this.unionSet, UnionSetDAOTest.this.atom2, UnionSetDAOTest.this.atomSet2);
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
			}
		};
		add2UnionSet.setUnionSetDAO(this.unionSetDAO);
		this.executor.setOperation(add2UnionSet);
		Thread th = new Thread(this.executor);
		th.start();
		try {
			th.join();
		} catch (InterruptedException e) {
		}
		//now let's see if I can get it back with the added objects:
		UnionSet persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		assertNotNull(persistedSet);
		assertTrue(persistedSet.equals(this.unionSet));
		this.unionSetDAO.load(persistedSet);
		for (LLDigitalObject o : persistedSet.getObjects()) {
			assertNotNull(o);
			Wrapper curr = (Wrapper) o;
			log.info(curr);
			assertTrue(curr.getObject().equals(this.atom1) | curr.getObject().equals(this.atom2));
		}
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#addToSet(eu.dnetlib.dlms.union.objects.UnionSet, eu.dnetlib.dlms.lowlevel.objects.LLDigitalObject)}
	 * . This method test the behaviour when calling addToSet on an object that belongs to 2 sets (i.e. the object has
	 * been previously imported). Expected behaviour is that the addToSet throws an exception.
	 */
	@Test
	@DirtiesContext
	@ExpectedException(LowLevelException.class)
	public void testAddToSetUnionSetLLDigitalObjectEx() {
		log.info(this.getClass() + ".testAddToSetUnionSetLLDigitalObjectEx");
		this.unionSetType.getSetTypes().add(this.setType4);
		this.unionSetTypeDAO.save(this.unionSetType);
		//now let's import atom1 into set atomSet4
		this.importer.importObject(this.atomSet4, this.atom1);
		this.atomDAO.save(this.atom1);
		this.setDAO.save(this.atomSet4);
		assertTrue(this.atom1.getBelongingSets().size() == 2);
		//now let's call the method to add the object into the union set
		this.unionSetDAO.addToSet(this.unionSet, this.atom1);
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#addToSet(eu.dnetlib.dlms.union.objects.UnionSet, eu.dnetlib.dlms.lowlevel.objects.LLDigitalObject)}
	 * .
	 */
	@Test
	@DirtiesContext
	public void testAddToSetUnionSetLLDigitalObject() {
		log.info(this.getClass() + ".testAddToSetUnionSetLLDigitalObject");
		UnionDorotyOperation add2UnionSet = new UnionDorotyOperation() {
			@Override
			public void execute() {
				UnionSetDAOTest.this.unionSet = this.getUnionSetDAO().create();
				UnionSetDAOTest.this.unionSet.setObjectType(UnionSetDAOTest.this.unionSetType);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet2);
				UnionSetDAOTest.this.unionSet.setInfo("UnionSetForAddObject2");
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
				this.getUnionSetDAO().addToSet(UnionSetDAOTest.this.unionSet, UnionSetDAOTest.this.atom1);
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
			}
		};
		add2UnionSet.setUnionSetDAO(this.unionSetDAO);
		this.executor.setOperation(add2UnionSet);
		Thread th = new Thread(this.executor);
		th.start();
		try {
			th.join();
		} catch (InterruptedException e) {
		}
		//now let's see if I can get it back with the added objects:
		UnionSet persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		assertTrue(persistedSet.equals(this.unionSet));
		this.unionSetDAO.load(persistedSet);
		for (LLDigitalObject o : persistedSet.getObjects()) {
			assertNotNull(o);
			Wrapper curr = (Wrapper) o;
			log.info(curr);
			assertTrue(curr.getObject().equals(this.atom1));
		}
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#addToSet(eu.dnetlib.dlms.union.objects.UnionSet, eu.dnetlib.dlms.union.objects.UnionObject)}
	 * .
	 */
	@Test
	@DirtiesContext
	public void testAddToSetUnionSetUnionObject() {
		log.info(this.getClass() + ".testAddToSetUnionSetUnionObject");
		UnionDorotyOperation add2UnionSet = new UnionDorotyOperation() {
			@Override
			public void execute() {
				UnionSetDAOTest.this.unionSet = this.getUnionSetDAO().create();
				UnionSetDAOTest.this.unionSet.setObjectType(UnionSetDAOTest.this.unionSetType);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet2);
				UnionSetDAOTest.this.unionSet.setInfo("UnionSetForAddObject1");
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
				UnionSetDAOTest.this.atom1Wrapper = new Wrapper(UnionSetDAOTest.this.atom1, UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.atom1Wrapper.setObjectType(UnionSetDAOTest.this.unionType);
				this.getUnionSetDAO().addToSet(UnionSetDAOTest.this.unionSet, UnionSetDAOTest.this.atom1Wrapper);
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);

			}
		};
		add2UnionSet.setUnionSetDAO(this.unionSetDAO);
		this.executor.setOperation(add2UnionSet);
		Thread th = new Thread(this.executor);
		th.start();
		try {
			th.join();
		} catch (InterruptedException e) {
		}
		//now let's see if I can get it back with the added objects:
		UnionSet persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		assertTrue(persistedSet.equals(this.unionSet));
		this.unionSetDAO.load(persistedSet);
		for (LLDigitalObject o : persistedSet.getObjects()) {
			assertNotNull(o);
			Wrapper curr = (Wrapper) o;
			log.info(curr);
			assertTrue(curr.getObject().equals(this.atom1) && curr.equals(this.atom1Wrapper));
		}
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#createUnionSet(eu.dnetlib.dlms.lowlevel.types.SetType, eu.dnetlib.dlms.lowlevel.objects.Set[])}
	 * .
	 */
	@Test
	public void testCreateUnionSet() {
		log.info(this.getClass() + ".testCreateUnionSet");
		this.unionSet = this.unionSetDAO.create();
		this.unionSet.setObjectType(this.unionSetType);
		this.unionSet.addSet(this.atomSet1);
		this.unionSet.addSet(this.atomSet2);
		assertNotNull(this.unionSet);
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#delete(eu.dnetlib.dlms.union.objects.UnionSet)}.
	 */
	@Test
	@DirtiesContext
	public void testDeleteUnionSet() {
		log.info(this.getClass() + ".testDeleteUnionSet");
		this.unionSet = this.unionSetDAO.create();
		this.unionSet.setObjectType(this.unionSetType);
		this.unionSet.addSet(this.atomSet1);
		this.unionSet.addSet(this.atomSet2);
		this.unionSet.setInfo("UnionSetForDelete");
		this.unionSetDAO.save(this.unionSet);
		//now let's see if I can get it back:
		UnionSet persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		assertNotNull(persistedSet);
		//now let's delete it
		this.unionSetDAO.delete(persistedSet);
		//now let's see if I can't get it back:
		assertNull(this.unionSetDAO.getByID(this.unionSet.getId()));
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#removeFromSet(eu.dnetlib.dlms.union.objects.UnionSet, eu.dnetlib.dlms.lowlevel.objects.LLDigitalObject, eu.dnetlib.dlms.lowlevel.objects.Set)}
	 * .
	 */
	@Test
	@DirtiesContext
	public void testRemoveFromSetUnionSetLLDigitalObjectSet() {
		log.info(this.getClass() + ".testRemoveFromSetUnionSetLLDigitalObjectSet");
		UnionDorotyOperation add2UnionSet = new UnionDorotyOperation() {
			@Override
			public void execute() {
				UnionSetDAOTest.this.unionSet = this.getUnionSetDAO().create();
				UnionSetDAOTest.this.unionSet.setObjectType(UnionSetDAOTest.this.unionSetType);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet2);
				UnionSetDAOTest.this.unionSet.setInfo("UnionSetForRemoveObject3");
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
				this.getUnionSetDAO().addToSet(UnionSetDAOTest.this.unionSet, UnionSetDAOTest.this.atom1, UnionSetDAOTest.this.atomSet1);
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);

			}
		};
		add2UnionSet.setUnionSetDAO(this.unionSetDAO);
		this.executor.setOperation(add2UnionSet);
		Thread th = new Thread(this.executor);
		th.start();
		try {
			th.join();
		} catch (InterruptedException e) {
		}
		//now let's see if I can get it back with the added objects:
		UnionSet persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		assertTrue(persistedSet.equals(this.unionSet));
		this.unionSetDAO.load(persistedSet);
		for (LLDigitalObject o : persistedSet.getObjects()) {
			assertNotNull(o);
			Wrapper curr = (Wrapper) o;
			log.info(curr);
			assertTrue(curr.getObject().equals(this.atom1));
		}
		//now let's delete the object from the union set:
		this.unionSetDAO.removeFromSet(this.unionSet, this.atom1, this.atomSet1);
		this.unionSetDAO.save(this.unionSet);
		//and now let's check unionSet has no objects anymore:
		persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		this.unionSetDAO.load(persistedSet);
		assertTrue(persistedSet.getObjects().isEmpty());
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#removeFromSet(eu.dnetlib.dlms.union.objects.UnionSet, eu.dnetlib.dlms.union.objects.UnionObject)}
	 * .
	 */
	@Test
	@DirtiesContext
	public void testRemoveFromSetUnionSetUnionObject() {
		log.info(this.getClass() + ".testRemoveFromSetUnionSetUnionObject");
		UnionDorotyOperation add2UnionSet = new UnionDorotyOperation() {
			@Override
			public void execute() {
				UnionSetDAOTest.this.unionSet = this.getUnionSetDAO().create();
				UnionSetDAOTest.this.unionSet.setObjectType(UnionSetDAOTest.this.unionSetType);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet2);
				UnionSetDAOTest.this.unionSet.setInfo("UnionSetForRemoveObject1");
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
				UnionSetDAOTest.this.atom1Wrapper = new Wrapper(UnionSetDAOTest.this.atom1, UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.atom1Wrapper.setObjectType(UnionSetDAOTest.this.unionType);
				this.getUnionSetDAO().addToSet(UnionSetDAOTest.this.unionSet, UnionSetDAOTest.this.atom1Wrapper);
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
			}
		};
		add2UnionSet.setUnionSetDAO(this.unionSetDAO);
		this.executor.setOperation(add2UnionSet);
		Thread th = new Thread(this.executor);
		th.start();
		try {
			th.join();
		} catch (InterruptedException e) {
		}
		//now let's see if I can get it back with the added objects:
		UnionSet persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		assertTrue(persistedSet.equals(this.unionSet));
		this.unionSetDAO.load(persistedSet);
		for (LLDigitalObject o : persistedSet.getObjects()) {
			assertNotNull(o);
			Wrapper curr = (Wrapper) o;
			log.info(curr);
			assertTrue(curr.getObject().equals(this.atom1));
		}
		//and now removes the object and let's check unionSet has no objects anymore:
		this.unionSetDAO.removeFromSet(this.unionSet, this.atom1Wrapper);
		this.wrapperDAO.save(this.atom1Wrapper);
		persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		this.unionSetDAO.load(persistedSet);
		assertTrue(persistedSet.getObjects().isEmpty());
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#removeFromSet(eu.dnetlib.dlms.union.objects.UnionSet, eu.dnetlib.dlms.union.objects.UnionObject)}
	 * . Test in the case the wrapper object to remove is a transient instance, so the remove method must explicitly
	 * check if there exist a saved instcne equals to th non persisted one.
	 */
	@Test
	@DirtiesContext
	public void testRemoveFromSetUnionSetUnionObject2() {
		log.info(this.getClass() + ".testRemoveFromSetUnionSetUnionObject2");
		UnionDorotyOperation add2UnionSet = new UnionDorotyOperation() {
			@Override
			public void execute() {
				UnionSetDAOTest.this.unionSet = this.getUnionSetDAO().create();
				UnionSetDAOTest.this.unionSet.setObjectType(UnionSetDAOTest.this.unionSetType);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.unionSet.addSet(UnionSetDAOTest.this.atomSet2);
				UnionSetDAOTest.this.unionSet.setInfo("UnionSetForRemoveObject1");
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
				UnionSetDAOTest.this.atom1Wrapper = new Wrapper(UnionSetDAOTest.this.atom1, UnionSetDAOTest.this.atomSet1);
				UnionSetDAOTest.this.atom1Wrapper.setObjectType(UnionSetDAOTest.this.unionType);
				this.getUnionSetDAO().addToSet(UnionSetDAOTest.this.unionSet, UnionSetDAOTest.this.atom1Wrapper);
				this.getUnionSetDAO().save(UnionSetDAOTest.this.unionSet);
			}
		};
		add2UnionSet.setUnionSetDAO(this.unionSetDAO);
		this.executor.setOperation(add2UnionSet);
		this.executor.run();
		//now let's see if I can get it back with the added objects:
		UnionSet persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		assertTrue(persistedSet.equals(this.unionSet));
		this.unionSetDAO.load(persistedSet);
		for (LLDigitalObject o : persistedSet.getObjects()) {
			assertNotNull(o);
			Wrapper curr = (Wrapper) o;
			log.info(curr);
			assertTrue(curr.getObject().equals(this.atom1));
		}
		//and now removes the object and let's check unionSet has no objects anymore:
		Wrapper w = new Wrapper();
		w.setObject(this.atom1Wrapper.getObject());
		w.setTagSet(this.atom1Wrapper.getTagSet());
		this.unionSetDAO.removeFromSet(this.unionSet, w);
		//this.wrapperDAO.save(this.atom1Wrapper);
		persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		this.unionSetDAO.load(persistedSet);
		assertTrue(persistedSet.getObjects().isEmpty());
		log.info("-----------------------------------");
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#save(eu.dnetlib.dlms.union.objects.UnionSet)}.
	 */
	@Test
	@DirtiesContext
	public void testSaveUnionSet() {
		log.info(this.getClass() + ".testSaveUnionSet");
		this.unionSet = this.unionSetDAO.create();
		this.unionSet.setObjectType(this.unionSetType);
		this.unionSet.addSet(this.atomSet1);
		this.unionSet.addSet(this.atomSet2);
		this.unionSet.setInfo("UnionSetForSave");
		this.unionSetDAO.save(this.unionSet);
		//now let's see if I can get it back:
		UnionSet persistedSet = this.unionSetDAO.getByID(this.unionSet.getId());
		assertTrue(persistedSet.equals(this.unionSet));
		log.info("-----------------------------------");
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.union.objects.UnionSetDAOHibernate#listUnionSets()}.
	 * 
	 * @throws RepositoryException
	 *             accessing triplestore repository
	 */
	@Test
	@DirtiesContext
	public void testListUnionSets() throws RepositoryException {
		log.info(this.getClass().getName() + ".testListUnionSets()");
		//none expected!
		UnionDorotyOperation listRelEmpty = new UnionDorotyOperation() {
			@Override
			public void execute() {
				//At first list is empty
				List<UnionSet> list = this.getUnionSetDAO().list();
				assertTrue(list.isEmpty());
			}
		};
		listRelEmpty.setUnionSetDAO(this.unionSetDAO);
		this.executor.setOperation(listRelEmpty);
		new Thread(this.executor).start();
		//add a set
		this.unionSet = this.unionSetDAO.create();
		this.unionSet.setObjectType(this.unionSetType);
		this.unionSet.addSet(this.atomSet1);
		this.unionSet.addSet(this.atomSet2);
		this.unionSet.setInfo("UnionSetForSave");
		this.unionSetDAO.save(this.unionSet);
		//1 set expected
		UnionDorotyOperation listRelOne = new UnionDorotyOperation() {
			@Override
			public void execute() {
				List<UnionSet> list = this.getUnionSetDAO().list();
				assertTrue(list.size() == 1);
				//let's see what happens at the get
				for (int i = 0; i < list.size(); i++) {
					UnionSet a1 = list.get(i);
					assertNotNull(a1);
					log.debug(a1);
				}
			}
		};
		listRelOne.setUnionSetDAO(this.unionSetDAO);
		this.executor.setOperation(listRelOne);
		Thread th = new Thread(this.executor);
		th.start();
		try {
			th.join();
		} catch (InterruptedException e) {
		}
		this.unionSetDAO.delete(this.unionSet);
		//now check for empty list
		this.executor.setOperation(listRelEmpty);
		th = new Thread(this.executor);
		th.start();
		try {
			th.join();
		} catch (InterruptedException e) {
		}
		log.info("-------------------------------------------");
	}
}
