/// <summary>
        /// Check if a given manifest is valid for the current files in the package.
        /// </summary>
        /// <param name="manifest">The manifest object to test.</param>
        /// <param name="errMsg">If the function returns false, this string will contain an error message.</param>
        /// <returns>true if the manifest is valid, false otherwise.</returns>
        public bool IsValidManifest(TemplatePackageManifest manifest, out string errMsg)
        {
            Dictionary <string, Dependency> dict = new Dictionary <string, Dependency>();
            Dictionary <string, string>     dictT = new Dictionary <string, string>();
            string         name, key, location;
            DependencyType depType;
            int            i;

            //
            if (manifest == null)
            {
                errMsg = "No manifest defined";
                return(false);
            }
            if (string.IsNullOrEmpty(manifest.HotDocsVersion))
            {
                errMsg = "Missing HotDocsVersion in manifest";
                return(false);
            }
            if (manifest.Version >= 11 && string.IsNullOrEmpty(manifest.PublishDateTime))
            {
                errMsg = "Missing PublishDateTime in manifest";
                return(false);
            }
            if (manifest.MainTemplate == null)
            {
                errMsg = "MainTemplate in manifest cannot be null";
                return(false);
            }
            location = "MainTemplate";
            if (!CollectDependencies(manifest.MainTemplate, dict, out errMsg))
            {
                errMsg = "Error in " + location + " of manifest: " + errMsg;
                return(false);
            }
            name       = manifest.MainTemplate.FileName;
            key        = name.ToLower();
            dict[key]  = new Dependency(name, DependencyType.Assemble);
            dictT[key] = name;
            for (i = 0; i < manifest.OtherTemplates.Length; i++)
            {
                location = string.Format("OtherTemplates[{0}]", i + 1);
                if (!CollectDependencies(manifest.OtherTemplates[i], dict, out errMsg))
                {
                    errMsg = "Error in " + location + " of manifest: " + errMsg;
                    return(false);
                }
                name = manifest.OtherTemplates[i].FileName;
                key  = name.ToLower();
                if (dictT.ContainsKey(key))
                {
                    errMsg = "Error in " + location + " of manifest: template'" + name + "' has been defined already";
                    return(false);
                }
                dictT[key] = name;
            }
            foreach (var d in dict)
            {
                key     = d.Key;
                name    = d.Value.FileName;
                depType = d.Value.DependencyType;
                if (Dependency.IsTemplateDependency(depType) && !dictT.ContainsKey(key))
                {
                    errMsg = "Template '" + name + "' is not defined in the manifest but is listed as a dependency";
                    return(false);
                }
                if (!FileExists(name))
                {
                    errMsg = "File '" + name + "' in manifest doesn't exist in the package";
                    return(false);
                }
            }
            location = "MainTemplate";
            if (!IsValidTemplateInfo(manifest.MainTemplate, dict, out errMsg))
            {
                errMsg = "Error in " + location + " of manifest: " + errMsg;
                return(false);
            }
            for (i = 0; i < manifest.OtherTemplates.Length; i++)
            {
                location = string.Format("OtherTemplates[{0}]", i + 1);
                if (!IsValidTemplateInfo(manifest.OtherTemplates[i], dict, out errMsg))
                {
                    errMsg = "Error in " + location + " of manifest: " + errMsg;
                    return(false);
                }
            }
            if (manifest.AdditionalFiles == null)
            {
                errMsg = "AdditionalFiles in manifest cannot be null";
                return(false);
            }
            for (i = 0; i < manifest.AdditionalFiles.Length; i++)
            {
                location = string.Format("AdditionalFiles[{0}]", i + 1);
                name     = manifest.AdditionalFiles[i];
                if (string.IsNullOrEmpty(name))
                {
                    errMsg = location + " in manifest cannot be null or empty";
                    return(false);
                }
                key = name.ToLower();
                if (dict.ContainsKey(key))
                {
                    errMsg = "Additional file '" + name + "' in manifest is already referenced from a template or occurs twice in additional files";
                    return(false);
                }
                dict[key] = new Dependency(name, DependencyType.NoDependency);
                if (!FileExists(name))
                {
                    errMsg = "Additional file '" + name + "' in manifest doesn't exist in the package";
                    return(false);
                }
            }
            foreach (string s in GetFiles())
            {
                name = s;
                key  = name.ToLower();
                if (!dict.ContainsKey(key))
                {
                    errMsg = "File '" + name + "' in package is not referenced in manifest";
                    return(false);
                }
            }
            errMsg = string.Empty;
            return(true);
        }
        private bool IsValidTemplateInfo(TemplateInfo ti, Dictionary <string, Dependency> dict, out string errMsg)
        {
            string         name, key, keyC, ext;
            DependencyType depType;
            Dictionary <string, string> dictS = new Dictionary <string, string>();
            bool hasJs = false, hasHvc = false;

            //
            name    = ti.FileName;
            key     = name.ToLower();
            depType = dict[key].DependencyType;
            if (string.IsNullOrEmpty(ti.EffectiveComponentFile))
            {
                errMsg = "EffectiveComponentFile cannot be null or empty";
                return(false);
            }
            keyC = ti.EffectiveComponentFile.ToLower();
            if (!dict.ContainsKey(keyC))
            {
                errMsg = "EffectiveComponentFile doesn't occur in a dependency";
                return(false);
            }
            if (!FileExists(ti.EffectiveComponentFile))
            {
                errMsg = "EffectiveComponentFile defines the file '" + ti.EffectiveComponentFile + "' which is not part of the package";
                return(false);
            }
            if (ti.GeneratedFiles == null)
            {
                errMsg = "GeneratedFiles cannot be null";
                return(false);
            }
            foreach (string s in ti.GeneratedFiles)
            {
                if (string.IsNullOrEmpty(s))
                {
                    errMsg = "GeneratedFiles contains a null or empty string";
                    return(false);
                }
                name = s;
                key  = name.ToLower();
                if (dictS.ContainsKey(key))
                {
                    errMsg = "GeneratedFiles contains the file '" + name + "' more than once";
                    return(false);
                }
                dictS[key] = name;
                ext        = Path.GetExtension(key).ToLower();
                if (ext == ".js" || ext == ".hvc")
                {
                    hasJs  = hasJs || ext == ".js";
                    hasHvc = hasHvc || ext == ".hvc";
                    if (dict.ContainsKey(key))
                    {
                        errMsg = "GeneratedFiles contains the file '" + name + "' which is already referenced from another template";
                        return(false);
                    }
                    dict[key] = new Dependency(name, DependencyType.NoDependency);
                    if (!FileExists(name))
                    {
                        errMsg = "GeneratedFiles contains the file '" + name + "' which is not part of the package";
                        return(false);
                    }
                }
                else if (ext == ".dll")
                {
                    if (dict.ContainsKey(key))
                    {
                        errMsg = "GeneratedFiles contains the file '" + name + "' which is already referenced from another template";
                        return(false);
                    }
                    dict[key] = new Dependency(name, DependencyType.NoDependency);
                    if (!FileExists(name))
                    {
                        errMsg = "GeneratedFiles contains the file '" + name + "' which is not part of the package";
                        return(false);
                    }
                }
                else if (ext == ".xml")
                {
                    if (dict.ContainsKey(key))
                    {
                        errMsg = "GeneratedFiles contains the file '" + name + "' which is already referenced from another template";
                        return(false);
                    }
                    dict[key] = new Dependency(name, DependencyType.NoDependency);
                    if (!FileExists(name))
                    {
                        errMsg = "GeneratedFiles contains the file '" + name + "' which is not part of the package";
                        return(false);
                    }
                }
                else
                {
                    errMsg = "GeneratedFiles contains the file '" + name + "' which has an unknown file extension";
                    return(false);
                }
            }
            if (!hasJs && depType == DependencyType.Assemble)
            {
                errMsg = "GeneratedFiles doesn't contain a .js file";
                return(false);
            }
            if (!hasHvc && depType == DependencyType.Assemble)
            {
                errMsg = "GeneratedFiles doesn't contain a .hvc file";
                return(false);
            }
            errMsg = string.Empty;
            return(true);
        }