From: mka Date: Fri, 20 Sep 2013 09:04:39 +0000 (+0000) Subject: New checkIn functionality is implemented. Now some files can be checkedIn simultaneously. X-Git-Tag: V7_3_0b1~7 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=1ca76c70534b7aaaefc89b19ce03c84de0bf697f;hp=30eceaa11c1c2f3403a80c661fe97c3f202ea074;p=tools%2Fsiman.git New checkIn functionality is implemented. Now some files can be checkedIn simultaneously. --- diff --git a/Workspace/Siman-Common/src/org/splat/service/ScenarioServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/ScenarioServiceImpl.java index f75f2d7..857b4be 100644 --- a/Workspace/Siman-Common/src/org/splat/service/ScenarioServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/ScenarioServiceImpl.java @@ -503,6 +503,7 @@ public class ScenarioServiceImpl implements ScenarioService { if (LOG.isInfoEnabled()) { LOG.info("Move " + upfile.getAbsolutePath() + TO + file.getPath()); } + file.delete(); // necessary on some platforms if the file exists. return upfile.renameTo(file); } @@ -783,6 +784,9 @@ public class ScenarioServiceImpl implements ScenarioService { if (LOG.isDebugEnabled()) { LOG.debug("Checkin the step:\n" + stepDTO); } + if (stepDTO.getDocs().size() == 0) { + break; + } // Find a result document type of the step int i = 0; resType = null; @@ -797,9 +801,75 @@ public class ScenarioServiceImpl implements ScenarioService { // Find the appropriate scenario step Step step = findStep(stepDTO, steps); - // Process each document of the step - for (DocumentDTO doc : stepDTO.getDocs()) { - checkinDoc(step, doc, aUser, resType, aDate, newVersion, + List filesToBeAttached = new ArrayList(); + FileDTO fileToAttachTo = null; //all the rest documents will be attached to it + + //The id is the same for all DocumentDTOs of a step + Long currentDocId = stepDTO.getDocs().get(0).getId(); + if(currentDocId != null && currentDocId > 0) { //there is a result document in the step + String currentFormat = step.getDocument(currentDocId).value().getFormat(); + + // Process each document of the step + for (DocumentDTO doc : stepDTO.getDocs()) { + for (FileDTO fileDTO : doc.getFiles()) { + + String path = fileDTO.getPath(); + String format = path.substring(path.lastIndexOf('.') + 1); + + // If it has the same format as current doc (there can be just one such file) + // then this doc will be DocToAttachTo. + if (format != null && format.equals(currentFormat)) { + fileToAttachTo = fileDTO; + } else { + // Else, put it in the list of docs that will be attached to DocToAttachTo + filesToBeAttached.add(fileDTO); + } + } + } + } else { + // Process each document of the step + for (DocumentDTO doc : stepDTO.getDocs()) { + for (FileDTO fileDTO : doc.getFiles()) { + String path = doc.getFiles().get(0).getPath(); + String format = path.substring(path.lastIndexOf('.') + 1); + + ProjectSettingsService.Step stepType = step.getStep(); + // If the default type for its format in the current step is the result type, + // then this doc will be DocToAttachTo. + DocumentType defaultDocType = _projectSettings.getDefaultDocumentType(stepType, format); + if (defaultDocType != null && defaultDocType.isResultOf(stepType)) { + //It is possible that there is not just one such doc + if(fileToAttachTo != null){ + filesToBeAttached.add(fileToAttachTo); + } + fileToAttachTo = fileDTO; + } else { + // Else, put it in the list of docs that will be attached to DocToAttachTo + filesToBeAttached.add(fileDTO); + } + } + } + + //could not find any file with appropriate format + if (fileToAttachTo == null && !filesToBeAttached.isEmpty()) { + //All the rest documents will be attached to the first in the list + fileToAttachTo = filesToBeAttached.get(0); + filesToBeAttached.remove(0); + } + } + + if (fileToAttachTo != null) { // true if the DocumentDTO list is not empty + + //Process docToAttachTo + Publication pub = checkinDoc(step, fileToAttachTo, currentDocId, + aUser, resType, aDate, + newVersion, newVers, newDocs); + currentDocId = pub.value().getIndex(); + } + + //Process rest docs + for (FileDTO file : filesToBeAttached) { + checkinDoc(step, file, currentDocId, aUser, resType, aDate, newVersion, newVers, newDocs); } } @@ -873,7 +943,8 @@ public class ScenarioServiceImpl implements ScenarioService { for (Publication pub : aScenario.getDocums()) { if ((pub.getStep().getNumber() <= newPub.getStep().getNumber()) && (!pub.isOutdated()) - && usedTypes.contains(pub.value().getType())) { + && usedTypes.contains(pub.value().getType()) + && !newPub.equals(pub)) { // Create uses relation from the new document // to the found document in the previous step. newPub.addDependency(pub); @@ -889,8 +960,10 @@ public class ScenarioServiceImpl implements ScenarioService { * * @param step * the destination scenario step - * @param doc - * the DTO of the document to checkin + * @param file + * the FilDTO to checkin + * @param docId + * target document id * @param aUser * the user who performs checkin * @param resType @@ -903,6 +976,9 @@ public class ScenarioServiceImpl implements ScenarioService { * the list of publications of new created versions of existing documents * @param newDocs * the list of publications of new created documents not existing before the checkin + * @return + * the newly created publication, if exists (the document has been created or versioned), + * null otherwise (the doc has been attached to the old one) * @throws InvalidPropertyException * if the scenario hasn't some of given steps or documents * @throws IOException @@ -916,17 +992,17 @@ public class ScenarioServiceImpl implements ScenarioService { * @throws NotApplicableException * if failed saving of a new publication with a given state */ - private void checkinDoc(final Step step, final DocumentDTO doc, - final User aUser, final DocumentType resType, final Date aDate, - final Map newVersion, + private Publication checkinDoc(final Step step, final FileDTO file, + final long docId, final User aUser, final DocumentType resType, + final Date aDate, final Map newVersion, final List newVers, final List newDocs) throws InvalidPropertyException, MismatchException, MissedPropertyException, MultiplyDefinedException, IOException, NotApplicableException { - if (doc.getFiles().size() > 0) { + Publication newPub = null; + if (file != null) { Document.Properties dprop = new Document.Properties(); // NOTE: Process only the first attached file for each document - FileDTO file = doc.getFiles().get(0); dprop.setLocalPath(file.getPath()); // Get document title as the file name @@ -943,8 +1019,8 @@ public class ScenarioServiceImpl implements ScenarioService { MessageKeyEnum.DCT_000005.toString(), authorName); dprop.setDescription(summary); - if (doc.getId() > 0) { - checkinExistingDoc(step, doc, dprop, fileFormat, upfile, + if (docId > 0) { + newPub = checkinExistingDoc(step, docId, dprop, fileFormat, upfile, newVersion, newVers); } else { @@ -967,7 +1043,7 @@ public class ScenarioServiceImpl implements ScenarioService { docname += "_" + i; // The generated new document title dprop.setName(docname); - Publication newPub = getStepService().createDocument(step, + newPub = getStepService().createDocument(step, dprop); // Remember the new document @@ -975,7 +1051,8 @@ public class ScenarioServiceImpl implements ScenarioService { saveFile(newPub, step, upfile); } - } + } + return newPub; } /** @@ -983,8 +1060,8 @@ public class ScenarioServiceImpl implements ScenarioService { * * @param step * study step to check in - * @param doc - * document DTO to check in + * @param docId + * target document id * @param dprop * document properties * @param fileFormat @@ -995,6 +1072,9 @@ public class ScenarioServiceImpl implements ScenarioService { * the map of created versions during this check in * @param newVers * the list of new versions created during this check in + * @return + * the newly created publication, if exists (the document has been versioned), + * null otherwise (the doc has been attached to the old one) * @throws InvalidPropertyException * if publication of the document is not found in the step * @throws MismatchException @@ -1008,7 +1088,7 @@ public class ScenarioServiceImpl implements ScenarioService { * @throws NotApplicableException * if failed saving of a new publication with a given state */ - private void checkinExistingDoc(final Step step, final DocumentDTO doc, + private Publication checkinExistingDoc(final Step step, final long docId, final Properties dprop, final String fileFormat, final java.io.File upfile, final Map newVersion, @@ -1021,14 +1101,16 @@ public class ScenarioServiceImpl implements ScenarioService { // If file format (i.e. extension) is the same then create a new // version of the document. // Find the document publication - Publication pub = step.getDocument(doc.getId()); + //Publication pub = step.getDocument(doc.getId()); + Publication pub = step.getDocument(docId); + Publication newPub = null; if (pub == null) { throw new InvalidPropertyException(MessageKeyEnum.SCN_000002 - .toString(), doc.getId()); + .toString(), docId); } if (pub.value() == null) { throw new MismatchException(MessageKeyEnum.SCN_000002.toString(), - doc.getId()); + docId); } if (LOG.isDebugEnabled()) { LOG.debug("Old format: " + pub.value().getFormat() @@ -1037,7 +1119,7 @@ public class ScenarioServiceImpl implements ScenarioService { // If formats are same then create a new document version if (pub.value().getFormat() != null && pub.value().getFormat().equals(fileFormat)) { - Publication newPub = getStepService().versionDocument(step, pub, + newPub = getStepService().versionDocument(step, pub, dprop); if (LOG.isDebugEnabled()) { LOG.debug("Created document type: " @@ -1066,6 +1148,7 @@ public class ScenarioServiceImpl implements ScenarioService { attach.setDate(new Date()); } } + return newPub; } /** diff --git a/Workspace/Siman-Common/src/test/splat/service/TestScenarioService.java b/Workspace/Siman-Common/src/test/splat/service/TestScenarioService.java index baddb01..13f1b32 100644 --- a/Workspace/Siman-Common/src/test/splat/service/TestScenarioService.java +++ b/Workspace/Siman-Common/src/test/splat/service/TestScenarioService.java @@ -16,6 +16,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -412,7 +413,6 @@ public class TestScenarioService extends BaseTest { // Call checkin method for empty list of modules. // Simulate checkout - List steps = _scenarioService.getScenarioInfo(scenarioId); _scenarioService.checkout(aScen, user); _scenarioDAO.flush(); // Check that scenario is no more marked as checked out @@ -432,267 +432,346 @@ public class TestScenarioService extends BaseTest { Assert.assertFalse(aScen.isCheckedout(), "Scenario is still marked as checked out after checkin."); - // //////////////////////////////////////////////////////// - // Call checkin method for good prepared transient data. - - // Simulate checkout - steps = _scenarioService.getScenarioInfo(scenarioId); - _scenarioService.checkout(aScen, user); - - // Remember modification dates of all attached files - Map dates = new HashMap(); - for (Publication p : aScen.getDocums()) { - for (Relation r : p.value().getRelations(ConvertsRelation.class)) { - org.splat.dal.bo.som.File attach = ((ConvertsRelation) r) - .getTo(); - dates.put(attach.getIndex(), attach.getDate()); + // /////////////////////////////////////////////////////////// + // Different test cases + + //Fancy but compact way to iterate over all possible combinations without missing any of them. + List trueFalse = new ArrayList(); + trueFalse.add(false); + trueFalse.add(true); + long testCaseNumber = 1; //To provide some uniqueness to files content. + + for (boolean hasSource : trueFalse) { + for (boolean hasAttachments : trueFalse) { + for (boolean checkinSource : trueFalse) { + for (boolean checkinAttachments : trueFalse) { + if (hasAttachments && !hasSource) { // Impossible test cases + continue; + } + if (!checkinAttachments && !checkinSource) { // Unnecessary test cases + continue; + } + + //startNestedTransaction(); + Set res = testCheckinTestcase(testCaseNumber++, + scenarioId, userId, + hasSource, hasAttachments, + checkinSource, checkinAttachments); + //rollbackNestedTransaction(); + + // These combinations are dictated by assertCheckinValidity logic + Assert.assertEquals(!hasSource && (checkinSource || checkinAttachments), + res.contains("aNewSourceCreated")); + Assert.assertEquals(hasSource && checkinSource, + res.contains("oldSourceVersioned")); + Assert.assertEquals(checkinAttachments && hasSource && checkinSource, + res.contains("fileAttachedToAVersionedDoc")); + Assert.assertEquals(checkinAttachments && hasSource && !checkinSource, + res.contains("fileAttachedToAnOldDoc")); + Assert.assertEquals(checkinAttachments && !hasSource, + res.contains("fileAttachedToANewDoc")); + + } + } } } - - // Prepare test data for checkin - // Checkin only two first steps (geom and mesh) - for (StepDTO step : steps) { - // Prepare GEOM: checkin actual brep - StepDTO stepToCheckin = createDocDTOForModule(null, "GEOM", "brep", - userId, step, stepsToCheckin); - createDocDTOForModule(stepToCheckin, "SMESH", "med", userId, step, - stepsToCheckin); + + // /////////////////////////////////////////////////////////// + // Call checkin method for a not existing id. + try { + _scenarioService.checkin(-1, userId, stepsToCheckin); + Assert + .fail("Check in for scenario with not existing id must be failed."); + } catch (Exception e) { + LOG.debug("Expected exception is thrown: " + + e.getClass().getSimpleName() + ": " + e.getMessage()); } - // ///////////////////////////////////////////////////////////////// - // Do test checkin + + // Test checkin with empty list of steps + stepsToCheckin.clear(); _scenarioService.checkin(scenarioId, userId, stepsToCheckin); - _scenarioDAO.flush(); - // Check that scenario is no more marked as checked out - aScen = _scenarioDAO.get(scenarioId); + rollbackNestedTransaction(); + LOG.debug(">>>>> END testCheckin()"); + } + + + /** + * Performs necessary checks after checkin. + * @param testCaseNumber + * the test case number + * @param stepsToCheckin + * stepDTOs which has been checked in + * @param aScen + * the scenario + * @param dates + * modification dates + * @return + * set of strings indicating which cases has occurred + * @throws IOException + * if something is wrong + */ + private Set assertCheckinValidity(final long testCaseNumber, + final List stepsToCheckin, final Scenario aScen, + final Map dates) throws IOException{ + Set result = new HashSet(); Assert.assertFalse(aScen.isCheckedout(), "Scenario is still marked as checked out after checkin."); - boolean modifDatesChecked = false; // Check that new document versions are created for checked in documents for (StepDTO step : stepsToCheckin) { for (DocumentDTO docDTO : step.getDocs()) { - if ((docDTO.getId() != 0) && (docDTO.getId() != null)) { - boolean found = false; - Document prevDoc = null; - Document curDoc = null; - Publication newPub = null; - for (Publication pub : aScen.getDocums()) { - prevDoc = pub.value().getPreviousVersion(); - if (prevDoc != null) { - found = (prevDoc.getIndex() == docDTO.getId()); - if (found) { // Found next published version of the checked in document - newPub = pub; + for (FileDTO fileDTO : docDTO.getFiles()) { + + if ((docDTO.getId() != 0) && (docDTO.getId() != null)) { + boolean prevVersFound = false; + boolean versionedWithThisFile = false; + Document prevDoc = null; + Document curDoc = null; + Publication newPub = null; + + // If previous version is found then the format must be the same + String newFormat = fileDTO.getPath() + .substring(fileDTO.getPath().lastIndexOf('.') + 1); + for (Publication pub : aScen.getDocums()) { + prevDoc = pub.value().getPreviousVersion(); + if (prevDoc != null) { + prevVersFound = (prevDoc.getIndex() == docDTO.getId()); + if (prevVersFound) { // Found next published version of the checked in document + newPub = pub; + if(pub.value().getFormat().equals(newFormat)) { + versionedWithThisFile = true; + } + break; + } + } + if (pub.value().getIndex() == docDTO.getId()) { + // Document version was not changed, old document is still published + curDoc = pub.value(); break; } } - if (pub.value().getIndex() == docDTO.getId()) { - // Document version was not changed, old document is still published - curDoc = pub.value(); - break; - } - } - Assert.assertTrue(found || (curDoc != null), - "New version or new attached file of the existing checked in document \"" - + docDTO.getTitle() + "\" (id=" - + docDTO.getId() - + ") is not found in the scenario."); - // If previous version is found then the format must be the same - String newFormat = docDTO.getFiles().get(0).getPath() - .substring( - docDTO.getFiles().get(0).getPath() - .lastIndexOf('.') + 1); - if (found) { - Assert.assertEquals(prevDoc.getFormat(), newFormat, - "Formats of versions must be same"); - Assert.assertFalse(aScen.publishes(prevDoc)); - // Check that presentation of the previous version is removed - checkFiles(docDTO, newPub); - - // Formats of files are new if they are according to the document's type on the study step - if ("py".equals(prevDoc.getFormat()) - && "geometry".equals(prevDoc.getType() - .getName())) { - Assert.assertEquals(newPub.value().getFormat(), - newFormat); - Assert.assertEquals(newPub.getSourceFile() - .getFormat(), newFormat); - Assert.assertEquals(newPub.getSourceFile() - .getRelativePath().substring( - newPub.getSourceFile() - .getRelativePath() - .lastIndexOf('.') + 1), - newFormat); - } - - // Check that uses relations are copied correctly - - // 1. Get all uses relations of the previous document version - for (Relation rel : prevDoc - .getRelations(UsesRelation.class)) { - Document used = ((UsesRelation) rel).getTo(); - // 2.1. Get the latest version of the document published in this scenario - Publication toBeUsed = aScen.getPublication(used); - if (toBeUsed == null) { - // Find the latest published version - for (Publication lastPub : aScen.getDocums()) { - if ((lastPub.value().getPreviousVersion() != null) - && (lastPub.value() - .getPreviousVersion() - .getIndex() == used - .getIndex())) { - toBeUsed = lastPub; - break; + Assert.assertTrue(prevVersFound || (curDoc != null), + "New version or new attached file of the existing checked in document \"" + + docDTO.getTitle() + "\" (id=" + + docDTO.getId() + + ") is not found in the scenario."); + + if (prevVersFound && versionedWithThisFile) { + result.add("oldSourceVersioned"); + Assert.assertFalse(aScen.publishes(prevDoc)); + // Check that presentation of the previous version is removed + checkFiles(docDTO, newPub); + + // Formats of files are new if they are according to the document's type on the study step + Assert.assertEquals(newPub.getSourceFile() + .getFormat(), newFormat); + Assert.assertEquals(newPub.getSourceFile() + .getRelativePath().substring( + newPub.getSourceFile() + .getRelativePath() + .lastIndexOf('.') + 1), + newFormat); + + // Check that uses relations are copied correctly + + // 1. Get all uses relations of the previous document version + for (Relation rel : prevDoc + .getRelations(UsesRelation.class)) { + Document used = ((UsesRelation) rel).getTo(); + // 2.1. Get the latest version of the document published in this scenario + Publication toBeUsed = aScen.getPublication(used); + if (toBeUsed == null) { + // Find the latest published version + for (Publication lastPub : aScen.getDocums()) { + if ((lastPub.value().getPreviousVersion() != null) + && (lastPub.value() + .getPreviousVersion() + .getIndex() == used + .getIndex())) { + toBeUsed = lastPub; + break; + } } } + if ((toBeUsed != null) && (!toBeUsed.isOutdated())) { + // 2.2. For each used document check that its latest not outdated version + // is used by the new checked in document version. + checkUsesRelation(newPub, toBeUsed); + } } - if ((toBeUsed != null) && (!toBeUsed.isOutdated())) { - // 2.2. For each used document check that its latest not outdated version - // is used by the new checked in document version. - checkUsesRelation(newPub, toBeUsed); + // 1. Get all usedBy relations of the previous document version + for (Relation rel : prevDoc + .getRelations(UsedByRelation.class)) { + Document using = ((UsedByRelation) rel).getTo(); + // Check that not checked in dependent documents became outdated + Publication usingPub = aScen.getPublication(using); + if (usingPub != null) { // if the document using the old version is still published + Assert.assertTrue(usingPub.isOutdated(), + "Not checked in dependent document " + + using.getTitle() + " (" + + using.getType().getName() + + ") must become outdated."); + } } - } - // 1. Get all usedBy relations of the previous document version - for (Relation rel : prevDoc - .getRelations(UsedByRelation.class)) { - Document using = ((UsedByRelation) rel).getTo(); - // Check that not checked in dependent documents became outdated - Publication usingPub = aScen.getPublication(using); - if (usingPub != null) { // if the document using the old version is still published - Assert.assertTrue(usingPub.isOutdated(), - "Not checked in dependent document " - + using.getTitle() + " (" - + using.getType().getName() - + ") must become outdated."); + + // Check that a correct comment is generated for VersionsRelation + VersionsRelation versRel = (VersionsRelation) newPub + .value().getFirstRelation( + VersionsRelation.class); + Assert.assertNotNull(versRel, + "VersionsRelation must be created."); + Assert + .assertNotNull(versRel.getDescription(), + "VersionsRelation description was not generated."); + int descrLen = versRel.getDescription().length(); + Assert.assertTrue(descrLen > 0, + "VersionsRelation description is empty."); + LOG.debug("Version description: " + + versRel.getDescription()); + } else { + // Otherwise the file is attached to some other document, + // which has been or has not been versioned during checkin + Document targetDoc = null; + if(prevVersFound) { // if the document has been versioned + Assert.assertEquals(Long.valueOf(prevDoc.getIndex()), + docDTO.getId()); + targetDoc = newPub.value(); + result.add("fileAttachedToAVersionedDoc"); + } else { + targetDoc = curDoc; + result.add("fileAttachedToAnOldDoc"); } - } - - // Check that a correct comment is generated for VersionsRelation - VersionsRelation versRel = (VersionsRelation) newPub - .value().getFirstRelation( - VersionsRelation.class); - Assert.assertNotNull(versRel, - "VersionsRelation must be created."); - Assert - .assertNotNull(versRel.getDescription(), - "VersionsRelation description was not generated."); - int descrLen = versRel.getDescription().length(); - Assert.assertTrue(descrLen > 0, - "VersionsRelation description is empty."); - LOG.debug("Version description: " - + versRel.getDescription()); - } else { - // Otherwise the new file format must differ from the previous one - // and the new file must be attached to the same document - org.splat.dal.bo.som.File attFile = curDoc - .getAttachedFile(newFormat); - Assert.assertNotNull(attFile, "File " - + docDTO.getFiles().get(0).getPath() - + " must be attached to the document " - + docDTO.getTitle() + "#" + docDTO.getId()); - Assert.assertTrue(attFile.asFile().exists(), "File " - + docDTO.getFiles().get(0).getPath() - + " attached to the document " - + docDTO.getTitle() + "#" + docDTO.getId() - + " doesn't exist"); - LOG.debug("Source format: " + curDoc.getFormat() - + ", new format: " + newFormat); - // Check that attachment with the same format is not duplicated. - int attachNb = 0; - for (Relation conv : curDoc - .getRelations(ConvertsRelation.class)) { - if (newFormat.equals(((ConvertsRelation) conv) - .getTo().getFormat())) { - attachNb++; + Assert.assertFalse(newFormat.equals(targetDoc.getFormat())); + + // Check file content + Assert.assertTrue(Files.readFile(targetDoc.getAttachedFile(newFormat).asFile()) + .contains(new File(fileDTO.getPath()).getName())); + + // Otherwise the new file format must differ from the previous one + // and the new file must be attached to the same document + org.splat.dal.bo.som.File attFile = targetDoc + .getAttachedFile(newFormat); + Assert.assertNotNull(attFile, "File " + + fileDTO.getPath() + + " must be attached to the document " + + docDTO.getTitle() + "#" + docDTO.getId()); + Assert.assertTrue(attFile.asFile().exists(), "File " + + fileDTO.getPath() + + " attached to the document " + + docDTO.getTitle() + "#" + docDTO.getId() + + " doesn't exist"); + LOG.debug("Source format: " + targetDoc.getFormat() + + ", new format: " + newFormat); + // Check that attachment with the same format is not duplicated. + int attachNb = 0; + for (Relation conv : targetDoc + .getRelations(ConvertsRelation.class)) { + if (newFormat.equals(((ConvertsRelation) conv) + .getTo().getFormat())) { + attachNb++; + } } - } - Assert - .assertEquals(attachNb, 1, - "Attachment with the same format must be only one."); - - // Check that the attached file date is updated - if (dates.containsKey(attFile.getIndex())) { Assert - .assertTrue(attFile.getDate().compareTo( - dates.get(attFile.getIndex())) > 0, - "Attachment modification date is not updated."); - modifDatesChecked = true; + .assertEquals(attachNb, 1, + "Attachment with the same format must be only one."); + + // Check that the attached file date is updated + if (dates.containsKey(attFile.getIndex())) { + Assert + .assertTrue(attFile.getDate().compareTo( + dates.get(attFile.getIndex())) > 0, + "Attachment modification date is not updated."); + result.add("modifDatesChecked"); + } } - } - - } else { - // Check that new documents are created for new data - boolean found = false; - Publication newPub = null; - for (Publication pub : aScen.getDocums()) { - if (pub.value().getPreviousVersion() == null) { - found = (pub.value().getTitle().startsWith(pub - .value().getType().getName())); - if (found) { // Found next published version of the checked in document - String fcontent = Files.readFile(pub - .getSourceFile().asFile()); - found = fcontent.contains(docDTO.getTitle()); - if (found) { - LOG - .debug("Found new document with generated title: " - + pub.value().getTitle()); - newPub = pub; - break; + + } else { + // here file may be attached to a newly created one, + // or it may be a source of new doc itself. + + // Check that new documents are created for new data + boolean foundAsSource = false; + boolean foundAsAttachment = false; + Publication newPub = null; + for (Publication pub : aScen.getDocums()) { + if (pub.value().getPreviousVersion() == null) { + // TODO: is it correct? type name here? + foundAsSource = (pub.value().getTitle().startsWith(pub + .value().getType().getName())); + if (foundAsSource) { // Found next published version of the checked in document + String fcontent = Files.readFile(pub + .getSourceFile().asFile()); + foundAsSource = fcontent.contains( + new File(fileDTO.getPath()).getName()); + if (foundAsSource) { + LOG + .debug("Found new document with generated title: " + + pub.value().getTitle()); + newPub = pub; + break; + } + } + + String format = fileDTO.getPath().substring( + fileDTO.getPath().lastIndexOf('.') + 1); + org.splat.dal.bo.som.File attachment = pub.value().getAttachedFile(format); + if (attachment != null) { + String fcontent = Files.readFile(attachment.asFile()); + if (fcontent.contains(new File(fileDTO.getPath()).getName())) { + foundAsAttachment = true; + Assert.assertFalse(new File(fileDTO.getPath()).exists(), "File" + + fileDTO.getPath() + + " was not removed from downloads directory."); + result.add("fileAttachedToANewDoc"); + break; + } } } } - } - Assert.assertTrue(found, - "New document is not created for checked in document \"" - + docDTO.getTitle() + "\"."); - - // Check that uses relations are created correctly - Assert.assertTrue(newPub.value().getTitle().startsWith( - newPub.value().getType().getName() + "_"), - "Document title newPub.value().getTitle() must start with " - + newPub.value().getType().getName() + "_"); - - // 1. Find the document type used by this document type - Set usedTypes = newPub.value().getType() - .getDefaultUses(); - // 2. Find documents of used types in the current study step and previous study steps - for (Publication pub : aScen.getDocums()) { - if ((pub.getStep().getNumber() <= step.getNumber()) - && (!pub.isOutdated()) - && usedTypes.contains(pub.value().getType())) { - // 3. Check that there is uses relation to the found document - // if it is not outdated. - checkUsesRelation(newPub, pub); + Assert.assertTrue(foundAsSource || foundAsAttachment, + "New document or attachment is not created for checked in document \"" + + docDTO.getTitle() + "\"."); + + if (foundAsSource) { + + // TODO: check that all the conditions for this file to be chosen + // as fileToAttachTo are present. + //probably, drop some unimportant + + // Check file content + Assert.assertTrue(Files.readFile(newPub.getSourceFile().asFile()) + .contains(new File(fileDTO.getPath()).getName())); + + result.add("aNewSourceCreated"); + // Check that uses relations are created correctly + Assert.assertTrue(newPub.value().getTitle().startsWith( + newPub.value().getType().getName() + "_"), + "Document title newPub.value().getTitle() must start with " + + newPub.value().getType().getName() + "_"); + + // 1. Find the document type used by this document type + Set usedTypes = newPub.value().getType() + .getDefaultUses(); + // 2. Find documents of used types in the current study step and previous study steps + for (Publication pub : aScen.getDocums()) { + if ((pub.getStep().getNumber() <= step.getNumber()) + && (!pub.isOutdated()) + && usedTypes.contains(pub.value().getType()) + && !newPub.equals(pub)) { + // 3. Check that there is uses relation to the found document + // if it is not outdated. + checkUsesRelation(newPub, pub); + } + } + + // Check that files are moved correctly + checkFiles(docDTO, newPub); } } - - // Check that files are moved correctly - checkFiles(docDTO, newPub); } } } - - Assert - .assertTrue( - modifDatesChecked, - "No modification date is checked because no files were attached when attachment with same extension already exists."); - - // /////////////////////////////////////////////////////////// - // Call checkin method for a not existing id. - try { - _scenarioService.checkin(-1, userId, stepsToCheckin); - Assert - .fail("Check in for scenario with not existing id must be failed."); - } catch (Exception e) { - LOG.debug("Expected exception is thrown: " - + e.getClass().getSimpleName() + ": " + e.getMessage()); - } - - // Test checkin with empty list of steps - stepsToCheckin.clear(); - _scenarioService.checkin(scenarioId, userId, stepsToCheckin); - - rollbackNestedTransaction(); - LOG.debug(">>>>> END testCheckin()"); + return result; } /** @@ -808,6 +887,249 @@ public class TestScenarioService extends BaseTest { } return stepToCheckin; } + + /** + * Tests a checkin testcase. + * @param testCaseNumber + * the test case number + * @param scenarioId + * the scenrio id + * @param userId + * the user id + * @param hasSource + * whether the scenario is supposed to have a source file in this test case befor checkin + * @param hasAttachments + * whether the scenario is supposed to have files attached to the source + * in this test case befor checkin + * @param checkinSource + * whether the "comm" file should be checked in + * @param checkinAttachment + * whether the "resu" and "mess" files should be checked in + * @return + * set of strings indicating which cases has occurred + * @throws IOException + * if something is wrong + * @throws InvalidPropertyException + * if something is wrong + * @throws MultiplyDefinedException + * if something is wrong + * @throws MissedPropertyException + * if something is wrong + * @throws SQLException + * if something is wrong + * @throws NotApplicableException + * if something is wrong + * @throws MismatchException + * if something is wrong + */ + private Set testCheckinTestcase(final long testCaseNumber, + final long scenarioId, final long userId, + final boolean hasSource, final boolean hasAttachments, + final boolean checkinSource, final boolean checkinAttachment) + throws IOException, InvalidPropertyException, MultiplyDefinedException, + MissedPropertyException, SQLException, NotApplicableException, MismatchException{ + + Scenario aScen = _scenarioDAO.get(scenarioId); + User user = _userDAO.get(userId); + + List steps = _scenarioService.getScenarioInfo(scenarioId); + + // //////////////////////////////////////////////////////// + // Call checkin method for good prepared transient data. + + // Simulate checkout + steps = _scenarioService.getScenarioInfo(scenarioId); + _scenarioService.checkout(aScen, user); + + // Remember modification dates of all attached files + Map dates = new HashMap(); + for (Publication p : aScen.getDocums()) { + for (Relation r : p.value().getRelations(ConvertsRelation.class)) { + org.splat.dal.bo.som.File attach = ((ConvertsRelation) r) + .getTo(); + dates.put(attach.getIndex(), attach.getDate()); + } + } + + long targetDocId = + addMecaDocsToScenario(testCaseNumber, aScen, user, hasAttachments, hasSource); + + List stepsToCheckin = new ArrayList(); + for(StepDTO step : steps) { + createDocDTOForMeca(testCaseNumber, targetDocId, null, userId, step, stepsToCheckin, + checkinSource, checkinAttachment); + } + + // ///////////////////////////////////////////////////////////////// + // Do test checkin + _scenarioService.checkin(scenarioId, userId, stepsToCheckin); + + // Check that scenario is no more marked as checked out + aScen = _scenarioDAO.get(scenarioId); + return assertCheckinValidity(testCaseNumber, stepsToCheckin, aScen, dates); + } + + /** + * It will delete any "comm" publications in the scenario, and then create a new one, + * with attachments if specified. + * @param testCaseNumber + * the test case number + * @param aScen + * the scenario + * @param user + * user who will be used as an author for the added documents + * @param hasAttachments + * whether to add the "comm" doc to the scenario + * @param hasSource + * whether to add "resu" and "mess" docs to the scenario + * @return + * the source document id, if exists, 0 otherwise. + * @throws IOException + * if something is wrong + * @throws InvalidPropertyException + * if something is wrong + * @throws MissedPropertyException + * if something is wrong + * @throws MultiplyDefinedException + * if something is wrong + */ + private long addMecaDocsToScenario(final long testCaseNumber, + final Scenario aScen, final User user, + final boolean hasAttachments, final boolean hasSource) + throws IOException, InvalidPropertyException, MissedPropertyException, + MultiplyDefinedException { + + long res = 0; + org.splat.som.Step mecaStep = null; + for (org.splat.som.Step step : _projectElementService.getSteps(aScen)) { + if ("SALOME_MECA".equals(step.getStep().getModule())) { + mecaStep = step; + } + } + + //remove comm documents + List toRemove = new ArrayList(); + for (Publication pub : mecaStep.getDocuments()) { + if ("comm".equals(pub.value().getFormat())) { + toRemove.add(pub); + } + } + for (Publication pub : toRemove) { + // remove relations so the publication can be removed correctly + List relations = new ArrayList(); + relations.addAll(pub.value().getAllRelations()); + for (Relation rel : relations) { + pub.value().removeRelation(UsesRelation.class, rel.getTo()); + } + aScen.remove(pub); + } + + if (hasSource) { + // Select result document type for Meca step + List dtypes = _documentTypeService + .selectTypesOf(mecaStep.getStep()); + DocumentType resultType = null; + for (DocumentType doctype : dtypes) { + if(doctype.isResultOf(mecaStep.getStep())) { + resultType = doctype; + break; + } + } + + Document.Properties dprop = new Document.Properties(); + File directory = _repositoryService.getDownloadDirectory(user); + directory.mkdirs(); + dprop.setName("commDoc" + testCaseNumber) + .setFormat("comm") + .setAuthor(user) + .setDate(new Date()) + .setType(resultType) + .setLocalPath(dprop.getName() + "." + dprop.getFormat()); + + Publication commPub = createDoc(aScen, mecaStep, dprop, "", false); + // The following is necessary because createDoc does not do all required work + // (and PublicationServiceImpl.createDoc() is complicated so it's harder to make it work) + commPub.setStep(mecaStep); + aScen.getDocums().add(commPub); + mecaStep.getDocuments().add(commPub); + + res = commPub.value().getIndex(); + + // add attachments + if (hasAttachments) { + // Create new "resu" file + FileDTO resuFileDTO = createDownloadedFile(user.getIndex(), "resuFile", "resu"); + ConvertsRelation export = _publicationService.attach(commPub, "resu"); + File resuFile = new File(resuFileDTO.getPath()); + File dest = export.getTo().asFile(); + dest.delete(); + Assert.assertTrue(resuFile.renameTo(dest)); + + // Create new "mess" file + FileDTO messFileDTO = createDownloadedFile(user.getIndex(), "messFile", "mess"); + export = _publicationService.attach(commPub, "mess"); + File messFile = new File(messFileDTO.getPath()); + dest = export.getTo().asFile(); + dest.delete(); + Assert.assertTrue(messFile.renameTo(dest)); + } + } + + return res; + } + + /** + * Prepare a document with a file for check-in. + * + * @param stepTo + * step DTO with data for check-in + * @param userId + * download directory + * @param stepFrom + * checked out stepDTO + * @param stepsToCheckin + * DTO for check-in + * @param createSource + * whether to add the COMM file to the DTO + * @param createAttachment + * whether to add the RESU and MESS files to the DTO + * @throws IOException + * if file creation failed + * @return step DTO with data prepared for check-in (stepTo or new if stepTo is null) + */ + private StepDTO createDocDTOForMeca(final long testCaseNumber, + final long targetDocId, final StepDTO stepTo, + final long userId, final StepDTO stepFrom, final List stepsToCheckin, + final boolean createSource, final boolean createAttachment) + throws IOException { + StepDTO stepToCheckin = stepTo; + if (stepToCheckin == null) { + stepToCheckin = new StepDTO(); + } + if ("SALOME_MECA".equals(stepFrom.getModule())) { + + stepsToCheckin.add(stepToCheckin); + stepToCheckin.setNumber(stepFrom.getNumber()); + + DocumentDTO docToCheckin = stepToCheckin.addDoc( + targetDocId, "newCommDoc"); + + if(createSource) { + docToCheckin.addFile(createDownloadedFile( + userId, "newCommDoc" + testCaseNumber + "_result", + "comm")); + } + if(createAttachment) { + docToCheckin.addFile(createDownloadedFile( + userId, "newResuDoc" + testCaseNumber + "_result", + "resu")); + docToCheckin.addFile(createDownloadedFile( + userId, "newMessDoc" + testCaseNumber + "_result", + "mess")); + } + } + return stepToCheckin; + } /** * Create a file in the user's repository downloads directory.