1 /*****************************************************************************
5 * Creation date 12 Oct 2012
8 *****************************************************************************/
9 package test.splat.service;
12 import java.io.FileNotFoundException;
13 import java.io.FileWriter;
14 import java.io.IOException;
15 import java.sql.SQLException;
16 import java.util.ArrayList;
17 import java.util.Date;
18 import java.util.List;
20 import org.splat.dal.bo.kernel.User;
21 import org.splat.dal.bo.som.Document;
22 import org.splat.dal.bo.som.DocumentType;
23 import org.splat.dal.bo.som.Publication;
24 import org.splat.dal.bo.som.Scenario;
25 import org.splat.dal.bo.som.Study;
26 import org.splat.dal.bo.som.Document.Properties;
27 import org.splat.dal.dao.som.Database;
28 import org.splat.dal.dao.som.ScenarioDAO;
29 import org.splat.kernel.InvalidPropertyException;
30 import org.splat.kernel.MismatchException;
31 import org.splat.kernel.MissedPropertyException;
32 import org.splat.kernel.MultiplyDefinedException;
33 import org.splat.kernel.NotApplicableException;
34 import org.splat.log.AppLogger;
35 import org.splat.service.DocumentTypeService;
36 import org.splat.service.PublicationService;
37 import org.splat.service.ScenarioService;
38 import org.splat.service.StepService;
39 import org.splat.service.dto.DocumentDTO;
40 import org.splat.service.dto.FileDTO;
41 import org.splat.service.dto.StepDTO;
42 import org.splat.service.technical.ProjectSettingsService;
43 import org.splat.service.technical.RepositoryService;
44 import org.splat.service.technical.ProjectSettingsService.Step;
45 import org.springframework.beans.factory.annotation.Autowired;
46 import org.springframework.beans.factory.annotation.Qualifier;
47 import org.springframework.orm.hibernate3.HibernateTemplate;
48 import org.testng.Assert;
49 import org.testng.annotations.Test;
51 import test.splat.common.BaseTest;
54 * Test class for KnowledgeElementDAO.
56 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
59 public class TestScenarioService extends BaseTest {
62 * Logger for the class.
64 private static final AppLogger LOG = AppLogger
65 .getLogger(TestScenarioService.class);
68 * The tested ScenarioService. Later injected by Spring.
71 @Qualifier("scenarioService")
72 private transient ScenarioService _scenarioService;
75 * The RepositoryService. Later injected by Spring.
78 @Qualifier("repositoryService")
79 private transient RepositoryService _repositoryService;
82 * The Scenario DAO. Later injected by Spring.
85 @Qualifier("scenarioDAO")
86 private transient ScenarioDAO _scenarioDAO;
89 * The PublicationService. Later injected by Spring.
92 @Qualifier("publicationService")
93 private transient PublicationService _publicationService;
96 * The StepService. Later injected by Spring.
99 @Qualifier("stepService")
100 private transient StepService _stepService;
103 * The ProjectSettingsService. Later injected by Spring.
106 @Qualifier("projectSettings")
107 private transient ProjectSettingsService _projectSettings;
110 * The DocumentTypeService. Later injected by Spring.
113 @Qualifier("documentTypeService")
114 private transient DocumentTypeService _documentTypeService;
117 * Test of getting a scenario content for building siman-salome.conf.<BR>
118 * <B>Description :</B> <BR>
119 * <i>Create a scenario and try to get an info for it.</i><BR>
120 * <B>Action : </B><BR>
121 * <i>1. call the method for an existing scenario id.</i><BR>
122 * <i>2. call the method for a not existing scenario id.</i><BR>
123 * <B>Test data : </B><BR>
124 * <i>no input parameters</i><BR>
125 * <i>no input parameters</i><BR>
127 * <B>Outcome results:</B><BR>
130 * <li>result DTO must contain list of all documents and files<BR>
132 * <li>Exception is thrown<BR>
137 * @throws InvalidPropertyException
138 * if an invalid property is used when creating objects
139 * @throws MultiplyDefinedException
140 * when trying to create an object with already existing id
141 * @throws MissedPropertyException
142 * if a mandatory property is not defined for an object to be created
143 * @throws IOException
144 * if scenario creation is failed
145 * @throws SQLException
146 * if scenario creation is failed
149 public void testGetScenarioInfo() throws InvalidPropertyException,
150 MissedPropertyException, MultiplyDefinedException, IOException,
152 LOG.debug(">>>>> BEGIN testGetScenarioInfo()");
153 long scenarioId = createScenario();
154 // Call DAO's create method for a good transient knowledge element.
155 List<StepDTO> steps = _scenarioService.getScenarioInfo(scenarioId);
156 Assert.assertNotNull(steps, "List of steps must not be null.");
157 Assert.assertTrue(steps.size() > 0, "No steps are read.");
159 List<Step> projSteps = _projectSettings.getStepsOf(Scenario.class);
160 Assert.assertEquals(steps.size(), projSteps.size(),
161 "Not all steps are listed.");
163 for (StepDTO step : steps) {
164 LOG.debug("check the step " + step.getNumber() + ":\n" + step);
165 Assert.assertNotNull(step, "Step DTO must not be null.");
166 Assert.assertNotNull(step.getKey(), "Step name must not be null.");
167 Assert.assertFalse(step.getKey().isEmpty(),
168 "Step name must not empty.");
169 Assert.assertTrue(step.getNumber() > 0,
170 "Step number must be positive integer.");
171 Assert.assertNotNull(step.getDocs(),
172 "Step documents list must not be null.");
174 Step aProjStep = null;
175 for (Step projStep : projSteps) {
176 if (projStep.getNumber() == step.getNumber()) {
177 aProjStep = projStep;
182 List<DocumentType> dtypes = _documentTypeService
183 .selectTypesOf(aProjStep);
184 for (DocumentType dtype : dtypes) {
185 Assert.assertTrue(step.getDocs().size() > 0,
186 "Step documents list must not be empty.");
187 String docName = "document" + docIndex;
188 for (DocumentDTO doc : step.getDocs()) {
189 if (docName.equals(doc.getTitle())) {
190 Assert.assertTrue(doc.getId() > 0,
191 "Document id must be positive integer.");
192 Assert.assertEquals(doc.getTitle(), docName);
193 Assert.assertNotNull(doc.getFiles(),
194 "Document files list must not be null.");
196 .assertTrue(doc.getFiles().size() > 1,
197 "Document must have more then 1 attached file.");
199 for (FileDTO file : doc.getFiles()) {
200 Assert.assertNotNull(file.getPath(),
201 "File path must not be null.");
202 Assert.assertFalse(file.getPath().isEmpty(),
203 "File path must not be empty.");
205 * <mappings> <document type="geometry"> <import format="brep"/> <!-- Result Shape --> </document> <document
206 * type="model"> <import format="med"/> <!-- Result mesh without input parameters --> </document> <document
207 * type="loads"> <import format="c3m"/> <!-- Input data created interactively --> </document> <document
208 * type="results"> <import format="med"/> <!-- Calculation results source file --> </document> </mappings>
210 // Check state and processing instruction
211 String fileFormat = file.getPath().substring(
212 file.getPath().lastIndexOf('.') + 1);
214 * if (_projectSettings.doImport(dtype.getName(), fileFormat)) { Assert.assertTrue(file.isResult(), "The file
215 * must be a result file."); } else { Assert.assertFalse(file.isResult(), "The file must be a source file."); }
216 */if ((docIndex % 2) == 0) { // New
217 Assert.assertEquals(file.getState(), 'Y',
218 "File state must be actual ('Y').");
219 if (_projectSettings.doImport(dtype.getName(),
221 Assert.assertEquals(file.getProcessing(),
223 "File must be imported.");
225 Assert.assertEquals(file.getProcessing(),
227 "File must be downloaded.");
230 Assert.assertEquals(file.getState(), 'O',
231 "File state must be actual ('O').");
233 .assertEquals(file.getProcessing(),
235 "Outdated document should not be imported but downloaded.");
244 // Call DAO's get method for a not existing id.
246 steps = _scenarioService.getScenarioInfo(-1L);
247 // getHibernateTemplate().flush();
249 .fail("Getting an object with not existing id must be failed.");
250 } catch (Exception e) {
251 LOG.debug("Expected exception is thrown: "
252 + e.getClass().getSimpleName() + ": " + e.getMessage());
254 LOG.debug(">>>>> END testGetScenarioInfo()");
258 * Test check-in scenario operation to be performed after SALOME session.<BR>
259 * <B>Description :</B> <BR>
260 * <i>Create a scenario and try to check-in it with some simulated SALOME results data.<BR>
261 * After check-in verify following points:
263 * <li>scenario is no more marked as checked out</li>
264 * <li>new document versions are created for checked in documents</li>
265 * <li>presentation of the previous version is removed</li>
266 * <li>uses relations are copied correctly</li>
267 * <li>files are moved correctly</li>
268 * <li>new documents are created for new data</li>
269 * <li>uses relations are created correctly</li>
270 * <li>files are moved correctly</li>
273 * <B>Action : </B><BR>
274 * <i>1. call the method for an existing scenario id.</i><BR>
275 * <i>2. call the method for a not existing scenario id.</i><BR>
276 * <B>Test data : </B><BR>
277 * <i>no input parameters</i><BR>
278 * <i>no input parameters</i><BR>
280 * <B>Outcome results:</B><BR>
283 * <li>New version of existing documents must be created and new documents must be imported for documents with zero id. Correct
284 * relations must be created.<BR>
286 * <li>Exception is thrown<BR>
291 * @throws InvalidPropertyException
292 * if an invalid property is used when creating objects
293 * @throws MultiplyDefinedException
294 * when trying to create an object with already existing id
295 * @throws MissedPropertyException
296 * if a mandatory property is not defined for an object to be created
297 * @throws IOException
298 * if scenario creation is failed
299 * @throws SQLException
300 * if scenario creation is failed
301 * @throws NotApplicableException
303 * @throws MismatchException
307 public void testCheckin() throws InvalidPropertyException,
308 MissedPropertyException, MultiplyDefinedException, IOException,
309 SQLException, MismatchException, NotApplicableException {
310 LOG.debug(">>>>> BEGIN testCheckin()");
311 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
312 _projectSettings.configure(ClassLoader
313 .getSystemResource("test/som.xml").getPath());
314 long scenarioId = createScenario();
315 Scenario aScen = _scenarioDAO.get(scenarioId);
316 User user = aScen.getAuthor();
317 long userId = user.getIndex();
319 // ////////////////////////////////////////////////////////
320 // Call checkin method for good prepared transient data.
323 List<StepDTO> steps = _scenarioService.getScenarioInfo(scenarioId);
324 _scenarioService.checkout(aScen, user);
326 // Prepare test data for checkin
327 // Checkin only two first steps (geom and mesh)
328 List<StepDTO> stepsToCheckin = new ArrayList<StepDTO>();
329 for (StepDTO step : steps) {
330 // Prepare GEOM: checkin actual brep
331 StepDTO stepToCheckin = createDocDTOForModule(null, "GEOM", "brep",
332 userId, step, stepsToCheckin);
333 createDocDTOForModule(stepToCheckin, "SMESH", "med", userId, step,
337 _scenarioService.checkin(scenarioId, userId, stepsToCheckin);
339 // Check that scenario is no more marked as checked out
340 aScen = _scenarioDAO.get(scenarioId);
341 Assert.assertFalse(aScen.isCheckedout(),
342 "Scenario is still marked as checked out after checkin.");
343 // Check that new document versions are created for checked in documents
344 for (StepDTO step : stepsToCheckin) {
345 for (DocumentDTO docDTO : step.getDocs()) {
346 if (docDTO.getId() != 0) {
347 boolean found = false;
348 Document prevDoc = null;
349 Publication newPub = null;
350 for (Publication pub : aScen.getDocums()) {
351 prevDoc = pub.value().getPreviousVersion();
352 if (prevDoc != null) {
353 found = (prevDoc.getIndex() == docDTO.getId());
354 if (found) { // Found next published version of the checked in document
360 Assert.assertTrue(found,
361 "New version of existing checked in document \""
362 + docDTO.getTitle() + "\" (id="
364 + ") is not found in the scenario.");
365 // Check that presentation of the previous version is removed
366 Assert.assertFalse(aScen.publishes(prevDoc));
367 // Check that files are moved correctly
368 for (int j = 0; j < docDTO.getFiles().size(); j++) {
369 FileDTO fileDTO = docDTO.getFiles().get(j);
372 new File(fileDTO.getPath()).exists(),
375 + " was not removed from downloads directory.");
376 String format = fileDTO.getPath().substring(
377 fileDTO.getPath().lastIndexOf('.') + 1);
379 // Check file by its internal content
380 // Check that uses relations are copied correctly
383 // Check that new documents are created for new data
384 boolean found = false;
385 Publication newPub = null;
386 for (Publication pub : aScen.getDocums()) {
387 if (pub.value().getPreviousVersion() == null) {
388 found = (docDTO.getTitle().equals(pub.value()
390 if (found) { // Found next published version of the checked in document
396 Assert.assertTrue(found,
397 "New document is not created for checked in document \""
398 + docDTO.getTitle() + "\".");
399 // Check that uses relations are created correctly
400 // Check that files are moved correctly
406 // ///////////////////////////////////////////////////////////
407 // Call checkin method for a not existing id.
409 _scenarioService.checkin(-1, userId, stepsToCheckin);
411 .fail("Check in for scenario with not existing id must be failed.");
412 } catch (Exception e) {
413 LOG.debug("Expected exception is thrown: "
414 + e.getClass().getSimpleName() + ": " + e.getMessage());
417 LOG.debug(">>>>> END testCheckin()");
421 * Prepare a document with a file for check-in.
424 * step DTO with data for check-in
432 * checked out stepDTO
433 * @param stepsToCheckin
435 * @throws IOException
436 * if file creation failed
437 * @return step DTO with data prepared for check-in (stepTo or new if stepTo is null)
439 private StepDTO createDocDTOForModule(final StepDTO stepTo,
440 final String module, final String format, final long userId,
441 final StepDTO stepFrom, final List<StepDTO> stepsToCheckin)
443 StepDTO stepToCheckin = stepTo;
444 if (stepToCheckin == null) {
445 stepToCheckin = new StepDTO();
447 if (module.equals(stepFrom.getModule())) {
448 stepsToCheckin.add(stepToCheckin);
449 stepToCheckin.setNumber(stepFrom.getNumber());
450 for (DocumentDTO doc : stepFrom.getDocs()) {
451 if (doc.getFiles().get(0).getState() != 'O') {
452 DocumentDTO docToCheckin = stepToCheckin.addDoc(
453 doc.getId(), doc.getTitle());
454 for (FileDTO file : doc.getFiles()) {
455 if (file.getPath().endsWith(format)) {
456 // Create a file in the download directory
457 docToCheckin.addFile(createDownloadedFile(userId,
458 doc.getTitle() + "_result", format));
464 stepToCheckin.addDoc(0, "newdoc" + stepFrom.getNumber()).addFile(
465 createDownloadedFile(userId, "newdoc"
466 + stepFrom.getNumber(), "brep"));
468 return stepToCheckin;
472 * Create a file in the user's repository downloads directory.
480 * @return created file DTO
481 * @throws IOException
482 * if file creation failed
484 private FileDTO createDownloadedFile(final long userId, final String name,
485 final String format) throws IOException {
486 // Create a file in the download directory
487 String filePath = getDownloadPath(userId) + name + "." + format;
488 FileWriter fw = new FileWriter(filePath);
489 fw.write("Simulation of " + name + "." + format
490 + " file for checkin at " + new Date());
492 return new FileDTO(filePath);
496 * Get path to the user's downloads directory. The directory is created if it is not exist yet.
500 * @return absolute path to downloads directory followed by slash
502 private String getDownloadPath(final long userId) {
503 // Prepare download directory
504 File tmpDir = _repositoryService.getDownloadDirectory(userId);
505 if (!tmpDir.exists()) {
506 Assert.assertTrue(tmpDir.mkdir(),
507 "Can't create temporary directory: "
508 + tmpDir.getAbsolutePath());
511 return tmpDir.getAbsolutePath() + "/";
515 * Create a persistent scenario for tests.
517 * @return a persistent scenario
518 * @throws InvalidPropertyException
519 * if an invalid property is used when creating objects
520 * @throws MultiplyDefinedException
521 * when trying to create an object with already existing id
522 * @throws MissedPropertyException
523 * if a mandatory property is not defined for an object to be created
524 * @throws IOException
525 * if document creation is failed
526 * @throws SQLException
527 * if project settings loading is failed
529 private long createScenario() throws InvalidPropertyException,
530 MissedPropertyException, MultiplyDefinedException, IOException,
532 // Create a scenario for tests
533 HibernateTemplate ht = getHibernateTemplate();
535 Database.getInstance().reset();
536 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
537 // Load workflow customization
539 _projectSettings.configure(ClassLoader.getSystemResource(
540 "test/som.xml").getPath());
541 } catch (FileNotFoundException e) {
542 Assert.fail("Can't find som.xml: ", e);
544 List<Step> steps = _projectSettings.getStepsOf(Scenario.class);
545 Assert.assertTrue(steps.size() > 0, "No steps are created.");
547 // Create a test user
548 User.Properties uprop = new User.Properties();
549 uprop.setUsername("TST_Username").setName("TST_SimanUnitTestsUser")
550 .setFirstName("TST_FirstName").setDisplayName("TST_test.user")
551 .addRole("TST_user").setMailAddress(
552 "noreply@salome-platform.org");
553 uprop.disableCheck();
554 User anAuthor = new User(uprop);
557 // Create a test study
558 Study.Properties stprops = new Study.Properties().setReference(
559 "TST_SID_01").setTitle("TST_Study").setManager(anAuthor);
560 Study aStudy = new Study(stprops);
561 ht.saveOrUpdate(aStudy);
563 // Create a test scenario
564 Scenario.Properties sprops = new Scenario.Properties().setTitle(
565 "TST_Scenario").setManager(anAuthor).setOwnerStudy(aStudy);
566 Scenario aScenario = new Scenario(sprops);
567 aStudy.getScenariiList().add(aScenario);
568 ht.saveOrUpdate(anAuthor);
569 ht.saveOrUpdate(aStudy);
570 ht.saveOrUpdate(aScenario);
572 // Create documents for each scenario step
573 Document.Properties dprop = new Document.Properties().setAuthor(
574 anAuthor).setDate(new Date());
576 for (Step step : steps) {
577 LOG.debug("Create scenario step: " + i);
579 org.splat.som.Step aScStep = new org.splat.som.Step(step, aScenario);
580 List<DocumentType> dtypes = _documentTypeService
581 .selectTypesOf(step);
582 for (DocumentType dtype : dtypes) {
583 // Create a document published in the scenario
584 // document<i>: document type[0] - first type used on the step
585 // <source-file>.brep
586 // <attached-file>.med
587 dprop.setName("document" + i++).setType(dtype);
588 if (step.getNumber() > 3) {
589 dprop.setFormat("med");
591 dprop.setFormat("brep");
593 createDoc(aScenario, aScStep, dprop, "med", false);
595 // Create another document with outdated publication
596 dprop.setName("document" + i++).setType(dtype)
598 createDoc(aScenario, aScStep, dprop, "med", true);
601 if (dtypes.size() <= 0) {
602 LOG.debug("No document types are found for scenario step " + i);
606 // Check that the scenario and its documents have been created correctly.
608 Assert.assertNotNull(ht.find("from Document"),
609 "No documents in the database.");
610 Assert.assertTrue(ht.find("from Document").size() > 0,
611 "No documents in the database.");
613 Assert.assertNotNull(ht.find("from Publication where owner="
614 + aScenario.getIndex()), "No publications in the database.");
616 ht.find("from Publication where owner=" + aScenario.getIndex())
617 .size() > 0, "No publications in the database.");
619 for (Publication p : (List<Publication>) ht
620 .find("from Publication where owner=" + aScenario.getIndex())) {
621 LOG.debug("Publication found: [id=" + p.getIndex() + ", owner="
622 + p.getOwner().getIndex() + ", doc=" + p.value().getIndex()
624 Assert.assertEquals(p.getOwner().getIndex(), aScenario.getIndex(),
625 "The publication was not attached to the scenario.");
628 // Remove the scenario from the current hibernate session.
630 // Check that the scenario is created in the database.
631 Scenario aScen = ht.load(Scenario.class, aScenario.getIndex());
632 Assert.assertNotNull(aScen, "Scenario was not saved in the database.");
633 Assert.assertTrue(aScen.getDocums().size() > 0,
634 "No publications in the scenario.");
636 Assert.assertTrue(i > 0,
637 "More then one document must be in the database");
639 return aScenario.getIndex();
643 * Create a document published in the scenario. <BR>
645 * document type[0] - first type used on the step <BR>
646 * <source-file>.brep <BR>
647 * <attached-file>.med
650 * the scenario to add the document to
652 * scenario step where the document to be published
654 * document properties
655 * @param attachedFileExt
656 * extension of the secon attached (exported) file
658 * outdated document flag
659 * @return the publication of the created document
660 * @throws IOException
661 * @throws MultiplyDefinedException
662 * @throws InvalidPropertyException
663 * @throws MissedPropertyException
665 private Publication createDoc(final Scenario aScenario,
666 final org.splat.som.Step aScStep, final Properties dprop,
667 final String attachedFileExt, final boolean isOutdated)
668 throws MissedPropertyException, InvalidPropertyException,
669 MultiplyDefinedException, IOException {
670 // Create a document published in the scenario
671 // document<i>: document type[0] - first type used on the step
672 // <source-file>.brep
673 // <attached-file>.med
674 Publication pub = _stepService.createDocument(aScStep, dprop);
675 Assert.assertNotNull(pub.getOwner(),
676 "The publication must be attached to the scenario.");
677 Assert.assertEquals(pub.getOwner().getIndex(), aScenario.getIndex(),
678 "The publication was not attached to the scenario.");
684 HibernateTemplate ht = getHibernateTemplate();
685 ht.saveOrUpdate(pub);
688 ht.save(pub.value());
689 ht.saveOrUpdate(_publicationService.attach(pub, attachedFileExt));