Beispiel #1
0
 public MultiTraitContext()
 {
     _empty  = new MultiTrait(this);
     _traits = new ConcurrentDictionary <string, MultiTrait>(StringComparer.Ordinal);
     _traits[String.Empty] = _empty;
     _creationLock         = new Object();
 }
Beispiel #2
0
        MultiTrait FindOrCreate(string traits, bool create)
        {
            if (traits == null || traits.Length == 0)
            {
                return(_empty);
            }
            traits = traits.Normalize();
            MultiTrait m;

            if (!_traits.TryGetValue(traits, out m))
            {
                int      traitCount;
                string[] splitTraits = SplitMultiTrait(traits, out traitCount);
                if (traitCount <= 0)
                {
                    return(_empty);
                }
                if (traitCount == 1)
                {
                    m = FindOrCreateAtomicTrait(splitTraits[0], create);
                }
                else
                {
                    traits = String.Join("+", splitTraits, 0, traitCount);
                    if (!_traits.TryGetValue(traits, out m))
                    {
                        MultiTrait[] atomics = new MultiTrait[traitCount];
                        for (int i = 0; i < traitCount; ++i)
                        {
                            MultiTrait trait = FindOrCreateAtomicTrait(splitTraits[i], create);
                            if ((atomics[i] = trait) == null)
                            {
                                return(null);
                            }
                        }
                        lock ( _creationLock )
                        {
                            if (!_traits.TryGetValue(traits, out m))
                            {
                                m = new MultiTrait(this, traits, new ReadOnlyListOnIList <MultiTrait>(atomics));
                                _traits[traits] = m;
                            }
                        }
                    }
                    Debug.Assert(!m.IsAtomic && m.AtomicTraits.Count == traitCount, "Combined trait.");
                }
            }
            return(m);
        }
Beispiel #3
0
        private MultiTrait FindOrCreateAtomicTrait(string trait, bool create)
        {
            MultiTrait m;

            if (!_traits.TryGetValue(trait, out m) && create)
            {
                lock ( _creationLock )
                {
                    if (!_traits.TryGetValue(trait, out m))
                    {
                        m = new MultiTrait(this, trait);
                        _traits[trait] = m;
                    }
                }
                Debug.Assert(m.IsAtomic, "Special construction for atomic traits.");
            }
            return(m);
        }
Beispiel #4
0
        /// <summary>
        /// Obtains a trait from a list of atomic (already sorted) traits.
        /// Used by fall back generation.
        /// </summary>
        internal MultiTrait FindOrCreate(MultiTrait[] atomicTraits, int count)
        {
            Debug.Assert(count > 1, "Atomic traits are handled directly.");

            Debug.Assert(!Array.Exists(atomicTraits, delegate(MultiTrait mA) { return(mA.Context != this || mA.AtomicTraits.Count != 1); }),
                         "Traits are from this Context and they are atomic and not empty.");

            StringBuilder b = new StringBuilder(atomicTraits[0].ToString());

            for (int i = 1; i < count; ++i)
            {
                Debug.Assert(StringComparer.Ordinal.Compare(atomicTraits[i - 1].ToString(), atomicTraits[i].ToString()) < 0, "Traits are already sorted and NO DUPLICATE exists.");
                b.Append('+').Append(atomicTraits[i].ToString());
            }
            string     traits = b.ToString();
            MultiTrait m;

            if (!_traits.TryGetValue(traits, out m))
            {
                // We must clone the array since fallback generation reuses it.
                if (atomicTraits.Length != count)
                {
                    MultiTrait[] subArray = new MultiTrait[count];
                    Array.Copy(atomicTraits, subArray, count);
                    atomicTraits = subArray;
                }
                else
                {
                    atomicTraits = (MultiTrait[])atomicTraits.Clone();
                }
                lock ( _creationLock )
                {
                    if (!_traits.TryGetValue(traits, out m))
                    {
                        m = new MultiTrait(this, traits, new ReadOnlyListOnIList <MultiTrait>(atomicTraits));
                        _traits[traits] = m;
                    }
                }
            }
            return(m);
        }
Beispiel #5
0
        /// <summary>
        /// Obtains a trait from a list of atomic (already sorted) traits.
        /// Used by the Add, Toggle, Remove, Intersect methods.
        /// </summary>
        internal MultiTrait FindOrCreate(List <MultiTrait> atomicTraits)
        {
            if (atomicTraits.Count == 0)
            {
                return(_empty);
            }
            Debug.Assert(atomicTraits[0].Context == this, "This is one of our traits.");
            Debug.Assert(atomicTraits[0].AtomicTraits.Count == 1, "This is an atomic trait and not the empty one.");
            if (atomicTraits.Count == 1)
            {
                return(atomicTraits[0]);
            }
            StringBuilder b = new StringBuilder(atomicTraits[0].ToString());

            for (int i = 1; i < atomicTraits.Count; ++i)
            {
                Debug.Assert(atomicTraits[i].Context == this, "This is one of our traits.");
                Debug.Assert(atomicTraits[i].AtomicTraits.Count == 1, "This is an atomic trait and not the empty one.");
                Debug.Assert(StringComparer.Ordinal.Compare(atomicTraits[i - 1].ToString(), atomicTraits[i].ToString()) < 0,
                             "Traits are already sorted and NO DUPLICATES exist.");
                b.Append('+').Append(atomicTraits[i].ToString());
            }
            string     traits = b.ToString();
            MultiTrait m;

            if (!_traits.TryGetValue(traits, out m))
            {
                lock ( _creationLock )
                {
                    if (!_traits.TryGetValue(traits, out m))
                    {
                        m = new MultiTrait(this, traits, new ReadOnlyListOnIList <MultiTrait>(atomicTraits.ToArray()));
                        _traits[traits] = m;
                    }
                }
            }
            return(m);
        }
Beispiel #6
0
        /// <summary>
        /// Finds a <see cref="MultiTrait"/> with only already existing atomic traits.
        /// </summary>
        /// <param name="traits">Atomic trait or traits separated by +.</param>
        /// <param name="collector">Optional collector for unknown trait. As soon as the collector returns false, the process stops.</param>
        /// <returns>A trait that contains only already existing traits or null if none already exists.</returns>
        public MultiTrait FindOnlyExisting(string traits, Func <string, bool> collector = null)
        {
            if (traits == null || traits.Length == 0)
            {
                return(null);
            }
            traits = traits.Normalize();
            MultiTrait m;

            if (!_traits.TryGetValue(traits, out m))
            {
                int      traitCount;
                string[] splitTraits = SplitMultiTrait(traits, out traitCount);
                if (traitCount <= 0)
                {
                    return(null);
                }
                if (traitCount == 1)
                {
                    m = FindOrCreateAtomicTrait(splitTraits[0], false);
                }
                else
                {
                    traits = String.Join("+", splitTraits, 0, traitCount);
                    if (!_traits.TryGetValue(traits, out m))
                    {
                        List <MultiTrait> atomics = new List <MultiTrait>();
                        for (int i = 0; i < traitCount; ++i)
                        {
                            MultiTrait trait = FindOrCreateAtomicTrait(splitTraits[i], false);
                            if (trait == null)
                            {
                                if (collector != null && !collector(splitTraits[i]))
                                {
                                    break;
                                }
                            }
                            else
                            {
                                atomics.Add(trait);
                            }
                        }
                        if (atomics.Count != 0)
                        {
                            traits = String.Join("+", atomics);
                            if (!_traits.TryGetValue(traits, out m))
                            {
                                lock ( _creationLock )
                                {
                                    if (!_traits.TryGetValue(traits, out m))
                                    {
                                        m = new MultiTrait(this, traits, atomics.ToReadOnlyList());
                                        _traits[traits] = m;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(m);
        }