1 /*****************************************************************************
5 * Creation date 12 Oct 2012
8 *****************************************************************************/
9 package test.splat.service;
11 import java.io.FileNotFoundException;
12 import java.io.IOException;
13 import java.sql.SQLException;
14 import java.util.ArrayList;
15 import java.util.Date;
16 import java.util.HashMap;
17 import java.util.List;
20 import org.splat.dal.bo.kernel.User;
21 import org.splat.dal.bo.som.ConvertsRelation;
22 import org.splat.dal.bo.som.Document;
23 import org.splat.dal.bo.som.DocumentType;
24 import org.splat.dal.bo.som.File;
25 import org.splat.dal.bo.som.ProjectElement;
26 import org.splat.dal.bo.som.Publication;
27 import org.splat.dal.bo.som.Scenario;
28 import org.splat.dal.bo.som.Study;
29 import org.splat.dal.bo.som.UsedByRelation;
30 import org.splat.dal.bo.som.UsesRelation;
31 import org.splat.dal.bo.som.Document.Properties;
32 import org.splat.dal.dao.som.Database;
33 import org.splat.dal.dao.som.FileDAO;
34 import org.splat.dal.dao.som.ScenarioDAO;
35 import org.splat.exception.BusinessException;
36 import org.splat.exception.DocumentIsUsedException;
37 import org.splat.kernel.InvalidPropertyException;
38 import org.splat.kernel.MissedPropertyException;
39 import org.splat.kernel.MultiplyDefinedException;
40 import org.splat.log.AppLogger;
41 import org.splat.service.DocumentTypeService;
42 import org.splat.service.PublicationService;
43 import org.splat.service.StepService;
44 import org.splat.service.StudyService;
45 import org.splat.service.technical.ProjectSettingsService;
46 import org.splat.service.technical.ProjectSettingsService.Step;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.beans.factory.annotation.Qualifier;
49 import org.springframework.orm.hibernate3.HibernateTemplate;
50 import org.testng.Assert;
51 import org.testng.annotations.Test;
53 import test.splat.common.BaseTest;
56 * Test class for StepService.
58 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
61 public class TestStepService extends BaseTest {
64 * Logger for the class.
66 private static final AppLogger LOG = AppLogger
67 .getLogger(TestStepService.class);
70 * The StudyService. Later injected by Spring.
73 @Qualifier("studyService")
74 private transient StudyService _studyService;
77 * The Scenario DAO. Later injected by Spring.
80 @Qualifier("scenarioDAO")
81 private transient ScenarioDAO _scenarioDAO;
84 * The File DAO. Later injected by Spring.
88 private transient FileDAO _fileDAO;
91 * The PublicationService. Later injected by Spring.
94 @Qualifier("publicationService")
95 private transient PublicationService _publicationService;
98 * The StepService. Later injected by Spring.
101 @Qualifier("stepService")
102 private transient StepService _stepService;
105 * The ProjectSettingsService. Later injected by Spring.
108 @Qualifier("projectSettings")
109 private transient ProjectSettingsService _projectSettings;
112 * The DocumentTypeService. Later injected by Spring.
115 @Qualifier("documentTypeService")
116 private transient DocumentTypeService _documentTypeService;
119 * Test removeDocument method.<BR>
120 * <B>Description :</B> <BR>
121 * <i>Create a scenario and try to remove documents from it.<BR>
123 * <B>Action : </B><BR>
124 * <i>1. call the method for all documents used by other document(s).</i><BR>
125 * <i>2. call the method for all documents starting from the last activity.</i><BR>
126 * <B>Test data : </B><BR>
127 * <i>no input parameters</i><BR>
128 * <i>no input parameters</i><BR>
130 * <B>Outcome results:</B><BR>
133 * <li>Exception DocumentIsUsedException is expected<BR>
135 * <li>All documents and their files and relations must be removed<BR>
140 * @throws BusinessException
141 * if scenario creation or checkin is failed
142 * @throws IOException
143 * if scenario creation is failed
144 * @throws SQLException
145 * if scenario creation is failed
148 public void testRemoveDocument() throws BusinessException, IOException,
150 LOG.debug(">>>>> BEGIN testRemoveDocument()");
151 startNestedTransaction();
153 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
154 _projectSettings.configure(ClassLoader
155 .getSystemResource("test/som.xml").getPath());
156 HibernateTemplate ht = getHibernateTemplate();
158 long scenarioId = createScenario();
160 _scenarioDAO.flush();
161 Scenario aScen = _scenarioDAO.get(scenarioId);
164 ht.evict(aScen.getOwnerStudy());
166 Assert.assertTrue(ht.find("from UsesRelation").size() > 0,
167 "Uses relations were not created in the database.");
169 Assert.assertTrue(ht.find("from UsedByRelation").size() > 0,
170 "UsedBy relations were not created in the database.");
172 ProjectElement projElem;
176 int nbDoc = ht.find("from Document").size();
177 int nbRemovedDoc = 0;
178 List<Long> removedDocs = new ArrayList<Long>();
180 // ////////////////////////////////////////////////////////
181 // Call removeDocument method for each document
182 // used by other document(s).
183 // Exception DocumentIsUsedException is expected
184 for (int i = 1; i <= _projectSettings.getAllSteps().size(); i++) {
185 LOG.debug("Remove used documents from the step " + i);
186 step = _projectSettings.getStep(i);
187 if (step.appliesTo(Study.class)) {
188 projElem = _studyService.selectStudy(aScen.getOwnerStudy()
194 org.splat.som.Step aScStep = new org.splat.som.Step(step, projElem);
196 if (aScStep.getDocuments().size() > 0) {
197 docId = aScStep.getDocuments().get(0).value().getIndex();
200 List<UsesRelation> uses = ht
201 .find("from UsesRelation where owner=" + docId);
202 List<UsedByRelation> usedBy = ht
203 .find("from UsedByRelation where owner=" + docId);
204 if (!usedBy.isEmpty()) {
205 int usesRefer = ht.find(
206 "from UsesRelation where refer=" + docId).size();
207 int usedByRefer = ht.find(
208 "from UsedByRelation where refer=" + docId).size();
209 int convertsNb = ht.find(
210 "from ConvertsRelation where owner=" + docId)
212 LOG.debug("Remove used document "
213 + aScStep.getDocument(docId).value().getTitle());
214 LOG.debug("From db: It uses following " + uses.size()
216 for (UsesRelation rel : uses) {
217 LOG.debug(rel.getTo().getTitle());
220 .debug("From step: It uses following "
221 + aScStep.getDocument(docId).value()
222 .getRelations(UsesRelation.class)
223 .size() + " documents: ");
224 for (Publication rel : aScStep.getDocument(docId)
225 .getRelations(UsesRelation.class)) {
226 LOG.debug(rel.value().getTitle());
228 LOG.debug("From db: It is used by following "
229 + usedBy.size() + " documents: ");
230 for (UsedByRelation rel : usedBy) {
231 LOG.debug(rel.getTo().getTitle());
233 LOG.debug("From step: It is used by following "
234 + aScStep.getDocument(docId).value().getRelations(
235 UsedByRelation.class).size()
237 for (Publication rel : aScStep.getDocument(docId)
238 .getRelations(UsedByRelation.class)) {
239 LOG.debug(rel.value().getTitle());
242 ok = _stepService.removeDocument(aScStep, docId);
243 Assert.fail("DocumentIsUsedException must be thrown.");
244 } catch (DocumentIsUsedException e) {
245 LOG.debug("Expected exception is thrown: "
246 + e.getLocalizedMessage());
248 _scenarioDAO.flush();
251 .assertEquals(ht.find(
252 "from UsesRelation where owner=" + docId)
253 .size(), uses.size(),
254 "UsesRelation(s) must not be changed.");
255 Assert.assertEquals(ht.find(
256 "from UsedByRelation where owner=" + docId).size(),
258 "UsedByRelation(s) must not be changed.");
259 Assert.assertEquals(ht.find(
260 "from UsesRelation where refer=" + docId).size(),
262 "Referencing UsesRelation(s) must not be changed.");
264 .assertEquals(ht.find(
265 "from UsedByRelation where refer=" + docId)
266 .size(), usedByRefer,
267 "Referencing UsedByRelation(s) must not be changed.");
268 Assert.assertEquals(ht.find(
269 "from ConvertsRelation where owner=" + docId)
271 "ConvertsRelation(s) must not be changed.");
276 // ////////////////////////////////////////////////////////
277 // Call removeDocument method for each document
278 // starting from the last activity.
279 for (int i = _projectSettings.getAllSteps().size(); i > 0; i--) {
280 LOG.debug("Remove documents from the step " + i);
281 step = _projectSettings.getStep(i);
282 if (step.appliesTo(Study.class)) {
283 projElem = _studyService.selectStudy(aScen.getOwnerStudy()
289 org.splat.som.Step aScStep = new org.splat.som.Step(step, projElem);
291 if (aScStep.getDocuments().size() > 0) {
292 docId = aScStep.getDocuments().get(0).value().getIndex();
293 LOG.debug("Remove document#" + docId + " "
294 + aScStep.getDocument(docId).value().getTitle());
296 List<UsesRelation> uses = ht
297 .find("from UsesRelation where owner=" + docId);
298 List<UsedByRelation> usedBy = ht
299 .find("from UsedByRelation where owner=" + docId);
300 LOG.debug("From db: It uses following " + uses.size()
302 for (UsesRelation rel : uses) {
303 LOG.debug(rel.getTo().getTitle());
305 LOG.debug("From step: It uses following "
306 + aScStep.getDocument(docId).getRelations(
307 UsesRelation.class).size() + " documents: ");
308 for (Publication rel : aScStep.getDocument(docId).getRelations(
309 UsesRelation.class)) {
310 LOG.debug(rel.value().getTitle());
312 LOG.debug("From db: It is used by following " + usedBy.size()
314 for (UsedByRelation rel : usedBy) {
315 LOG.debug(rel.getTo().getTitle());
317 LOG.debug("From step: It is used by following "
318 + aScStep.getDocument(docId).getRelations(
319 UsedByRelation.class).size() + " documents: ");
320 for (Publication rel : aScStep.getDocument(docId).getRelations(
321 UsedByRelation.class)) {
322 LOG.debug(rel.value().getTitle());
324 Assert.assertEquals(ht.find("from Document where rid=" + docId)
325 .size(), 1, "Nothing to delete.");
328 ht.evict(aScStep.getDocuments().get(0).value()
330 LOG.debug("Load file#" + aScStep.getDocuments().get(0).value()
331 .getRelations(ConvertsRelation.class).get(0).getTo().getIndex());
334 File f = _fileDAO.get(aScStep.getDocuments().get(0).value()
335 .getRelations(ConvertsRelation.class).get(0).getTo().getIndex());
336 ht.evict(aScStep.getDocuments().get(0).value());
338 ok = _stepService.removeDocument(aScStep, docId);
341 removedDocs.add(docId);
343 Assert.assertTrue(ok, "Removing was failed.");
344 _scenarioDAO.flush();
347 for (Long id : removedDocs) {
349 if (ht.get(Document.class, id) != null) {
350 title = ht.get(Document.class, id).getTitle();
352 Assert.assertEquals(ht
353 .find("from Document where rid=" + id).size(), 0,
354 "Document#" + id + "(" + title
355 + ") was not removed from the database.");
358 Assert.assertEquals(ht.find("from Document").size(), nbDoc
360 "Documents were not removed from the database.");
361 Assert.assertEquals(ht.find(
362 "from UsesRelation where owner=" + docId).size(), 0,
363 "UsesRelation(s) were not removed from the database.");
365 .assertEquals(ht.find(
366 "from UsedByRelation where owner=" + docId)
368 "UsedByRelation(s) were not removed from the database.");
370 .assertEquals(ht.find(
371 "from UsesRelation where refer=" + docId)
373 "Referencing UsesRelation(s) were not removed from the database.");
375 .assertEquals(ht.find(
376 "from UsedByRelation where refer=" + docId)
378 "Referencing UsedByRelation(s) were not removed from the database.");
380 .assertEquals(ht.find(
381 "from ConvertsRelation where owner=" + docId)
383 "ConvertsRelation(s) were not removed from the database.");
388 .assertEquals(ht.find("from Document").size(), nbDoc
390 "Documents were not removed from the database.");
392 Assert.assertEquals(ht.find("from File").size(), 0,
393 "Files were not removed from the database.");
395 Assert.assertEquals(ht.find(
396 "from Publication where owner=" + aScen.getIndex()).size(), 0,
397 "Publications were not removed from the database.");
399 Assert.assertEquals(ht.find("from UsesRelation").size(), 0,
400 "Uses relations were not removed from the database.");
402 Assert.assertEquals(ht.find("from UsedByRelation").size(), 0,
403 "UsedBy relations were not removed from the database.");
405 rollbackNestedTransaction();
406 LOG.debug(">>>>> END testRemoveDocument()");
410 * Create a persistent scenario for tests.
412 * @return a persistent scenario
413 * @throws InvalidPropertyException
414 * if an invalid property is used when creating objects
415 * @throws MultiplyDefinedException
416 * when trying to create an object with already existing id
417 * @throws MissedPropertyException
418 * if a mandatory property is not defined for an object to be created
419 * @throws IOException
420 * if document creation is failed
421 * @throws SQLException
422 * if project settings loading is failed
424 private long createScenario() throws InvalidPropertyException,
425 MissedPropertyException, MultiplyDefinedException, IOException,
427 // Create a scenario for tests
428 HibernateTemplate ht = getHibernateTemplate();
430 Database.getInstance().reset();
431 _projectSettings.getAllSteps().clear(); // Clear config to be able to load it again
432 // Load workflow customization
434 _projectSettings.configure(ClassLoader.getSystemResource(
435 "test/som.xml").getPath());
436 } catch (FileNotFoundException e) {
437 Assert.fail("Can't find som.xml: ", e);
439 List<Step> steps = _projectSettings.getAllSteps();
440 Assert.assertTrue(steps.size() > 0, "No steps are created.");
442 // Create a test user
443 User.Properties uprop = new User.Properties();
444 uprop.setUsername("TST_Username").setName("TST_SimanUnitTestsUser")
445 .setFirstName("TST_FirstName").setDisplayName("TST_test.user")
446 .addRole("TST_user").setMailAddress(
447 "noreply@salome-platform.org");
448 uprop.disableCheck();
449 User anAuthor = new User(uprop);
450 ht.saveOrUpdate(anAuthor);
452 // Create a test study
453 Study.Properties stprops = new Study.Properties().setReference(
454 "TST_SID_01").setTitle("TST_Study").setManager(anAuthor);
455 Study aStudy = new Study(stprops);
456 ht.saveOrUpdate(aStudy);
458 // Create a test scenario
459 Scenario.Properties sprops = new Scenario.Properties().setTitle(
460 "TST_Scenario").setManager(anAuthor).setOwnerStudy(aStudy);
461 Scenario aScenario = new Scenario(sprops);
462 aStudy.getScenariiList().add(aScenario);
463 ht.saveOrUpdate(anAuthor);
464 ht.saveOrUpdate(aStudy);
465 ht.saveOrUpdate(aScenario);
467 // Create documents for each scenario step
468 Document.Properties dprop = new Document.Properties().setAuthor(
469 anAuthor).setDate(new Date());
471 Publication usedPub = null;
472 Map<Long, Long> usedMap = new HashMap<Long, Long>();
473 for (int stepNum = 1; stepNum <= steps.size(); stepNum++) {
474 Step step = _projectSettings.getStep(stepNum);
475 LOG.debug("Create scenario step: " + stepNum);
476 ProjectElement projElem;
478 if (step.appliesTo(Study.class)) {
481 projElem = aScenario;
483 org.splat.som.Step aScStep = new org.splat.som.Step(step, projElem);
484 List<DocumentType> dtypes = _documentTypeService
485 .selectTypesOf(step);
486 if (dtypes.size() > 0) {
487 DocumentType dtype = dtypes.get(0);
488 // Create a document published in the scenario
489 // document<i>: document type[0] - first type used on the step
490 // <source-file>.brep
491 // <attached-file>.med
493 dprop.setName("document" + stepNum).setType(dtype);
494 if (step.getNumber() > 3) {
495 dprop.setFormat("med");
497 dprop.setFormat("py");
499 Publication pub = createDoc(projElem, aScStep, dprop, "med",
501 if (usedPub != null) {
502 pub.addDependency(usedPub);
503 LOG.debug("Add dependency: " + pub.value().getTitle()
504 + " from " + usedPub.value().getTitle());
505 ht.saveOrUpdate(pub.value());
508 usedMap.put(pub.getIndex(), usedPub.getIndex());
512 if (dtypes.size() <= 0) {
513 LOG.debug("No document types are found for scenario step " + i);
517 // Check that the scenario and its documents have been created correctly.
519 Assert.assertNotNull(ht.find("from Document"),
520 "No documents in the database.");
521 Assert.assertTrue(ht.find("from Document").size() > 0,
522 "No documents in the database.");
524 Assert.assertNotNull(ht.find("from Publication where owner="
525 + aScenario.getIndex()), "No publications in the database.");
527 ht.find("from Publication where owner=" + aScenario.getIndex())
528 .size() > 0, "No publications in the database.");
530 for (Publication p : (List<Publication>) ht
531 .find("from Publication where owner=" + aScenario.getIndex())) {
532 LOG.debug("Publication found: [id=" + p.getIndex() + ", owner="
533 + p.getOwner().getIndex() + ", doc=" + p.value().getIndex()
535 Assert.assertEquals(p.getOwner().getIndex(), aScenario.getIndex(),
536 "The publication was not attached to the scenario.");
539 // Remove the scenario from the current hibernate session.
541 // Check that the scenario is created in the database.
542 Scenario aScen = ht.load(Scenario.class, aScenario.getIndex());
543 Assert.assertNotNull(aScen, "Scenario was not saved in the database.");
544 Assert.assertTrue(aScen.getDocums().size() > 0,
545 "No publications in the scenario.");
547 Assert.assertTrue(i > 0,
548 "More then one document must be in the database");
550 // Check created uses relations
552 .assertTrue(usedMap.size() > 0,
553 "Uses relations must be created.");
554 boolean foundAny = false;
555 for (Long usingId : usedMap.keySet()) {
556 for (Publication pub : aScen.getDocums()) {
557 if (pub.getIndex() == usingId) {
558 boolean found = false;
559 for (Publication used : aScen.getDocums()) {
560 found = (used.getIndex() == usedMap.get(usingId));
566 for (Publication used : aStudy.getDocums()) {
567 found = (used.getIndex() == usedMap.get(usingId));
573 Assert.assertTrue(found,
574 "Uses relation was not created in the database.");
575 foundAny = foundAny || found;
579 Assert.assertTrue(foundAny,
580 "No Uses relation was created in the database.");
582 return aScenario.getIndex();
586 * Create a document published in the scenario. <BR>
588 * document type - type used on the step <BR>
589 * <source-file>.brep <BR>
590 * <attached-file>.med
593 * the scenario to add the document to
595 * scenario step where the document to be published
597 * document properties
598 * @param attachedFileExt
599 * extension of the secon attached (exported) file
601 * outdated document flag
602 * @return the publication of the created document
603 * @throws IOException
604 * @throws MultiplyDefinedException
605 * @throws InvalidPropertyException
606 * @throws MissedPropertyException
608 private Publication createDoc(final ProjectElement aScenario,
609 final org.splat.som.Step aScStep, final Properties dprop,
610 final String attachedFileExt, final boolean isOutdated)
611 throws MissedPropertyException, InvalidPropertyException,
612 MultiplyDefinedException, IOException {
613 // Create a document published in the scenario
614 // document<i>: document type - type used on the step
615 // <source-file>.brep
616 // <attached-file>.med
617 Publication pub = _stepService.createDocument(aScStep, dprop);
618 Assert.assertNotNull(pub.getOwner(),
619 "The publication must be attached to the scenario.");
620 Assert.assertEquals(pub.getOwner().getIndex(), aScenario.getIndex(),
621 "The publication was not attached to the scenario.");
627 HibernateTemplate ht = getHibernateTemplate();
628 ht.saveOrUpdate(pub);
631 ht.save(pub.value());
633 ht.saveOrUpdate(_publicationService.attach(pub, attachedFileExt));