Salome HOME
Added test of search by study readers.
[tools/siman.git] / Workspace / Siman-Common / src / test / splat / service / TestStudyService.java
1 /*****************************************************************************
2  * Company         OPEN CASCADE
3  * Application     SIMAN
4  * File            $Id$ 
5  * Creation date   12 Oct 2012
6  * @author         $Author$
7  * @version        $Revision$
8  *****************************************************************************/
9 package test.splat.service;
10
11 import java.io.File;
12 import java.io.FileNotFoundException;
13 import java.io.FileWriter;
14 import java.io.IOException;
15 import java.sql.SQLException;
16 import java.util.Date;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.splat.dal.bo.som.ReaderRelation;
22 import org.splat.dal.bo.kernel.Relation;
23 import org.splat.dal.bo.kernel.User;
24 import org.splat.dal.bo.som.ContributorRelation;
25 import org.splat.dal.bo.som.DescriptionAttribute;
26 import org.splat.dal.bo.som.Document;
27 import org.splat.dal.bo.som.DocumentType;
28 import org.splat.dal.bo.som.KnowledgeElement;
29 import org.splat.dal.bo.som.KnowledgeElementType;
30 import org.splat.dal.bo.som.ProgressState;
31 import org.splat.dal.bo.som.ProjectElement;
32 import org.splat.dal.bo.som.Publication;
33 import org.splat.dal.bo.som.Scenario;
34 import org.splat.dal.bo.som.SimulationContext;
35 import org.splat.dal.bo.som.Study;
36 import org.splat.dal.bo.som.ValidationCycle;
37 import org.splat.dal.bo.som.ValidationCycleRelation;
38 import org.splat.dal.bo.som.ValidationStep;
39 import org.splat.dal.bo.som.Document.Properties;
40 import org.splat.dal.dao.kernel.UserDAO;
41 import org.splat.dal.dao.som.Database;
42 import org.splat.dal.dao.som.KnowledgeElementDAO;
43 import org.splat.dal.dao.som.KnowledgeElementTypeDAO;
44 import org.splat.dal.dao.som.ScenarioDAO;
45 import org.splat.dal.dao.som.StudyDAO;
46 import org.splat.dal.dao.som.ValidationCycleDAO;
47 import org.splat.exception.BusinessException;
48 import org.splat.exception.InvalidParameterException;
49 import org.splat.kernel.InvalidPropertyException;
50 import org.splat.kernel.MissedPropertyException;
51 import org.splat.kernel.MultiplyDefinedException;
52 import org.splat.log.AppLogger;
53 import org.splat.service.DocumentTypeService;
54 import org.splat.service.ProjectElementService;
55 import org.splat.service.PublicationService;
56 import org.splat.service.SimulationContextService;
57 import org.splat.service.StepService;
58 import org.splat.service.StudyService;
59 import org.splat.service.dto.FileDTO;
60 import org.splat.service.dto.UserDTO;
61 import org.splat.service.technical.ProjectSettingsService;
62 import org.splat.service.technical.RepositoryService;
63 import org.splat.service.technical.ProjectSettingsService.Step;
64 import org.splat.util.BeanHelper;
65 import org.springframework.beans.factory.annotation.Autowired;
66 import org.springframework.beans.factory.annotation.Qualifier;
67 import org.springframework.orm.hibernate3.HibernateTemplate;
68 import org.testng.Assert;
69 import org.testng.annotations.Test;
70
71 import test.splat.common.BaseTest;
72 import test.splat.util.TestEntitiesGenerator;
73
74 /**
75  * Test class for StudyService.
76  * 
77  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
78  * 
79  */
80 public class TestStudyService extends BaseTest {
81
82         /**
83          * Logger for the class.
84          */
85         private static final AppLogger LOG = AppLogger
86                         .getLogger(TestStudyService.class);
87
88         /**
89          * The StudyDAO. Later injected by Spring.
90          */
91         @Autowired
92         @Qualifier("studyDAO")
93         private transient StudyDAO _studyDAO;
94
95         /**
96          * The PublicationService. Later injected by Spring.
97          */
98         @Autowired
99         @Qualifier("publicationService")
100         private transient PublicationService _publicationService;
101
102         /**
103          * The ProjectElementService. Later injected by Spring.
104          */
105         @Autowired
106         @Qualifier("projectElementService")
107         private transient ProjectElementService _projectElementService;
108
109         /**
110          * The StepService. Later injected by Spring.
111          */
112         @Autowired
113         @Qualifier("stepService")
114         private transient StepService _stepService;
115
116         /**
117          * The ProjectSettingsService. Later injected by Spring.
118          */
119         @Autowired
120         @Qualifier("projectSettings")
121         private transient ProjectSettingsService _projectSettings;
122
123         /**
124          * The DocumentTypeService. Later injected by Spring.
125          */
126         @Autowired
127         @Qualifier("documentTypeService")
128         private transient DocumentTypeService _documentTypeService;
129
130         /**
131          * The StudyService. Later injected by Spring.
132          */
133         @Autowired
134         @Qualifier("studyService")
135         private transient StudyService _studyService;
136
137         /**
138          * The UserDAO. Later injected by Spring.
139          */
140         @Autowired
141         @Qualifier("userDAO")
142         private transient UserDAO _userDAO;
143
144         /**
145          * The KnowledgeElementDAO. Later injected by Spring.
146          */
147         @Autowired
148         @Qualifier("knowledgeElementDAO")
149         private transient KnowledgeElementDAO _knowledgeElementDAO;
150
151         /**
152          * The KnowledgeElementTypeDAO. Later injected by Spring.
153          */
154         @Autowired
155         @Qualifier("knowledgeElementTypeDAO")
156         private transient KnowledgeElementTypeDAO _knowledgeElementTypeDAO;
157
158         /**
159          * The ScenarioDAO. Later injected by Spring.
160          */
161         @Autowired
162         @Qualifier("scenarioDAO")
163         private transient ScenarioDAO _scenarioDAO;
164
165         /**
166          * The SimulationContextService. Later injected by Spring.
167          */
168         @Autowired
169         @Qualifier("simulationContextService")
170         private transient SimulationContextService _simulationContextService;
171
172         /**
173          * The ValidationCycleDAO. Later injected by Spring.
174          */
175         @Autowired
176         @Qualifier("validationCycleDAO")
177         private transient ValidationCycleDAO _validationCycleDAO;
178
179         /**
180          * The RepositoryService. Later injected by Spring.
181          */
182         @Autowired
183         @Qualifier("repositoryService")
184         private transient RepositoryService _repositoryService;
185
186         /**
187          * Create a persistent scenario for tests.
188          * 
189          * @return a persistent scenario
190          * @throws InvalidPropertyException
191          *             if an invalid property is used when creating objects
192          * @throws MultiplyDefinedException
193          *             when trying to create an object with already existing id
194          * @throws MissedPropertyException
195          *             if a mandatory property is not defined for an object to be created
196          * @throws IOException
197          *             if document creation is failed
198          * @throws SQLException
199          *             if project settings loading is failed
200          */
201         private Study createStudy() throws InvalidPropertyException,
202                         MissedPropertyException, MultiplyDefinedException, IOException,
203                         SQLException {
204                 // Create a scenario for tests
205                 HibernateTemplate ht = getHibernateTemplate();
206
207                 Database.getInstance().reset();
208                 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
209                 // Load workflow customization
210                 try {
211                         _projectSettings.configure("classpath:test/som.xml");
212                 } catch (FileNotFoundException e) {
213                         Assert.fail("Can't find som.xml: ", e);
214                 }
215                 List<Step> steps = _projectSettings.getAllSteps();
216                 Assert.assertTrue(steps.size() > 0, "No steps are created.");
217
218                 // Create a test user
219                 User.Properties uprop = new User.Properties();
220                 uprop.setUsername("TST_Username").setName("TST_SimanUnitTestsUser")
221                                 .setFirstName("TST_FirstName").setDisplayName("TST_test.user")
222                                 .addRole("TST_user").setMailAddress(
223                                                 "noreply@salome-platform.org");
224                 uprop.disableCheck();
225                 User anAuthor = new User(uprop);
226                 ht.saveOrUpdate(anAuthor);
227
228                 // Create a test study
229                 Study.Properties stprops = new Study.Properties().setReference(
230                                 "TST_SID_01").setTitle("TST_Study").setManager(anAuthor);
231                 Study aStudy = new Study(stprops);
232                 ht.saveOrUpdate(aStudy);
233
234                 // Create a test scenario
235                 Scenario.Properties sprops = new Scenario.Properties().setTitle(
236                                 "TST_Scenario").setManager(anAuthor).setOwnerStudy(aStudy);
237                 Scenario aScenario = new Scenario(sprops);
238                 aStudy.getScenariiList().add(aScenario);
239                 ht.saveOrUpdate(anAuthor);
240                 ht.saveOrUpdate(aStudy);
241                 ht.saveOrUpdate(aScenario);
242
243                 // Create documents for each scenario step
244                 Document.Properties dprop = new Document.Properties().setAuthor(
245                                 anAuthor).setDate(new Date());
246                 int i = 0;
247                 Publication usedPub = null;
248                 Map<Long, Long> usedMap = new HashMap<Long, Long>();
249                 for (int stepNum = 1; stepNum <= steps.size(); stepNum++) {
250                         Step step = _projectSettings.getStep(stepNum);
251                         LOG.debug("Create scenario step: " + stepNum);
252                         ProjectElement projElem;
253
254                         if (step.appliesTo(Study.class)) {
255                                 projElem = aStudy;
256                         } else {
257                                 projElem = aScenario;
258                         }
259                         org.splat.som.Step aScStep = new org.splat.som.Step(step, projElem);
260                         List<DocumentType> dtypes = _documentTypeService
261                                         .selectTypesOf(step);
262                         if (dtypes.size() > 0) {
263                                 DocumentType dtype = dtypes.get(0);
264                                 // Create a document published in the scenario
265                                 // document<i>: document type[0] - first type used on the step
266                                 // <source-file>.brep
267                                 // <attached-file>.med
268                                 i++;
269                                 dprop.setName("document" + stepNum).setType(dtype);
270                                 if (step.getNumber() > 3) {
271                                         dprop.setFormat("med");
272                                 } else {
273                                         dprop.setFormat("py");
274                                 }
275                                 Publication pub = createDoc(projElem, aScStep, dprop, "med",
276                                                 false);
277                                 if (usedPub != null) {
278                                         pub.addDependency(usedPub);
279                                         LOG.debug("Add dependency: " + pub.value().getTitle()
280                                                         + " from " + usedPub.value().getTitle());
281                                         ht.saveOrUpdate(pub.value());
282                                         ht.flush();
283
284                                         usedMap.put(pub.getIndex(), usedPub.getIndex());
285                                 }
286                                 usedPub = pub;
287                         }
288                         if (dtypes.size() <= 0) {
289                                 LOG.debug("No document types are found for scenario step " + i);
290                         }
291                 }
292
293                 // Check that the scenario and its documents have been created correctly.
294
295                 Assert.assertNotNull(ht.find("from Document"),
296                                 "No documents in the database.");
297                 Assert.assertTrue(ht.find("from Document").size() > 0,
298                                 "No documents in the database.");
299
300                 Assert.assertNotNull(ht.find("from Publication where owner="
301                                 + aScenario.getIndex()), "No publications in the database.");
302                 Assert.assertTrue(
303                                 ht.find("from Publication where owner=" + aScenario.getIndex())
304                                                 .size() > 0, "No publications in the database.");
305
306                 for (Publication p : (List<Publication>) ht
307                                 .find("from Publication where owner=" + aScenario.getIndex())) {
308                         LOG.debug("Publication found: [id=" + p.getIndex() + ", owner="
309                                         + p.getOwner().getIndex() + ", doc=" + p.value().getIndex()
310                                         + "]");
311                         Assert.assertEquals(p.getOwner().getIndex(), aScenario.getIndex(),
312                                         "The publication was not attached to the scenario.");
313                 }
314
315                 // Remove the scenario from the current hibernate session.
316                 ht.evict(aScenario);
317                 // Check that the scenario is created in the database.
318                 Scenario aScen = ht.load(Scenario.class, aScenario.getIndex());
319                 Assert.assertNotNull(aScen, "Scenario was not saved in the database.");
320                 Assert.assertTrue(aScen.getDocums().size() > 0,
321                                 "No publications in the scenario.");
322
323                 Assert.assertTrue(i > 0,
324                                 "More then one document must be in the database");
325
326                 // Check created uses relations
327                 Assert
328                                 .assertTrue(usedMap.size() > 0,
329                                                 "Uses relations must be created.");
330                 boolean foundAny = false;
331                 for (Long usingId : usedMap.keySet()) {
332                         for (Publication pub : aScen.getDocums()) {
333                                 if (pub.getIndex() == usingId) {
334                                         boolean found = false;
335                                         for (Publication used : aScen.getDocums()) {
336                                                 found = (used.getIndex() == usedMap.get(usingId));
337                                                 if (found) {
338                                                         break;
339                                                 }
340                                         }
341                                         if (!found) {
342                                                 for (Publication used : aStudy.getDocums()) {
343                                                         found = (used.getIndex() == usedMap.get(usingId));
344                                                         if (found) {
345                                                                 break;
346                                                         }
347                                                 }
348                                         }
349                                         Assert.assertTrue(found,
350                                                         "Uses relation was not created in the database.");
351                                         foundAny = foundAny || found;
352                                 }
353                         }
354                 }
355                 Assert.assertTrue(foundAny,
356                                 "No Uses relation was created in the database.");
357
358                 return aScenario.getOwnerStudy();
359         }
360
361         /**
362          * Create a document published in the scenario. <BR>
363          * document:<BR>
364          * document type - type used on the step <BR>
365          * &lt;source-file&gt;.brep <BR>
366          * &lt;attached-file&gt;.med
367          * 
368          * @param aScenario
369          *            the scenario to add the document to
370          * @param aScStep
371          *            scenario step where the document to be published
372          * @param dprop
373          *            document properties
374          * @param attachedFileExt
375          *            extension of the secon attached (exported) file
376          * @param isOutdated
377          *            outdated document flag
378          * @return the publication of the created document
379          * @throws IOException
380          * @throws MultiplyDefinedException
381          * @throws InvalidPropertyException
382          * @throws MissedPropertyException
383          */
384         private Publication createDoc(final ProjectElement aScenario,
385                         final org.splat.som.Step aScStep, final Properties dprop,
386                         final String attachedFileExt, final boolean isOutdated)
387                         throws MissedPropertyException, InvalidPropertyException,
388                         MultiplyDefinedException, IOException {
389                 // Create a document published in the scenario
390                 // document<i>: document type - type used on the step
391                 // <source-file>.brep
392                 // <attached-file>.med
393                 Publication pub = _stepService.createDocument(aScStep, dprop);
394                 Assert.assertNotNull(pub.getOwner(),
395                                 "The publication must be attached to the scenario.");
396                 Assert.assertEquals(pub.getOwner().getIndex(), aScenario.getIndex(),
397                                 "The publication was not attached to the scenario.");
398
399                 if (isOutdated) {
400                         pub.setIsnew('O');
401                 }
402                 aScenario.add(pub);
403                 HibernateTemplate ht = getHibernateTemplate();
404                 ht.saveOrUpdate(pub);
405
406                 // Attach a file
407                 ht.save(pub.value());
408                 ht.flush();
409                 ht.saveOrUpdate(_publicationService.attach(pub, attachedFileExt));
410
411                 return pub;
412         }
413
414         /**
415          * Test of generating a study document index.<BR>
416          * <B>Description :</B> <BR>
417          * <i>Create a study and try to generate the next document index.</i><BR>
418          * <B>Action : </B><BR>
419          * <i>1. call DAO's read method for an existing id.</i><BR>
420          * <B>Test data : </B><BR>
421          * <i>no input parameters</i><BR>
422          * 
423          * <B>Outcome results:</B><BR>
424          * <i>
425          * <ul>
426          * <li>The new index must be equal to the incremented old one and saved into the database<BR>
427          * </li>
428          * </ul>
429          * </i>
430          * 
431          * @throws InvalidPropertyException
432          *             if an invalid property is used when creating objects
433          * @throws MultiplyDefinedException
434          *             when trying to create an object with already existing id
435          * @throws MissedPropertyException
436          *             if a mandatory property is not defined for an object to be created
437          * @throws SQLException
438          *             if test study creation is failed
439          * @throws IOException
440          *             if test study creation is failed
441          * 
442          */
443         @Test
444         public void testGenerateLocalIndex() throws InvalidPropertyException,
445                         MissedPropertyException, MultiplyDefinedException, IOException,
446                         SQLException {
447                 LOG.debug(">>>>> BEGIN testGenerateLocalIndex()");
448                 startNestedTransaction();
449
450                 HibernateTemplate ht = getHibernateTemplate();
451                 Study aStudy = createStudy();
452                 // Call DAO's create method for a good transient study.
453                 Long id = aStudy.getIndex();
454                 Assert.assertNotNull(id,
455                                 "Create method returns null instead of a new id.");
456                 Assert.assertTrue(id > 0, "The new id is not a positive number.");
457
458                 // Call DAO's get method for an existing id.
459                 _studyDAO.flush();
460                 getHibernateTemplate().evict(aStudy);
461                 getHibernateTemplate().clear();
462                 Study aStudyFound = _studyDAO.get(id);
463
464                 int oldInd = aStudyFound.getLastLocalIndex();
465                 int ind = _studyService.generateLocalIndex(aStudyFound);
466
467                 _studyDAO.flush();
468                 Assert.assertEquals(ind, oldInd + 1, "Index must be incremented.");
469                 Assert.assertEquals(ind, aStudyFound.getLastLocalIndex(),
470                                 "Index must be incremented.");
471                 Assert.assertEquals(ind, ht.get(Study.class, aStudyFound.getIndex())
472                                 .getLastLocalIndex(),
473                                 "Incremented index must be saved in the database.");
474                 aStudy = (Study) ht.find(
475                                 "from Study where rid = " + aStudyFound.getIndex()).get(0);
476                 Assert.assertEquals(ind, aStudy.getLastLocalIndex(),
477                                 "Incremented index must be saved in the database.");
478
479                 rollbackNestedTransaction();
480                 LOG.debug(">>>>> END testGenerateLocalIndex()");
481         }
482
483         /**
484          * Test of retrieval of a study description.
485          * 
486          * @throws BusinessException
487          *             if there is something wrong likely unrelated to the tested method
488          */
489         @Test
490         public void testGetDescription() throws BusinessException {
491                 LOG.debug(">>>>> BEGIN testGetDescription()");
492                 startNestedTransaction();
493
494                 User user = TestEntitiesGenerator.getTestUser("GoodUser");
495                 _userDAO.create(user);
496                 Study study = TestEntitiesGenerator.getTestStudy(user);
497                 _studyDAO.create(study);
498                 _studyDAO.flush();
499                 Long studyId = Long.valueOf(study.getIndex());
500
501                 // Empty description:
502                 Assert.assertNull(_studyService.getDescription(studyId),
503                                 "returned value for study without description must be null");
504
505                 // Not empty description:
506                 study.setAttribute(new DescriptionAttribute(study, "description"));
507                 _studyDAO.update(study);
508                 _studyDAO.flush();
509                 Assert.assertEquals("description", _studyService
510                                 .getDescription(studyId));
511
512                 // null id
513                 try {
514                         _studyService.getDescription(null);
515                         Assert.fail("retrieval with null study id must fail");
516                 } catch (InvalidParameterException e) {
517                         LOG.debug("Expected exception is thrown: "
518                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
519                 }
520
521                 // Non-existing id
522                 Study tmpStudy = TestEntitiesGenerator.getTestStudy(user);
523                 _studyDAO.create(tmpStudy);
524                 Long nonExistingId = tmpStudy.getIndex();
525                 _studyDAO.delete(tmpStudy);
526                 try {
527                         _studyService.getDescription(nonExistingId);
528                         Assert.fail("retrieval with non-existing study id must fail");
529                 } catch (InvalidParameterException e) {
530                         LOG.debug("Expected exception is thrown: "
531                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
532                 }
533
534                 rollbackNestedTransaction();
535                 LOG.debug(">>>>> END testGetDescription()");
536         }
537
538         /**
539          * Test of setting of a study description.
540          * 
541          * @throws BusinessException
542          *             if there is something wrong likely unrelated to the tested method
543          */
544         @Test
545         public void testSetDescription() throws BusinessException {
546                 LOG.debug(">>>>> BEGIN testSetDescription()");
547                 startNestedTransaction();
548
549                 User user = TestEntitiesGenerator.getTestUser("GoodUser");
550                 _userDAO.create(user);
551                 Study study = TestEntitiesGenerator.getTestStudy(user);
552                 _studyDAO.create(study);
553                 _studyDAO.flush();
554                 Long studyId = Long.valueOf(study.getIndex());
555
556                 // Setting description for study without any
557                 _studyService.setDescription(studyId, "description");
558
559                 // Resetting description
560                 _studyService.setDescription(studyId, "replaced description");
561
562                 // null id
563                 try {
564                         _studyService.setDescription(null, "description");
565                         Assert.fail("setting with null study id must fail");
566                 } catch (InvalidParameterException e) {
567                         LOG.debug("Expected exception is thrown: "
568                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
569                 }
570
571                 // Non-existing id
572                 Study tmpStudy = TestEntitiesGenerator.getTestStudy(user);
573                 _studyDAO.create(tmpStudy);
574                 Long nonExistingId = tmpStudy.getIndex();
575                 _studyDAO.delete(tmpStudy);
576
577                 try {
578                         _studyService.setDescription(nonExistingId, "description");
579                         Assert.fail("retrieval with non-existing study id must fail");
580                 } catch (InvalidParameterException e) {
581                         LOG.debug("Expected exception is thrown: "
582                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
583                 }
584
585                 rollbackNestedTransaction();
586                 LOG.debug(">>>>> END testSetDescription()");
587         }
588
589         /**
590          * Test of removal of a study description.
591          * 
592          * @throws BusinessException
593          *             if there is something wrong likely unrelated to the tested method
594          */
595         @Test
596         public void testRemoveDescription() throws BusinessException {
597                 LOG.debug(">>>>> BEGIN testRemoveDescription()");
598                 startNestedTransaction();
599
600                 User user = TestEntitiesGenerator.getTestUser("GoodUser");
601                 _userDAO.create(user);
602                 Study study = TestEntitiesGenerator.getTestStudy(user);
603                 _studyDAO.create(study);
604                 _studyDAO.flush();
605                 Long studyId = Long.valueOf(study.getIndex());
606
607                 // Empty description:
608                 Assert.assertFalse(_studyService.removeDescription(studyId),
609                                 "returned value for study without description must be null");
610
611                 // Not empty description:
612                 study.setAttribute(new DescriptionAttribute(study, "description"));
613                 _studyDAO.update(study);
614                 _studyDAO.flush();
615                 Assert.assertTrue(_studyService.removeDescription(studyId),
616                                 "existing description removal must return true");
617
618                 Assert.assertNull(_studyService.getDescription(studyId),
619                                 "description hasn't been successfully removed");
620
621                 // null id
622                 try {
623                         _studyService.removeDescription(null);
624                         Assert.fail("removal with null study id must fail");
625                 } catch (InvalidParameterException e) {
626                         LOG.debug("Expected exception is thrown: "
627                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
628                 }
629
630                 // Non-existing id
631                 Study tmpStudy = TestEntitiesGenerator.getTestStudy(user);
632                 _studyDAO.create(tmpStudy);
633                 Long nonExistingId = tmpStudy.getIndex();
634                 _studyDAO.delete(tmpStudy);
635                 try {
636                         _studyService.removeDescription(nonExistingId);
637                         Assert.fail("removal with non-existing study id must fail");
638                 } catch (InvalidParameterException e) {
639                         LOG.debug("Expected exception is thrown: "
640                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
641                 }
642
643                 rollbackNestedTransaction();
644                 LOG.debug(">>>>> END testGetDescription()");
645         }
646
647         /**
648          * Test study removal.<BR>
649          * <B>Description :</B> <BR>
650          * <i>Delete a study.</i><BR>
651          * <B>Action : </B><BR>
652          * <i>1. call the method for a not existing study id expecting an exception.</i><BR>
653          * <i>2. call the method for an existing study id.</i><BR>
654          * <B>Test data : </B><BR>
655          * <i>no input parameters</i><BR>
656          * 
657          * <B>Outcome results:</B><BR>
658          * <i>
659          * <ul>
660          * <li>1: Exception must be thrown.</li>
661          * <li>2: The study and all its objects must be removed.</li>
662          * </ul>
663          * </i>
664          * 
665          * @throws BusinessException
666          *             if test data creation is failed
667          * @throws IOException
668          *             if document creation is failed
669          */
670         @Test
671         public void testRemoveStudy() throws BusinessException, IOException {
672                 LOG.debug(">>>>> BEGIN testRemoveStudy()");
673                 startNestedTransaction();
674
675                 HibernateTemplate ht = getHibernateTemplate();
676
677                 Database.getInstance().reset();
678                 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
679                 // Load workflow customization
680                 try {
681                         _projectSettings.configure("classpath:test/som.xml");
682                 } catch (Exception e) {
683                         Assert.fail("Can't load som.xml: ", e);
684                 }
685
686                 User goodUser = TestEntitiesGenerator.getTestUser("GoodUser");
687                 _userDAO.create(goodUser);
688                 User otherUser = TestEntitiesGenerator.getTestUser("otherUser");
689                 _userDAO.create(otherUser);
690                 User thirdUser = TestEntitiesGenerator.getTestUser("thirdUser");
691                 _userDAO.create(thirdUser);
692                 KnowledgeElementType ktype1 = new KnowledgeElementType("testKType1");
693                 KnowledgeElementType ktype2 = new KnowledgeElementType("testKType2");
694                 ktype2.setState(ProgressState.inWORK);
695                 _knowledgeElementTypeDAO.create(ktype1);
696                 _knowledgeElementTypeDAO.create(ktype2);
697
698                 // Create private study
699                 Study aStudy = TestEntitiesGenerator.getTestStudy(goodUser);
700                 aStudy.setTitle("0.This is private study");
701                 Long studyId = _studyDAO.create(aStudy);
702
703                 // Add simulation context to the study
704                 SimulationContext.Properties cprop = new SimulationContext.Properties();
705                 cprop.setType(_simulationContextService.selectType("product"))
706                                 .setValue("Test Simulation Context: Product");
707                 _studyService.addProjectContext(aStudy, cprop);
708                 ht.flush();
709
710                 // Add a scenario to the study
711                 Scenario scen = TestEntitiesGenerator.getTestScenario(aStudy);
712                 _scenarioDAO.create(scen);
713                 ht.flush();
714
715                 // Add knowledge elements to the scenario
716                 KnowledgeElement kelm01 = TestEntitiesGenerator
717                                 .getTestKnowledgeElement(scen, ktype1, "TestKelm01 title");
718                 KnowledgeElement kelm02 = TestEntitiesGenerator
719                                 .getTestKnowledgeElement(scen, ktype2, "TestKelm02 title");
720                 _knowledgeElementDAO.create(kelm01);
721                 _knowledgeElementDAO.create(kelm02);
722                 ht.flush();
723
724                 // Add contributor relation
725                 aStudy.addRelation(new ContributorRelation(aStudy, otherUser));
726                 ht.flush();
727
728                 // Add a validation cycle with otherUser as a reviewer
729                 ValidationCycle.Properties vprop = new ValidationCycle.Properties();
730                 DocumentType dtype = _documentTypeService.selectType("minutes");
731                 vprop.setDocumentType(dtype);
732                 vprop.setActor(ValidationStep.REVIEW, otherUser);
733                 ValidationCycle cycle = new ValidationCycle(aStudy, vprop);
734                 _validationCycleDAO.create(cycle);
735                 ValidationCycleRelation link = cycle.getContext();
736                 aStudy.addRelation(link);
737                 ht.flush();
738
739                 // Add documents to the first study activity
740                 // Add a converts relations
741                 Publication pub1 = addDoc(aStudy, "document1", dtype);
742                 Publication pub2 = addDoc(aStudy, "document2", dtype);
743                 Publication pub3 = addDoc(aStudy, "document3", dtype);
744                 ht.flush();
745
746                 LOG.debug("pub1 version doc: " + pub1.value().getTitle() + " ["
747                                 + pub1.value().getReference() + "]" + " ["
748                                 + pub1.value().getRid() + "]");
749                 LOG.debug("pub2 version doc: " + pub2.value().getTitle() + " ["
750                                 + pub2.value().getReference() + "]" + " ["
751                                 + pub2.value().getRid() + "]");
752                 LOG.debug("pub3 version doc: " + pub3.value().getTitle() + " ["
753                                 + pub3.value().getReference() + "]" + " ["
754                                 + pub3.value().getRid() + "]");
755
756                 ht.update(aStudy);
757
758                 ht.flush();
759                 LOG.debug("Before versioning:");
760                 for (Publication doc : _projectElementService.getFirstStep(aStudy)
761                                 .getAllDocuments()) {
762                         LOG.debug("Study doc: " + doc.value().getTitle() + " ["
763                                         + doc.value().getReference() + "]" + " ["
764                                         + doc.value().getRid() + "]");
765                 }
766                 // Add a version relations
767                 Publication pub31 = version(pub3);
768
769                 // _publicationService.versionDocument(_projectElementService
770                 // .getFirstStep(aStudy), goodUser, pub3
771                 // .getSourceFile().getName(), pub3.value().getIndex(), "",
772                 // "The new version", pub3.getProgressState(), new Date(), null,
773                 // null);
774
775                 // Publication pub31 = null;
776                 // for (Publication pub : aStudy.getDocums()) {
777                 // if (pub.value().getPreviousVersion() != null) {
778                 // pub31 = pub;
779                 // }
780                 // }
781
782                 LOG.debug("pub31 version doc: " + pub31.value().getTitle() + " ["
783                                 + pub31.value().getReference() + "]" + " ["
784                                 + pub31.value().getRid() + "]");
785                 ht.saveOrUpdate(aStudy);
786
787                 LOG.debug("After versioning:");
788                 for (Publication doc : aStudy.getDocums()) {
789                         LOG.debug("Study doc: " + doc.value().getTitle() + " ["
790                                         + doc.value().getReference() + "]" + " ["
791                                         + doc.value().getRid() + "]");
792                 }
793
794                 // Add documents to the first scenario activity
795                 Publication spub1 = addDoc(scen, "sdocument1", dtype);
796                 Publication spub2 = addDoc(scen, "sdocument2", dtype);
797                 Publication spub3 = addDoc(scen, "sdocument3", dtype);
798                 LOG.debug("spub1 version doc: " + spub1.value().getTitle() + " ["
799                                 + spub1.value().getReference() + "]" + " ["
800                                 + spub1.value().getRid() + "]");
801                 LOG.debug("spub2 version doc: " + spub2.value().getTitle() + " ["
802                                 + spub2.value().getReference() + "]" + " ["
803                                 + spub2.value().getRid() + "]");
804                 LOG.debug("spub3 version doc: " + spub3.value().getTitle() + " ["
805                                 + spub3.value().getReference() + "]" + " ["
806                                 + spub3.value().getRid() + "]");
807                 ht.flush();
808
809                 // Create a scenario document version
810                 Publication spub31 = version(spub3);
811                 LOG.debug("spub31 version doc: " + spub31.value().getTitle() + " ["
812                                 + spub31.value().getReference() + "]" + " ["
813                                 + spub31.value().getRid() + "]");
814
815                 // Add uses relations
816                 pub2.addDependency(pub1);
817                 ht.saveOrUpdate(pub2.value());
818                 pub3.addDependency(pub2);
819                 ht.saveOrUpdate(pub3.value());
820
821                 spub2.addDependency(pub1);
822                 spub2.addDependency(spub1);
823                 spub2.addDependency(pub2);
824                 spub2.addDependency(pub3);
825                 ht.saveOrUpdate(spub2.value());
826                 spub3.addDependency(spub2);
827                 ht.saveOrUpdate(spub3.value());
828                 spub31.addDependency(spub31);
829                 ht.saveOrUpdate(spub31.value());
830                 ht.flush();
831
832                 // /////////////////////////////////////////////////////////
833                 ht.clear();
834                 // Check removal of contributors relation
835                 List found1 = ht.find("from ContributorRelation where owner=" + studyId);
836                 Assert.assertEquals(found1.size(), 1,
837                                 "ContributorRelation is not created");
838                 ht.clear();
839                 
840                 _studyService.removeStudy(studyId);
841                 ht.flush();
842
843                 // Check removal of the study
844                 Study foundStudy = ht.get(Study.class, studyId);
845                 Assert.assertNull(foundStudy);
846                 // Check removal of relations to validation cycle
847                 List found = ht.find("from ValidationCycleRelation where owner="
848                                 + studyId);
849                 Assert.assertEquals(found.size(), 0,
850                                 "ValidationCycleRelation is not removed");
851                 // Check removal of validation cycles
852                 found = ht.find("from ValidationCycle where rid=" + cycle.getIndex());
853                 Assert.assertEquals(found.size(), 0, "ValidationCycle is not removed");
854                 // Check removal of contributors relation
855                 found = ht.find("from ContributorRelation where owner=" + studyId);
856                 Assert.assertEquals(found.size(), 0,
857                                 "ContributorRelation is not removed");
858                 // Check that contributors are not removed
859                 User foundUser = ht.get(User.class, otherUser.getIndex());
860                 Assert.assertNotNull(foundUser);
861                 // Check removal of the scenario
862                 found = ht.find("from Scenario where owner=" + studyId);
863                 Assert.assertEquals(found.size(), 0, "Scenario is not removed");
864                 // Check removal of publications
865                 found = ht
866                                 .find("from Publication pub left join pub.owner as own where own.rid="
867                                                 + studyId + " or own.rid=" + scen.getIndex());
868                 Assert.assertEquals(found.size(), 0, "Publication is not removed");
869                 found = ht.find("from Publication");
870                 Assert.assertEquals(found.size(), 0, "Publication is not removed");
871                 // Check removal of documents
872                 found = ht.find("from Document");
873                 Assert.assertEquals(found.size(), 0, "Document is not removed");
874                 // Check removal of version relations
875                 found = ht.find("from VersionsRelation");
876                 Assert.assertEquals(found.size(), 0, "VersionsRelation is not removed");
877                 // Check removal of converts relations
878                 found = ht.find("from ConvertsRelation");
879                 Assert.assertEquals(found.size(), 0, "ConvertsRelation is not removed");
880                 // Check removal of files
881                 found = ht.find("from File");
882                 Assert.assertEquals(found.size(), 0, "File is not removed");
883                 // Check removal of uses relations
884                 found = ht.find("from UsesRelation");
885                 Assert.assertEquals(found.size(), 0, "UsesRelation is not removed");
886                 // Check removal of usedBy relations
887                 found = ht.find("from UsedByRelation");
888                 Assert.assertEquals(found.size(), 0, "UsedByRelation is not removed");
889
890                 rollbackNestedTransaction();
891                 LOG.debug(">>>>> END testRemoveStudy()");
892         }
893
894         /**
895          * Create a new version of the document.
896          * 
897          * @param pub
898          *            the current document publication
899          * @return the new document version publication
900          * @throws IOException
901          *             if versioning is failed
902          * @throws BusinessException
903          *             if versioning is failed
904          */
905         private Publication version(final Publication pub)
906                         throws BusinessException, IOException {
907                 Document.Properties dprop = new Document.Properties();
908                 dprop.setDocument(pub.value(), pub.getStep().getStep());
909                 Publication newpub = _stepService.versionDocument(pub.getStep(), pub,
910                                 dprop);
911                 pub.getOwner().getDocums().remove(pub);
912                 pub.getStep().getDocuments().remove(pub);
913                 pub.getOwner().add(newpub);
914                 pub.getStep().getDocuments().add(newpub);
915                 return newpub;
916         }
917
918         /**
919          * Create a document and publish it in the project element.
920          * 
921          * @param aStudy
922          *            the project element
923          * @param stStep
924          * @param docname
925          *            document name
926          * @param dtype
927          *            document type
928          * @return publication of the created document
929          * @throws BusinessException
930          *             if document creation is failed
931          * @throws IOException
932          *             if file creation is failed
933          */
934         private Publication addDoc(final ProjectElement aStudy,
935                         final String docname, final DocumentType dtype)
936                         throws BusinessException, IOException {
937                 HibernateTemplate ht = getHibernateTemplate();
938                 // Add documents to the first study activity
939                 org.splat.som.Step aStep = _projectElementService.getFirstStep(aStudy);
940                 Document.Properties dprop = new Document.Properties().setAuthor(
941                                 aStudy.getAuthor()).setDate(new Date()).setName(docname)
942                                 .setType(dtype).setFormat("py");
943                 dprop.setLocalPath(dprop.getName() + "." + dprop.getFormat());
944                 dprop.setStep(aStep.getStep());
945                 Publication pub = _stepService.createDocument(aStep, dprop);
946                 pub.setStep(aStep);
947                 aStudy.add(pub);
948                 aStep.getDocuments().add(pub);
949                 ht.saveOrUpdate(pub);
950                 ht.save(pub.value());
951                 // Add a converts relation
952                 // Attach a med file
953                 ht.saveOrUpdate(_publicationService.attach(pub, "med"));
954                 createDownloadedFile(aStudy.getAuthor().getIndex(), dprop
955                                 .getLocalPath());
956                 createDownloadedFile(aStudy.getAuthor().getIndex(), dprop
957                                 .getLocalPath().substring(0,
958                                                 dprop.getLocalPath().lastIndexOf(".") - 1), "med");
959                 return pub;
960         }
961
962         /**
963          * Create a file in the user's repository downloads directory.
964          * 
965          * @param userId
966          *            user id
967          * @param name
968          *            file name
969          * @param format
970          *            file extension
971          * @return created file DTO
972          * @throws IOException
973          *             if file creation failed
974          */
975         private FileDTO createDownloadedFile(final long userId, final String name,
976                         final String format) throws IOException {
977                 // Create a file in the download directory
978                 return createDownloadedFile(userId, name + "." + format);
979         }
980
981         /**
982          * Get path to the user's downloads directory. The directory is created if it is not exist yet.
983          * 
984          * @param userId
985          *            user id
986          * @return absolute path to downloads directory followed by slash
987          */
988         private String getDownloadPath(final long userId) {
989                 // Prepare download directory
990                 File tmpDir = _repositoryService.getDownloadDirectory(userId);
991                 if (!tmpDir.exists()) {
992                         Assert.assertTrue(tmpDir.mkdir(),
993                                         "Can't create temporary directory: "
994                                                         + tmpDir.getAbsolutePath());
995                 }
996
997                 return tmpDir.getAbsolutePath() + "/";
998         }
999
1000         /**
1001          * Create a file in the user's repository downloads directory.
1002          * 
1003          * @param userId
1004          *            user id
1005          * @param fname
1006          *            file name
1007          * @return created file DTO
1008          * @throws IOException
1009          *             if file creation failed
1010          */
1011         private FileDTO createDownloadedFile(final long userId, final String fname)
1012                         throws IOException {
1013                 // Create a file in the download directory
1014                 String filePath = getDownloadPath(userId) + fname;
1015                 FileWriter fw = new FileWriter(filePath);
1016                 fw.write("Simulation of " + fname + " file for checkin at "
1017                                 + new Date());
1018                 fw.close();
1019                 return new FileDTO(filePath);
1020         }
1021
1022         @Test
1023         public void testReaders() throws InvalidPropertyException, BusinessException {
1024                 LOG.debug(">>>>> BEGIN testReaders()");
1025                 startNestedTransaction();
1026
1027                 HibernateTemplate ht = getHibernateTemplate();
1028
1029                 User user = TestEntitiesGenerator.getTestUser("GoodUser");
1030                 _userDAO.create(user);
1031                 Study study = TestEntitiesGenerator.getTestStudy(user);
1032                 _studyDAO.create(study);
1033                 _studyDAO.flush();
1034                 ht.clear();
1035                 long studyId = study.getIndex();
1036                 long userId = user.getIndex();
1037                 
1038                 //get a non-existing user id
1039                 User nonExistingUser = TestEntitiesGenerator.getTestUser("nonExistingUser");
1040                 _userDAO.create(nonExistingUser);
1041                 long nonExistingUserId = nonExistingUser.getIndex();
1042                 _userDAO.delete(nonExistingUser);
1043                 _userDAO.flush();
1044                 ht.clear();
1045
1046                 //get a non-existing study id
1047                 Study nonExistingStudy = TestEntitiesGenerator.getTestStudy(user);
1048                 _studyDAO.create(nonExistingStudy);
1049                 long nonExistingStudyId = nonExistingStudy.getIndex();
1050                 _studyDAO.delete(nonExistingStudy);
1051                 _userDAO.flush();
1052                 ht.clear();
1053
1054
1055         //  ==============================================================================================================================
1056         //  1.Non-existing user and study ids
1057         //  ==============================================================================================================================
1058
1059                 //Test getReaders method with a non-existing study id
1060                 try {
1061                         _studyService.getReaders(nonExistingStudyId);
1062                         Assert.fail("retrieval of readers with non-existing study id " +
1063                                         "must throw InvalidParameterException");
1064                 } catch(InvalidParameterException e) {
1065                         LOG.debug("Expected exception is thrown: "
1066                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
1067                 }
1068                 
1069                 //Test removeReader method with a non-existing study id
1070                 try {
1071                         _studyService.removeReader(nonExistingStudyId, userId);
1072                         Assert.fail("attempt to remove from readers with non-existing study id " +
1073                                         "must throw InvalidParameterException");
1074                 } catch(InvalidParameterException e) {
1075                         LOG.debug("Expected exception is thrown: "
1076                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
1077                 }
1078                 
1079                 //Test removeReader method with an non-existing user id
1080                 try {
1081                         _studyService.removeReader(studyId, nonExistingUserId);
1082                         Assert.fail("attempt to remove from readers with non-existing user id " +
1083                                         "must throw InvalidParameterException");                
1084                 } catch(InvalidParameterException e) {
1085                         LOG.debug("Expected exception is thrown: "
1086                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
1087                 }
1088
1089                 //Test addReader method with a non-existing study id
1090                 try {
1091                         _studyService.addReader(nonExistingStudyId, userId);
1092                         Assert.fail("attempt to add a user to readers of a study with non-existing study id " +
1093                                         "must throw InvalidParameterException");
1094                 } catch(InvalidParameterException e) {
1095                         LOG.debug("Expected exception is thrown: "
1096                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
1097                 }
1098                 
1099                 //Test addReader method with a non-existing user id
1100                 try {
1101                         _studyService.addReader(studyId, nonExistingUserId);
1102                         Assert.fail("attempt to add to readers a user with non-existing id " +
1103                                         "must throw InvalidParameterException");
1104                 } catch(InvalidParameterException e) {
1105                         LOG.debug("Expected exception is thrown: "
1106                                         + e.getClass().getSimpleName() + ": " + e.getMessage());
1107                 }
1108
1109                 //  ==============================================================================================================================
1110                 //  2.Existing user who is not yet reader
1111                 //  ==============================================================================================================================
1112
1113                 //Test getReaders method with no readers
1114                 Assert.assertTrue(_studyService.getReaders(studyId).isEmpty(),
1115                                 "returned list for a study without readers must be empty");
1116                 
1117                 //Test removeReader method with an existing user who is not reader
1118                 Assert.assertFalse(_studyService.removeReader(studyId, userId),
1119                                 "attempt to remove from readers of a non-reader user must return false");
1120                 
1121                 //ADD A READER:
1122                 //Test addReader method with an existing user who is not yet reader
1123                 Assert.assertTrue(_studyService.addReader(studyId, userId),
1124                                 "addition of a user who is not yet reader must return true");
1125                 
1126                 _studyDAO.flush();
1127                 ht.clear();
1128                 study = _studyDAO.get(studyId);
1129                 
1130                 List<Relation> readerRelations = study.getRelations(ReaderRelation.class);
1131                 Assert.assertTrue(readerRelations.size() == 1, "The retrieved relations list has wrong size");
1132                 Assert.assertEquals(readerRelations.get(0).getFrom(), study,
1133                                 "the retrieved relation does not equal the one that has been added.");
1134                 Assert.assertEquals(readerRelations.get(0).getTo(), user,
1135                                 "the retrieved relation does not equal the one that has been added.");
1136
1137
1138                 //  ==============================================================================================================================
1139                 //  3.Existing reader
1140                 //  ==============================================================================================================================
1141
1142                 //Test getReaders method with an existing reader
1143                 List<UserDTO> readers = _studyService.getReaders(studyId);
1144                 Assert.assertTrue(readers.size() == 1, "The retrieved reader list has wrong size");
1145                 Assert.assertEquals(readers.get(0), BeanHelper.copyBean(user, UserDTO.class),
1146                                 "the retrieved user does not equal the one that has been added.");
1147
1148                 //Test addReader method with a user who is already reader
1149                 Assert.assertFalse(_studyService.addReader(studyId, userId),
1150                                 "addition of a user who is already reader must return false");
1151                 
1152                 //Test removeReader method with a user user who is already reader
1153                 Assert.assertTrue(_studyService.removeReader(studyId, userId),
1154                                 "removal from readers of a user who is study reader must return true");
1155                 Assert.assertTrue(study.getRelations(ReaderRelation.class).isEmpty(),
1156                                 "a relation has not been properly removed");
1157
1158                 rollbackNestedTransaction();
1159                 LOG.debug(">>>>> END testReaders()");
1160         }
1161 }