Esempio n. 1
0
        /// <summary>
        /// Finds all templates for a field ID.
        /// </summary>
        /// <param name="files">The files.</param>
        /// <param name="fieldId">The field identifier.</param>
        /// <returns></returns>
        public static IEnumerable <RainbowFile> FindAllTemplatesForField(IEnumerable <AdditionalText> files, Guid fieldId)
        {
            List <RainbowFile> result = new List <RainbowFile>();

            lock (readAllFilesLock)
            {
                RainbowFile file;
                Evaluate(files, null, out file);

                var         allRainbowFiles       = rainbowFiles.Values;
                RainbowFile potentialTemplateFile = allRainbowFiles.FirstOrDefault(f => Guid.Equals(f.Id, fieldId));
                while (potentialTemplateFile != null)
                {
                    if (Guid.Equals(potentialTemplateFile.TemplateId, SitecoreConstants.SitecoreTemplateTemplateId))
                    {
                        break;
                    }

                    potentialTemplateFile = allRainbowFiles.FirstOrDefault(f => Guid.Equals(f.Id, potentialTemplateFile.ParentId));
                }

                if (potentialTemplateFile != null)
                {
                    result.Add(potentialTemplateFile);

                    var allTemplateFiles = allRainbowFiles.Where(f => Guid.Equals(f.TemplateId, SitecoreConstants.SitecoreTemplateTemplateId)).ToList();
                    result.AddRange(FindDerivedTemplates(allTemplateFiles, potentialTemplateFile, 200));
                }
            }

            return(result.Distinct());
        }
        /// <summary>
        /// Parses the rainbow (.yml) file.
        /// </summary>
        /// <param name="text">The text of the .yml file.</param>
        /// <returns></returns>
        public static RainbowFile ParseRainbowFile(AdditionalText text)
        {
            const string idParseKey                    = "ID: ";
            const string pathParseKey                  = "Path: ";
            const string templateParseKey              = "Template: ";
            const string parentParseKey                = "Parent: ";
            const string baseTemplateIntroLine         = "- ID: \"12c33f3f-86c5-43a5-aeb4-5598cec45116\"";
            const string baseTemplateIntroLineNoQuotes = "- ID: 12c33f3f-86c5-43a5-aeb4-5598cec45116";
            const string baseTemplateParseKey          = "Value: ";

            var textLines = text.GetText().ToString().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

            if (textLines.Any())
            {
                var result = new RainbowFile();

                string textLineId = textLines.FirstOrDefault(l => l.StartsWith(idParseKey));
                Guid   idGuid;
                if (textLineId != null && Guid.TryParse(textLineId.Substring(idParseKey.Length).Trim(' ', '"'), out idGuid))
                {
                    result.Id = idGuid;
                }

                var  textLineParent = textLines.FirstOrDefault(l => l.StartsWith(parentParseKey));
                Guid parentIdGuid;
                if (textLineParent != null && Guid.TryParse(textLineParent.Substring(parentParseKey.Length).Trim(' ', '"'), out parentIdGuid))
                {
                    result.ParentId = parentIdGuid;
                }

                var textLinePath = textLines.FirstOrDefault(l => l.StartsWith(pathParseKey));
                if (textLinePath != null)
                {
                    result.Path = textLinePath.Substring(pathParseKey.Length).Trim();
                }

                string textLineTemplate = textLines.FirstOrDefault(l => l.StartsWith(templateParseKey));
                Guid   templateGuid;
                if (textLineTemplate != null && Guid.TryParse(textLineTemplate.Substring(templateParseKey.Length).Trim(' ', '"'), out templateGuid))
                {
                    result.TemplateId = templateGuid;

                    // Parse base template(s) if the item is a template
                    if (Guid.Equals(result.TemplateId, SitecoreConstants.SitecoreTemplateTemplateId))
                    {
                        result.BaseTemplates = new List <Guid>();

                        ////int? lineIndex = textLines
                        ////    .Select((l, i) => new { Index = i, Line = l })
                        ////    .FirstOrDefault(l => string.Equals(baseTemplateIntroLine, l.Line.Trim()) || string.Equals(baseTemplateIntroLineNoQuotes, l.Line.Trim()))?.Index;

                        var baseTemplateIdLines = textLines
                                                  .SkipWhile(l => !(string.Equals(baseTemplateIntroLine, l.Trim()) || string.Equals(baseTemplateIntroLineNoQuotes, l.Trim())))
                                                  .SkipWhile(l => !l.TrimStart().StartsWith(baseTemplateParseKey))
                                                  .TakeWhile(l => l.StartsWith("  "));
                        foreach (string baseTemplateIdLine in baseTemplateIdLines)
                        {
                            string line = baseTemplateIdLine.Trim();
                            if (line.StartsWith(baseTemplateParseKey))
                            {
                                line = line.Substring(baseTemplateParseKey.Length);
                            }

                            line = line.Trim(' ', '|', '"');
                            Guid baseTemplateId;
                            if (Guid.TryParse(line, out baseTemplateId))
                            {
                                result.BaseTemplates.Add(baseTemplateId);
                            }
                        }
                    }
                }

                return(result);
            }

            // Not a valid result, but return an empty object anyway so it won't have to be parsed more often
            return(new RainbowFile());
        }
Esempio n. 3
0
        /// <summary>
        /// Evaluates if any of the .yml files match the specified function.
        /// </summary>
        /// <param name="files">The .yml files.</param>
        /// <param name="evaluateFunction">The evaluation function.</param>
        /// <param name="matchingFile">The matching file.</param>
        /// <returns></returns>
        public static bool Evaluate(IEnumerable <AdditionalText> files, Func <RainbowFile, bool> evaluateFunction, out RainbowFile matchingFile)
        {
            matchingFile = null;
            foreach (AdditionalText text in files)
            {
                RainbowFile file;

                // This code will probably not run in parallel, but ensure that the dictionaries remain in sync just in case
                lock (rainbowFileHashes)
                {
                    if (rainbowFileHashes.ContainsKey(text.Path))
                    {
                        // We have already parsed this file, so check if our cache is up to date
                        if (rainbowFileHashes[text.Path] == text.GetHashCode())
                        {
                            // The cache is up to date, so use the cached version
                            file = rainbowFiles[text.Path];
                        }
                        else
                        {
                            // Update the cache
                            rainbowFileHashes[text.Path] = text.GetHashCode();
                            file = RainbowParserUtil.ParseRainbowFile(text);
                            rainbowFiles[text.Path] = file;
                        }
                    }
                    else
                    {
                        // Parse the file and add it to the cache
                        rainbowFileHashes.Add(text.Path, text.GetHashCode());
                        file = RainbowParserUtil.ParseRainbowFile(text);
                        rainbowFiles.Add(text.Path, file);
                    }
                }

                // Only stop evaluating if something matches
                if (evaluateFunction != null && evaluateFunction(file))
                {
                    matchingFile = file;
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 4
0
        /// <summary>
        /// Finds derived templates recursively.
        /// </summary>
        /// <param name="allTemplateFiles">All template files.</param>
        /// <param name="templateFile">The template.</param>
        /// <param name="maxDepth">The maximum depth, to prevent stack overflow if there are circular references.</param>
        /// <returns></returns>
        private static IEnumerable <RainbowFile> FindDerivedTemplates(List <RainbowFile> allTemplateFiles, RainbowFile templateFile, int maxDepth)
        {
            if (maxDepth > 0)
            {
                foreach (RainbowFile derivedTemplate in allTemplateFiles.Where(t => t.BaseTemplates != null && t.BaseTemplates.Contains(templateFile.Id)))
                {
                    yield return(derivedTemplate);

                    foreach (var derived in FindDerivedTemplates(allTemplateFiles, derivedTemplate, maxDepth - 1))
                    {
                        yield return(derived);
                    }
                }
            }
        }