// // HtmlSchemaService.cs // // Author: // Michael Hutchinson // // Copyright (C) 2008 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using MonoDevelop.Core; using MonoDevelop.Ide.CodeCompletion; using MonoDevelop.Xml.Completion; namespace MonoDevelop.AspNet.Html { public static class HtmlSchemaService { static Dictionary schemas; #region Service loading public static void Initialise () { if (schemas != null) return; schemas = new Dictionary (); //load all the schemas from addin points //NOTE: the first ([0]) schema must be the default schema foreach (DocTypeExtensionNode node in Mono.Addins.AddinManager.GetExtensionNodes ("/MonoDevelop/Html/DocTypes")) { if (schemas.ContainsKey (node.Name)) LoggingService.LogWarning ( "HtmlSchemaService cannot register duplicate doctype with the name '{0}'", node.Name); if (!string.IsNullOrEmpty (node.XsdFile)) { string path = node.Addin.GetFilePath (node.XsdFile); try { IXmlCompletionProvider provider = new XmlSchemaCompletionData (path); schemas.Add (node.Name, new HtmlSchema (node.Name, node.FullName, provider)); } catch (Exception ex) { LoggingService.LogWarning ( "HtmlSchemaService encountered an error registering the schema '" + path + "'", ex); } } else { schemas.Add (node.Name, new HtmlSchema (node.Name, node.FullName, node.CompletionDocTypeName)); } } //initialise the default backup schema if it doesn't exist already if (!schemas.ContainsKey (DefaultDocTypeName)) { HtmlSchema defaultSubstProvider = schemas["XHTML 1.0 Transitional"]; IXmlCompletionProvider provider; if (defaultSubstProvider != null) { //start the threaded schema loading LoadSchema (defaultSubstProvider, true); provider = defaultSubstProvider.CompletionProvider; } else { LoggingService.LogWarning ("Completion schema for default HTML doctype not found."); provider = new EmptyXmlCompletionProvider (); } schemas[DefaultDocTypeName] = new HtmlSchema ("HTML 4.01 Transitional", "", provider); } MonoDevelop.Core.LoggingService.LogDebug ("HtmlSchemaService initialised"); } #endregion public static string DefaultDocTypeName { get { return "HTML 4.01 Transitional"; } } public static HtmlSchema DefaultDocType { get { if (schemas == null) Initialise (); return schemas[DefaultDocTypeName]; } } public static HtmlSchema GetSchema (string docType) { return GetSchema (docType, false); } //if lazy==true, then if the schema is lazily compiled, it gets force-compiled in a thread and null is returned public static HtmlSchema GetSchema (string docType, bool lazy) { if (schemas == null) Initialise (); if (!string.IsNullOrEmpty (docType)) foreach (HtmlSchema schema in schemas.Values) if (docType.Contains (schema.Name)) return LoadSchema (schema, lazy); return null; } //if lazy == true, returns null if the schema isn't loaded yet static HtmlSchema LoadSchema (HtmlSchema schema, bool lazy) { ILazilyLoadedProvider lazyProv = schema.CompletionProvider as ILazilyLoadedProvider; if (lazyProv == null || lazyProv.IsLoaded) { return schema; } else { //FIXME: actually implement threaded loading and return null if loading && lazy lazyProv.EnsureLoaded (); return schema; } } public static IXmlCompletionProvider LazyGetProvider (HtmlSchema schema) { //get the provided schema, if it's loaded HtmlSchema hs = LoadSchema (schema, true); //fall back to the defaul provider if (hs == null) hs = LoadSchema (DefaultDocType, true); //fall back to a blank provider return new EmptyXmlCompletionProvider (); } public static IEnumerable DocTypeCompletionData { get { if (schemas == null) Initialise (); foreach (HtmlSchema item in schemas.Values) yield return new DocTypeCompletionData (item.Name, item.DocType); } } } }