/// <summary> /// Makes the other <see cref="CohortAggregateContainer"/> into a subcontainer of this container /// </summary> /// <param name="child"></param> public void AddChild(CohortAggregateContainer child) { if (child.IsRootContainer()) { throw new InvalidOperationException("Root containers cannot be added as subcontainers"); } CreateInsertionPointAtOrder(child, child.Order, true); _manager.Add(this, child); }
/// <summary> /// Creates a new <see cref="CohortAggregateContainer"/> if there is no <see cref="RootCohortAggregateContainer_ID"/> yet /// </summary> public void CreateRootContainerIfNotExists() { //if it doesn't have one if (RootCohortAggregateContainer_ID == null) { //create a new one and record it's ID RootCohortAggregateContainer_ID = new CohortAggregateContainer((ICatalogueRepository)Repository, SetOperation.UNION).ID; //save us to database to cement the object SaveToDatabase(); } }
/// <summary> /// Clone and import one or more <see cref="CohortIdentificationConfiguration"/> into the target <paramref name="into"/> /// </summary> /// <param name="cics"></param> /// <param name="into">The container into which you want to add the <paramref name="cics"/></param> public void Import(CohortIdentificationConfiguration[] cics, CohortAggregateContainer into) { var cicInto = into.GetCohortIdentificationConfiguration(); if (cicInto == null) { throw new ArgumentException($"Cannot import into orphan container '{into}'", nameof(into)); } //clone them var cicClones = new CohortIdentificationConfiguration[cics.Length]; try { for (int i = 0; i < cics.Length; i++) { cicClones[i] = cics[i].CreateClone(new ThrowImmediatelyCheckNotifier()); } } catch (Exception ex) { throw new Exception("Error during pre import cloning stage, no import will be attempted", ex); } using (_repository.BeginNewTransactedConnection()) { //Grab the root container of each of the input cics foreach (CohortIdentificationConfiguration cic in cicClones) { var container = cic.RootCohortAggregateContainer; //clear them to avoid dual parentage cic.RootCohortAggregateContainer_ID = null; cic.SaveToDatabase(); //add them into the target SET operation container you are importing into into.AddChild(container); // Make the new name of all the AggregateConfigurations match the owner of import into container foreach (var child in container.GetAllAggregateConfigurationsRecursively()) { EnsureNamingConvention(cicInto, child); } // Delete the old now empty clones cic.DeleteInDatabase(); } //finish transaction _repository.EndTransactedConnection(true); } }
/// <summary> /// Returns all containers that exist above the current container (up to the root container of the CohortIdentificationConfiguration) /// </summary> /// <returns></returns> public IEnumerable <CohortAggregateContainer> GetAllParentContainers() { CohortAggregateContainer container = this; while (container != null) { container = container.GetParentContainerIfAny(); if (container != null) { yield return(container); } } }
/// <summary> /// Returns true if this.Children contains the thing you are looking for - IMPORTANT: also returns true if we are the thing you are looking for /// </summary> /// <param name="potentialChild"></param> /// <returns></returns> public bool HasChild(CohortAggregateContainer potentialChild) { bool foundChildThroughRecursion = false; //recurse into all children foreach (var c in GetSubContainers()) { if (c.HasChild(potentialChild))//ask children recursively the same question (see return statement for the question we are asking) { foundChildThroughRecursion = true; } } //are we the one you are looking for or were any of our children return(potentialChild.ID == this.ID || foundChildThroughRecursion); }
/// <summary> /// Creates a new CohortAggregateContainer tree containing a clone container for each container in the original tree and a clone AggregateConfiguration for each in the original tree /// but with a rename in which AggregateConfigurations in the first tree are expected to start cic_X where X is the original cohort identification configuration ID, this will be replaced /// with the new clone's ID /// </summary> /// <param name="notifier"></param> /// <param name="original"></param> /// <param name="clone"></param> /// <param name="parentToCloneJoinablesDictionary"></param> public CohortAggregateContainer CloneEntireTreeRecursively(ICheckNotifier notifier, CohortIdentificationConfiguration original, CohortIdentificationConfiguration clone, Dictionary <JoinableCohortAggregateConfiguration, JoinableCohortAggregateConfiguration> parentToCloneJoinablesDictionary) { //what is in us? var contents = GetOrderedContents(); //clone us with same order (in parents) var cloneContainer = new CohortAggregateContainer((ICatalogueRepository)Repository, Operation); cloneContainer.Name = Name; cloneContainer.Order = Order; cloneContainer.SaveToDatabase(); //for each thing in us foreach (IOrderable content in contents) { int order = content.Order; var config = content as AggregateConfiguration; var container = content as CohortAggregateContainer; //its a config, clone the config and add it to the clone container if (config != null) { var configClone = clone.ImportAggregateConfigurationAsIdentifierList(config, null, false); notifier.OnCheckPerformed(new CheckEventArgs("Created clone dataset " + configClone + " with ID " + configClone.ID, CheckResult.Success)); cloneContainer.AddChild(configClone, order); //if the original used any joinable patient index tables var usedJoins = config.PatientIndexJoinablesUsed; //our dictionary should have a record of it along with a clone patient index table we should hook our clone up to foreach (var j in usedJoins) { //for some reason the CohortIdentificationConfiguration didn't properly clone the joinable permission or didn't add it to the dictionary if (!parentToCloneJoinablesDictionary.ContainsKey(j.JoinableCohortAggregateConfiguration)) { throw new KeyNotFoundException("Configuration " + configClone + " uses Patient Index Table " + j.AggregateConfiguration + " but our dictionary did not have the key, why was that joinable not cloned?"); } //we do have a clone copy of the joinable permission, set the clone aggregate var cloneJoinable = parentToCloneJoinablesDictionary[j.JoinableCohortAggregateConfiguration]; var cloneJoinUse = cloneJoinable.AddUser(configClone); cloneJoinUse.JoinType = j.JoinType; cloneJoinUse.SaveToDatabase(); //Now! (brace yourself). Some the filters in the AggregateConfiguration we just cloned might reference a table called ix2934 or whetever, this //is the Joinable we need to do a replace to point them at the correct ix number (although if they are good users they will have aliased any //patient index columns anyway) if (configClone.RootFilterContainer_ID != null) { foreach (var clonedFilter in SqlQueryBuilderHelper.GetAllFiltersUsedInContainerTreeRecursively(configClone.RootFilterContainer)) { var oldTableAlias = j.GetJoinTableAlias(); var newTableAlias = cloneJoinUse.GetJoinTableAlias(); clonedFilter.WhereSQL = clonedFilter.WhereSQL.Replace(oldTableAlias, newTableAlias); clonedFilter.SaveToDatabase(); } } } } //its another container (a subcontainer), recursively call the clone operation on it and add that subtree to teh clone container if (container != null) { var cloneSubContainer = container.CloneEntireTreeRecursively(notifier, original, clone, parentToCloneJoinablesDictionary); notifier.OnCheckPerformed(new CheckEventArgs("Created clone container " + cloneSubContainer + " with ID " + cloneSubContainer.ID, CheckResult.Success)); cloneContainer.AddChild(cloneSubContainer); } } //return the clone we created return(cloneContainer); }
/// <summary> /// Splits the root container of a <see cref="CohortIdentificationConfiguration"/> into multiple new cic. /// </summary> /// <param name="rootContainer"></param> /// <returns>All new configurations unmerged out of the <paramref name="rootContainer"/></returns> public CohortIdentificationConfiguration[] UnMerge(CohortAggregateContainer rootContainer) { if (!rootContainer.IsRootContainer()) { throw new ArgumentException("Container must be a root container to be unmerged", nameof(rootContainer)); } if (rootContainer.GetAggregateConfigurations().Any()) { throw new ArgumentException("Container must contain only sub-containers (i.e. no aggregates)", nameof(rootContainer)); } if (rootContainer.GetSubContainers().Length <= 1) { throw new ArgumentException("Container must contain 2+ sub-containers to be unmerged", nameof(rootContainer)); } var cic = rootContainer.GetCohortIdentificationConfiguration(); var toReturn = new List <CohortIdentificationConfiguration>(); try { // clone the input cic cic = cic.CreateClone(new ThrowImmediatelyCheckNotifier()); // grab the new clone root container rootContainer = cic.RootCohortAggregateContainer; } catch (Exception ex) { throw new Exception("Error during pre merge cloning stage, no UnMerge will be attempted", ex); } using (_repository.BeginNewTransactedConnection()) { // For each of these foreach (var subContainer in rootContainer.GetSubContainers().OrderBy(c => c.Order)) { // create a new config var newCic = new CohortIdentificationConfiguration(_repository, $"Un Merged { subContainer.Name } ({subContainer.ID }) "); //take the container we are splitting out subContainer.MakeIntoAnOrphan(); //make it the root container of the new cic newCic.RootCohortAggregateContainer_ID = subContainer.ID; newCic.SaveToDatabase(); // Make the new name of all the AggregateConfigurations match the new cic foreach (var child in subContainer.GetAllAggregateConfigurationsRecursively()) { EnsureNamingConvention(newCic, child); } toReturn.Add(newCic); } //Now delete the original clone that we unmerged the containers out of cic.DeleteInDatabase(); //finish transaction _repository.EndTransactedConnection(true); } return(toReturn.ToArray()); }
/// <summary> /// Makes the other <see cref="CohortAggregateContainer"/> into a subcontainer of this container /// </summary> /// <param name="child"></param> public void AddChild(CohortAggregateContainer child) { _manager.Add(this, child); }
/// <summary> /// Makes the other <see cref="CohortAggregateContainer"/> into a subcontainer of this container /// </summary> /// <param name="child"></param> public void AddChild(CohortAggregateContainer child) { CreateInsertionPointAtOrder(child, child.Order, true); _manager.Add(this, child); }