/// <summary>
 /// Adds the specified relationship group end.
 /// </summary>
 /// <param name="end">The relationship group end.</param>
 /// <param name="isKey">Indicates if this end is part of the key.</param>
 public void Add(RelationshipGroupEnd end, bool isKey)
 {
     this.ends.Add(end);
     if (isKey)
     {
         this.endsWhichFormTheKey.Add(end);
     }
 }
 /// <summary>
 /// Adds the specified relationship group end.
 /// </summary>
 /// <param name="end">The relationship group end.</param>
 /// <param name="isKey">Indicates if this end is part of the key.</param>
 public void Add(RelationshipGroupEnd end, bool isKey)
 {
     this.ends.Add(end);
     if (isKey)
     {
         this.endsWhichFormTheKey.Add(end);
     }
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="RelationshipCandidate"/> class.
 /// </summary>
 /// <param name="parent">The parent relationship group end this candidate can be used for.</param>
 /// <param name="entityDataKey">The entity data key.</param>
 /// <param name="capacityRange">The capacity range.</param>
 public RelationshipCandidate(
     RelationshipGroupEnd parent,
     EntityDataKey entityDataKey,
     CapacityRange capacityRange)
 {
     this.EntityDataKey = entityDataKey;
     this.CapacityRange = capacityRange;
     this.Parent        = parent;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="RelationshipCandidate"/> class.
 /// </summary>
 /// <param name="parent">The parent relationship group end this candidate can be used for.</param>
 /// <param name="entityDataKey">The entity data key.</param>
 /// <param name="capacityRange">The capacity range.</param>
 public RelationshipCandidate(
     RelationshipGroupEnd parent,
     EntityDataKey entityDataKey,
     CapacityRange capacityRange)
 {
     this.EntityDataKey = entityDataKey;
     this.CapacityRange = capacityRange;
     this.Parent = parent;
 }
        private void RemoveCandidatesOnTargetBasedOnTreshhold(RelationshipGroupEnd end)
        {
            var candidatesOnTargetWithUnlimitedCapacity = end.Candidates.Where(
                c => c.IsMinimumRequirementMet && c.IsUnlimitedCapacity).ToList();

            for (int i = 0; i < candidatesOnTargetWithUnlimitedCapacity.Count - TreshholdForCandidatesOnTarget; i++)
            {
                this.RemoveCandidate(candidatesOnTargetWithUnlimitedCapacity[i]);
            }
        }
        /// <summary>
        /// Sets the capacity selector if specified association set and role belong to this relationship selector.
        /// </summary>
        /// <param name="associationSetName">The association set name.</param>
        /// <param name="roleName">The role name.</param>
        /// <param name="selector">The capacitye range selector.</param>
        /// <returns>True if the capacity range selector was set, false otherwise.</returns>
        public bool SetCapacitySelectorIfApplicable(string associationSetName, string roleName, Func <CapacityRange> selector)
        {
            RelationshipGroupEnd end = this.ends.Where(e => e.AssociationSetEnds.Any(kv => kv.Key.Name == associationSetName && kv.Value.AssociationEnd.RoleName == roleName)).SingleOrDefault();

            if (end != null)
            {
                end.CapacitySelector = selector;
                return(true);
            }

            return(false);
        }
        private void CreateRelationshipSelectors()
        {
            this.relationshipSelectors = new List<RelationshipSelector>();

            List<AssociationSet> visitedAssociationSets = new List<AssociationSet>();

            foreach (AssociationSet associationSet in this.EntityContainer.AssociationSets.Where(s => !visitedAssociationSets.Contains(s)))
            {
                var identifyingEnds = this.GetAllDependentEndsFromIdentifyingGroup(associationSet);

                if (identifyingEnds.Count > 0)
                {
                    RelationshipSelector selector = new RelationshipSelector(this.Random);

                    RelationshipGroupEnd dependentGroupEnd = new RelationshipGroupEnd(identifyingEnds);
                    selector.Add(dependentGroupEnd, false);

                    foreach (KeyValuePair<AssociationSet, AssociationSetEnd> associationSetAndEndPair in identifyingEnds)
                    {
                        AssociationSetEnd principalSetEnd = associationSetAndEndPair.Key.GetOtherEnd(associationSetAndEndPair.Value);
                        RelationshipGroupEnd principalGroupEnd = new RelationshipGroupEnd(associationSetAndEndPair.Key, principalSetEnd);
                        
                        selector.Add(principalGroupEnd, true);

                        visitedAssociationSets.Add(associationSetAndEndPair.Key);
                    }

                    this.relationshipSelectors.Add(selector);
                }
                else if (!this.HasOverlappingForeignKeys(associationSet))
                {
                    RelationshipSelector selector = new RelationshipSelector(this.Random);
                    
                    foreach (AssociationSetEnd end in associationSet.Ends)
                    {
                        RelationshipGroupEnd groupEnd = new RelationshipGroupEnd(associationSet, end);
                        selector.Add(groupEnd, end.AssociationEnd.Multiplicity == EndMultiplicity.Many && associationSet.GetOtherEnd(end).AssociationEnd.Multiplicity == EndMultiplicity.Many);
                    }
                   
                    this.relationshipSelectors.Add(selector);
                }

                visitedAssociationSets.Add(associationSet);
            }
        }
        private void RemoveCandidatesOnTargetBasedOnTreshhold(RelationshipGroupEnd end)
        {
            var candidatesOnTargetWithUnlimitedCapacity = end.Candidates.Where(
                c => c.IsMinimumRequirementMet && c.IsUnlimitedCapacity).ToList();

            for (int i = 0; i < candidatesOnTargetWithUnlimitedCapacity.Count - TreshholdForCandidatesOnTarget; i++)
            {
                this.RemoveCandidate(candidatesOnTargetWithUnlimitedCapacity[i]);
            }
        }