Example #1
0
        public string[] ResolveSet <T>(string matchIdentifier, T value, bool addIdentifierIfNotExists = false, Type associatedType = null)
        {
            CheckMatchIdentifier(matchIdentifier);

            MatchIdentifierRequestCacheEntry cacheEntry = GetOrCreateCacheEntry(matchIdentifier);

            string localIdentifier = matchIdentifier.Contains('.') ? matchIdentifier.Substring(matchIdentifier.LastIndexOf('.') + 1) : matchIdentifier;

            foreach (string fullIdentifier in cacheEntry.FullMatchedIdentifierArray)
            {
                IRegistry currentRegistry = cacheEntry.FullMatchedIdentifierRegistries[fullIdentifier];

                associatedType = associatedType ?? currentRegistry.GetAssociatedType(localIdentifier);

                currentRegistry.Set(localIdentifier, value, associatedType);
            }

            if (addIdentifierIfNotExists)
            {
                foreach (string fullIdentifier in cacheEntry.LastUnmatchedIdentifierRegistries.Keys)
                {
                    IRegistry currentRegistry = cacheEntry.LastUnmatchedIdentifierRegistries[fullIdentifier];

                    associatedType = associatedType ?? currentRegistry.GetAssociatedType(localIdentifier);

                    currentRegistry.Set(localIdentifier, value, associatedType);
                }
            }

            return(cacheEntry.FullMatchedIdentifierArray);
        }
Example #2
0
        public T[] ResolveGet <T>(string matchIdentifier, out string[] fullMatchedIdentifierArray, T[] values = null)
        {
            CheckMatchIdentifier(matchIdentifier);

            MatchIdentifierRequestCacheEntry cacheEntry = GetOrCreateCacheEntry(matchIdentifier);

            if (values == null || values.Length < cacheEntry.FullMatchedIdentifierArray.Length)
            {
                values = new T[cacheEntry.FullMatchedIdentifierArray.Length];
            }

            for (int i = 0; i < cacheEntry.FullMatchedIdentifierArray.Length; i++)
            {
                string fullIdentifier = cacheEntry.FullMatchedIdentifierArray[i];

                values[i] = cacheEntry.FullMatchedIdentifierRegistries[fullIdentifier].Get <T>(cacheEntry.FullMatchedIdentifierLocals[fullIdentifier]);
            }

            fullMatchedIdentifierArray = cacheEntry.FullMatchedIdentifierArray;

            return(values);
        }
Example #3
0
        public void OnChildHierarchyChanged(string identifier, IRegistry previousChild, IRegistry newChild)
        {
            lock (_matchIdentifierCache)
            {
                foreach (string fullIdentifier in _matchIdentifierCache.Keys)
                {
                    MatchIdentifierRequestCacheEntry entry = _matchIdentifierCache[fullIdentifier];

                    if (entry.AllReferredRegistries.Contains <IRegistry>(previousChild))
                    {
                        _fullIdentifiersToInvalidate.Add(fullIdentifier);
                    }
                }

                foreach (string fullIdentifier in _fullIdentifiersToInvalidate)
                {
                    _matchIdentifierCache.Remove(fullIdentifier);
                }
            }

            RemoveChildHierarchyListener(previousChild);
            AddChildHierarchyListener(newChild);
        }
Example #4
0
        private void AddMatchingIdentifiersFromRegistryTree(int hierarchyLevel, int lastHierarchySearchLevel, IRegistry currentRootAtLevel, string currentFullIdentifier, string[] parsedMatchIdentifierParts, ISet <string>[] conditionalTagsPerLevel, MatchIdentifierRequestCacheEntry newCacheEntry)
        {
            Regex regex = new Regex(parsedMatchIdentifierParts[hierarchyLevel]);

            bool noneMatched = true;

            foreach (string identifier in currentRootAtLevel.Keys.ToArray())             // TODO ugly hack, toarray is inefficient and is just to prevent "random" concurrent modification exception
            {
                if (regex.IsMatch(identifier))
                {
                    object value = currentRootAtLevel.Get(identifier);

                    if (hierarchyLevel < lastHierarchySearchLevel && value is IRegistry)
                    {
                        IRegistry subRegistry = (IRegistry)value;

                        if (RegistryMatchesAllTags(subRegistry, conditionalTagsPerLevel[hierarchyLevel]))
                        {
                            string nextFullIdentifier = String.IsNullOrEmpty(currentFullIdentifier) ? identifier : (currentFullIdentifier + "." + identifier);

                            AddMatchingIdentifiersFromRegistryTree(hierarchyLevel + 1, lastHierarchySearchLevel, subRegistry, nextFullIdentifier, parsedMatchIdentifierParts, conditionalTagsPerLevel, newCacheEntry);
                        }
                    }
                    else if (hierarchyLevel == lastHierarchySearchLevel)
                    {
                        if (value is IRegistry && !RegistryMatchesAllTags((IRegistry)value, conditionalTagsPerLevel[hierarchyLevel]))
                        {
                            continue;
                        }

                        string globalFullIdentifier = (String.IsNullOrEmpty(currentFullIdentifier) ? "" : currentFullIdentifier + ".") + identifier;

                        newCacheEntry.FullMatchedIdentifierRegistries.Add(globalFullIdentifier, currentRootAtLevel);
                        newCacheEntry.FullMatchedIdentifierLocals.Add(globalFullIdentifier, identifier);
                    }

                    noneMatched = false;
                }
            }

            if (noneMatched && hierarchyLevel == lastHierarchySearchLevel && !newCacheEntry.LastUnmatchedIdentifierRegistries.ContainsKey(currentFullIdentifier))
            {
                // keep last unmatched identifiers in case there is a (direct) resolve set
                newCacheEntry.LastUnmatchedIdentifierRegistries.Add(currentFullIdentifier, currentRootAtLevel);
            }
        }
Example #5
0
        private MatchIdentifierRequestCacheEntry GetOrCreateCacheEntry(string matchIdentifier)
        {
            CheckMatchIdentifier(matchIdentifier);

            lock (_matchIdentifierCache)
            {
                if (_matchIdentifierCache.ContainsKey(matchIdentifier))
                {
                    return(_matchIdentifierCache[matchIdentifier]);
                }
            }

            string[] matchIdentifierParts = matchIdentifier.Split('.');

            ISet <string>[] conditionalTagsPerLevel = new ISet <string> [matchIdentifierParts.Length];

            for (int i = 0; i < matchIdentifierParts.Length; i++)
            {
                matchIdentifierParts[i] = ParseMatchIdentifier(i, matchIdentifierParts[i], conditionalTagsPerLevel);
            }

            Dictionary <string, IRegistry> fullMatchedIdentifierRegistries = new Dictionary <string, IRegistry>();

            MatchIdentifierRequestCacheEntry newCacheEntry = new MatchIdentifierRequestCacheEntry(matchIdentifier, fullMatchedIdentifierRegistries, new Dictionary <string, string>(), null, null, new Dictionary <string, IRegistry>());

            AddMatchingIdentifiersFromRegistryTree(0, matchIdentifierParts.Length - 1, Root, "", matchIdentifierParts, conditionalTagsPerLevel, newCacheEntry);

            newCacheEntry.FullMatchedIdentifierArray = fullMatchedIdentifierRegistries.Keys.ToArray();
            newCacheEntry.AllReferredRegistries      = GetReferredRegistries(newCacheEntry.FullMatchedIdentifierRegistries.Values.ToList());

            ISet <string> unmatchedRegistriesToRemove = new HashSet <string>();

            foreach (var registry in newCacheEntry.LastUnmatchedIdentifierRegistries)
            {
                if (newCacheEntry.FullMatchedIdentifierRegistries.ContainsKey(registry.Key))
                {
                    unmatchedRegistriesToRemove.Add(registry.Key);
                }
            }

            foreach (string toRemove in unmatchedRegistriesToRemove)
            {
                newCacheEntry.LastUnmatchedIdentifierRegistries.Remove(toRemove);
            }

            // only cache if we found anything and the last identifier level did not contain a blank unrestricted wildcard
            //  (wildcard without conditional tags, meaning we can't cache anything as it could be any value)
            int  lastLevel              = matchIdentifierParts.Length - 1;
            bool foundAnything          = newCacheEntry.FullMatchedIdentifierArray.Length > 0;
            bool noUnrestrictedWildcard = !matchIdentifierParts[lastLevel].Contains(".*") || conditionalTagsPerLevel[lastLevel]?.Count > 0;
            bool shouldCache            = foundAnything && noUnrestrictedWildcard;

            lock (_matchIdentifierCache)
            {
                if (shouldCache)
                {
                    _matchIdentifierCache.Add(matchIdentifier, newCacheEntry);
                }
            }

            return(newCacheEntry);
        }