/// <summary> /// Copy the project to the target user and set it as shared by the source user /// </summary> /// <param name="project"></param> /// <param name="sourceUserName"></param> /// <param name="targetUserName"></param> /// <returns></returns> private bool copyProject(Project project, string sourceUserName, string targetUserName) { string sourceProjectName = project.ProjectName; string submissionId = project.SubmissionId; // Create share revision var revision = new ProjectRevision { RevisionId = project.RevisionHistory.Last().RevisionId + 1, Name = sourceProjectName, Date = DateTime.Now, Owner = sourceUserName, Action = ActionTypes.Share }; project.RevisionHistory.Add(revision); // Fix name collisions var targetProjectName = sourceProjectName; string xmlFilename = String.Format("{0}_{1}", submissionId, sourceProjectName ?? ""); if (XmlUserData.Exists(xmlFilename, "PkView", targetUserName)) { // Add a project rename entry by the destination user var renameRevision = new ProjectRevision { RevisionId = project.RevisionHistory.Last().RevisionId + 1, Date = DateTime.Now, Owner = targetUserName, Action = ActionTypes.Rename }; project.RevisionHistory.Add(renameRevision); // Add an incremental numeric suffix while a collision is found int i = 1; do { renameRevision.Name = string.Format("{0} ({1})", sourceProjectName, i++); xmlFilename = String.Format("{0}_{1}", submissionId, renameRevision.Name ?? ""); } while (XmlUserData.Exists(xmlFilename, "PkView", targetUserName)); targetProjectName = renameRevision.Name; project.ProjectName = targetProjectName; // also change the project name of individual studies project.Studies.ForEach(s => { s.ProfileName = targetProjectName; }); } // Save the project for the target user this.CreateOrUpdate(project, targetUserName); // Output paths var sourcePath = string.Format(@"\\{0}\Output Files\PkView\{1}\{2}\{3}", iPortalApp.AppServerName, sourceUserName, sourceProjectName, submissionId); var targetPath = string.Format(@"\\{0}\Output Files\PkView\{1}\{2}\{3}", iPortalApp.AppServerName, targetUserName, targetProjectName, submissionId); // Copy each study foreach (var study in project.Studies) { var sourceStudyPath = Path.Combine(sourcePath, study.SupplementNumber, study.StudyCode); var targetStudyPath = Path.Combine(targetPath, study.SupplementNumber, study.StudyCode); if (Directory.Exists(sourceStudyPath)) { DirectoryTools.DirectoryCopy(sourceStudyPath, targetStudyPath, true, true); } } return(true); }
/// <summary> /// Share a project with the target user /// </summary> /// <param name="submissionId">Parent submission for the project</param> /// <param name="projectName">Project name</param> /// <param name="sourceUserName">user the project belongs to</param> /// <returns></returns> public bool Share(string submissionId, string projectName, string targetUserName, List <string> selectedStudies = null) { // source username var sourceUserName = Users.GetCurrentUserName(); // Find the source project var sourceProject = this.Find(submissionId, projectName, sourceUserName); if (sourceProject == null) { return(false); } // Leave only selected studies in the source project if (selectedStudies != null && selectedStudies.Count != sourceProject.Studies.Count) { var sourceStudies = from study in sourceProject.Studies join studyId in selectedStudies on study.StudyCode equals studyId select study; sourceProject.Studies = sourceStudies.ToList(); } // Locate matching projects by submission var targetProjectNames = this.List(submissionId, targetUserName); var targetProjects = targetProjectNames .Select(name => this.Find(submissionId, name, targetUserName)).ToList(); // Filter the list leaving only entries with matching creation date and shared by the source user var sourceCreation = sourceProject.RevisionHistory.Single(h => h.RevisionId == 1); var targetProjectsWithDate = Enumerable.Empty <object>() .Select(o => new { p = new Project(), d = new DateTime() }).ToList(); foreach (var tp in targetProjects) { // Ensure revision history is sorted tp.RevisionHistory.OrderBy(h => h.RevisionId); // If creation entry does not match, remove it from the list if (tp.RevisionHistory.First().Equals(sourceCreation)) { // Find the last share or import entry in the history var lastShareOrImport = tp.RevisionHistory .Last(h => h.Action == ActionTypes.Share || h.Action == ActionTypes.Import); // If it is a share by the source user, add the project to the list of target projects with the share date if (lastShareOrImport.Action == ActionTypes.Share && lastShareOrImport.Owner == sourceUserName) { targetProjectsWithDate.Add(new { p = tp, d = lastShareOrImport.Date }); } } } targetProjectsWithDate.OrderByDescending(tpd => tpd.d); // If no previously shared projects were found, just copy the project to the target user if (targetProjectsWithDate.Count == 0) { return(copyProject(sourceProject, sourceUserName, targetUserName)); } // Find the most recently shared project with compatible settings Project targetProject = null; List <Tuple <StudySettings, StudySettings> > matchedStudies = null; foreach (var tpd in targetProjectsWithDate) { // Match the studies being shared from the source project to the studies in the target project matchedStudies = (from sourceStudy in sourceProject.Studies join targetStudy in tpd.p.Studies on sourceStudy.StudyCode equals targetStudy.StudyCode into matched from match in matched.DefaultIfEmpty() select new Tuple <StudySettings, StudySettings> (sourceStudy, match)).ToList(); // Check for study compatibility bool compatible = true; foreach (var match in matchedStudies) { // If study has results in the target, check for settings compatibility if (match.Item2 != null && match.Item2.Pharmacokinetics != null) { // If revision id of the two studies is identical no additional check is needed if (match.Item1.RevisionId != match.Item2.RevisionId) { compatible = match.Item1.IsCompatible(match.Item2); if (!compatible) { break; } } } } // if the project is compatible stop looking if (compatible) { targetProject = tpd.p; break; } } // if no compatible project was found, just create a new copy of the project if (targetProject == null) { return(copyProject(sourceProject, sourceUserName, targetUserName)); } // Create shared revision in the target project var shareRevisionId = targetProject.RevisionHistory.Max(h => h.RevisionId) + 1; var revision = new ProjectRevision { RevisionId = shareRevisionId, Name = projectName, Date = DateTime.Now, Owner = sourceUserName, Action = ActionTypes.Share }; targetProject.RevisionHistory.Add(revision); var sourcePath = string.Format(@"\\{0}\Output Files\PkView\{1}\{2}\{3}", iPortalApp.AppServerName, sourceUserName, projectName, submissionId); var targetPath = string.Format(@"\\{0}\Output Files\PkView\{1}\{2}\{3}", iPortalApp.AppServerName, targetUserName, targetProject.ProjectName, submissionId); // Copy each study to the target foreach (var match in matchedStudies) { // if matching study exist but has no results bool removed = false; if (match.Item2 != null && match.Item2.Pharmacokinetics == null) { // If revisionId is identical ignore this entry otherwise delete the entry for re-copy if (match.Item1.RevisionId == match.Item2.RevisionId) { continue; } else { targetProject.Studies.Remove(match.Item2); removed = true; } } // If target study does not exist or was removed if (match.Item2 == null || removed) { match.Item1.ProfileName = targetProject.ProjectName; match.Item1.RevisionId = shareRevisionId; targetProject.Studies.Add(match.Item1); // if results exist, copy output files if (match.Item1.Pharmacokinetics != null) { var supplementNumber = match.Item1.SupplementNumber; var studyCode = match.Item1.StudyCode; var sourceStudyPath = Path.Combine(sourcePath, supplementNumber, studyCode); var targetStudyPath = Path.Combine(targetPath, supplementNumber, studyCode); // Copy output files if (Directory.Exists(sourceStudyPath)) { DirectoryTools.DirectoryCopy(sourceStudyPath, targetStudyPath, true, true); } } } else // If the study does exist and has results, copy the missing reports from the source { // if the study doesnt have reports, there is nothing else to do for this study if (match.Item1.Reports == null || match.Item1.Reports.Count == 0) { continue; } // if the target study does not have reports copy everything over if (match.Item2.Reports == null || match.Item2.Reports.Count == 0) { match.Item2.Reports = match.Item1.Reports; continue; } // Copy each report var potentialMatches = match.Item2.Reports.ToDictionary(r => r.Name); foreach (var sharedReport in match.Item1.Reports) { // while a report is found but the settings are different, look at the next incremental name String reportBaseName = sharedReport.Name; int i = 1; while (potentialMatches.ContainsKey(sharedReport.Name) && !sharedReport.Equals(potentialMatches[sharedReport.Name])) { // assign a report name with an incremental suffix sharedReport.Name = string.Format("{0} ({1})", reportBaseName, i++); } // if no report was found with the current name and identical settings, copy the source report if (!potentialMatches.ContainsKey(sharedReport.Name)) { match.Item2.Reports.Add(sharedReport); var supplementNumber = match.Item1.SupplementNumber; var studyCode = match.Item1.StudyCode; var sourceReportPath = Path.Combine(sourcePath, supplementNumber, studyCode, reportBaseName); var targetReportPath = Path.Combine(targetPath, supplementNumber, studyCode, sharedReport.Name); // Copy report files if (Directory.Exists(sourceReportPath)) { DirectoryTools.DirectoryCopy(sourceReportPath, targetReportPath, true, true); } } } } } // Save the project for the target user this.CreateOrUpdate(targetProject, targetUserName); return(true); }
/// <summary> /// Find a project in the repository /// </summary> /// <param name="submissionId">Parent submission for the project</param> /// <param name="projectName">Project name</param> /// <param name="userName">user the project belongs to, defaults to current user</param> /// <returns></returns> public Project Find(string submissionId, string projectName, string userName = null, ProjectRetrievalFlags flags = 0) { string xmlFilename = String.Format("{0}_{1}", submissionId, projectName ?? ""); if (XmlUserData.Exists(xmlFilename, "PkView", userName)) { Project project; try { project = XmlUserData.Load <Project>(xmlFilename, "PkView", userName); } catch { // Load legacy format project = new Project(); project.Studies = XmlUserData.Load <List <StudySettings> >(xmlFilename, "PkView", userName); if (project.Studies == null || project.Studies.Count == 0) { return(null); } project.SubmissionId = submissionId; project.ProjectName = projectName; userName = userName ?? Users.GetCurrentUserName(); // Initialize revision history project.RevisionHistory = new List <ProjectRevision>(); var revision = new ProjectRevision { RevisionId = 1, Name = projectName, Owner = userName, Date = DateTime.Now, Action = ActionTypes.Create }; project.RevisionHistory.Add(revision); project.Studies.ForEach(s => s.RevisionId = 1); XmlUserData.Save <Project>(project, xmlFilename, "PkView", userName); } // Return if project is empty or null if (project == null || project.Studies == null || !project.Studies.Any()) { return(project); } // Trim data based on project retrieval flags switch (flags) { // Clear mean data case ProjectRetrievalFlags.MeanDataOnly: foreach (var study in project.Studies) { if (study.Concentration != null && study.Concentration.Sections != null) { study.Concentration.Sections.ForEach(s => s.SubSections = null); } if (study.Pharmacokinetics != null && study.Pharmacokinetics.Sections != null) { study.Pharmacokinetics.Sections.ForEach(s => s.SubSections = null); } } break; // Clear everything but metadata case ProjectRetrievalFlags.MetaDataOnly: foreach (var study in project.Studies) { study.StudyMappings = null; study.ArmMappings = null; study.Concentration = null; study.Pharmacokinetics = null; study.Analytes = null; study.Parameters = null; study.Reports = null; } break; } return(project); } return(null); }
/// <summary> /// Import a project from the source user /// </summary> /// <param name="submissionId">Parent submission for the project</param> /// <param name="projectName">Project name</param> /// <param name="sourceUserName">user the project belongs to</param> /// <returns></returns> public bool Import(string submissionId, string projectName, string sourceUserName) { // Find the source project var project = this.Find(submissionId, projectName, sourceUserName); if (project == null) { return(false); } // destination username var targetUserName = Users.GetCurrentUserName(); // Create share revision var revision = new ProjectRevision { RevisionId = project.RevisionHistory.Last().RevisionId + 1, Name = projectName, Date = DateTime.Now, Owner = sourceUserName, Action = ActionTypes.Import }; project.RevisionHistory.Add(revision); // Fix name collisions var targetProjectName = projectName; string xmlFilename = String.Format("{0}_{1}", submissionId, projectName ?? ""); if (XmlUserData.Exists(xmlFilename, "PkView", targetUserName)) { // Add a project rename entry by the destination user var renameRevision = new ProjectRevision { RevisionId = project.RevisionHistory.Last().RevisionId + 1, Date = DateTime.Now, Owner = targetUserName, Action = ActionTypes.Rename }; project.RevisionHistory.Add(renameRevision); // Add an incremental numeric suffix while a collision is found int i = 1; do { renameRevision.Name = string.Format("{0} ({1})", projectName, i++); xmlFilename = String.Format("{0}_{1}", submissionId, renameRevision.Name ?? ""); } while (XmlUserData.Exists(xmlFilename, "PkView", targetUserName)); targetProjectName = renameRevision.Name; project.ProjectName = targetProjectName; // also change the project name of individual studies project.Studies.ForEach(s => { s.ProfileName = targetProjectName; }); } // Save the project for the target user this.CreateOrUpdate(project, targetUserName); // Copy output folder var sourcePath = string.Format(@"\\{0}\Output Files\PkView\{1}\{2}\{3}", iPortalApp.AppServerName, sourceUserName, projectName, submissionId); var destPath = string.Format(@"\\{0}\Output Files\PkView\{1}\{2}\{3}", iPortalApp.AppServerName, targetUserName, targetProjectName, submissionId); if (Directory.Exists(sourcePath)) { DirectoryTools.DirectoryCopy(sourcePath, destPath, true, true); } // Copy ouptut package if it exists FileInfo pkgFile = new FileInfo(sourcePath + ".zip"); if (pkgFile.Exists) { pkgFile.CopyTo(destPath + ".zip", true); } return(true); }