// ProjectTemplate.cs // // Author: // Mike Krüger (mkrueger@novell.com) // Lluis Sanchez Gual (lluis@novell.com) // Michael Hutchinson (mhutchinson@novell.com) // Marek Sieradzki (marek.sieradzki@gmail.com) // Viktoria Dudka (viktoriad@remobjects.com) // // Copyright (c) 2009 RemObjects Software // // 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.IO; using System.Xml; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Reflection; using System.CodeDom; using System.CodeDom.Compiler; using MonoDevelop.Core; using Mono.Addins; using MonoDevelop.Ide.Codons; using MonoDevelop.Projects; using MonoDevelop.Ide.Gui; using MonoDevelop.Projects.CodeGeneration; namespace MonoDevelop.Ide.Templates { internal class ProjectTemplate { public static List ProjectTemplates = new List (); private List actions = new List (); private string createdSolutionName; private ProjectCreateInformation createdProjectInformation = null; private SolutionDescriptor solutionDescriptor = null; public SolutionDescriptor SolutionDescriptor { get { return solutionDescriptor; } } private string languagename; public string LanguageName { get { return languagename; } } private string id; public string Id { get { return id; } } private string category; public string Category { get { return category; } } private string icon; public IconId Icon { get { return icon; } } private string description; public string Description { get { return description; } } private string name; public string Name { get { return name; } } private string originator; public string Originator { get { return originator; } } private string created; public string Created { get { return created; } } private string lastModified; public string LastModified { get { return lastModified; } } private string wizardPath; public string WizardPath { get { return wizardPath; } } //constructors static ProjectTemplate () { AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Ide/ProjectTemplates", OnExtensionChanged); } protected ProjectTemplate (RuntimeAddin addin, string id, ProjectTemplateCodon codon, string overrideLanguage) { XmlDocument xmlDocument = codon.GetTemplate (); XmlElement xmlConfiguration = xmlDocument.DocumentElement ["TemplateConfiguration"]; if (xmlConfiguration ["_Category"] != null) { category = addin.Localizer.GetString (xmlConfiguration ["_Category"].InnerText); } else throw new InvalidOperationException (string.Format ("_Category missing in file template {0}", codon.Id)); if (!string.IsNullOrEmpty (overrideLanguage)) { this.languagename = overrideLanguage; this.category = overrideLanguage + "/" + this.category; } else if (xmlConfiguration ["LanguageName"] != null) { List listLanguages = new List (); foreach (string item in xmlConfiguration ["LanguageName"].InnerText.Split (',')) listLanguages.Add (item.Trim ()); ExpandLanguageWildcards (listLanguages); this.languagename = listLanguages [0]; if (listLanguages.Count > 1 && !String.IsNullOrEmpty (languagename) && !category.StartsWith (languagename + "/")) category = languagename + "/" + category; for (int i = 1; i < listLanguages.Count; i++) { string language = listLanguages[i]; try { ProjectTemplates.Add (new ProjectTemplate (addin, id, codon, language)); } catch (Exception e) { LoggingService.LogError (GettextCatalog.GetString ("Error loading template {0} for language {1}", codon.Id, language), e); } } } this.id = id; this.originator = xmlDocument.DocumentElement.GetAttribute ("originator"); this.created = xmlDocument.DocumentElement.GetAttribute ("created"); this.lastModified = xmlDocument.DocumentElement.GetAttribute ("lastModified"); if (xmlConfiguration ["Wizard"] != null) { this.wizardPath = xmlConfiguration ["Wizard"].InnerText; } if (xmlConfiguration ["_Name"] != null) { this.name = addin.Localizer.GetString (xmlConfiguration ["_Name"].InnerText); } if (xmlConfiguration ["_Description"] != null) { this.description = addin.Localizer.GetString (xmlConfiguration ["_Description"].InnerText); } if (xmlConfiguration ["Icon"] != null) { this.icon = ImageService.GetStockId (addin, xmlConfiguration ["Icon"].InnerText, Gtk.IconSize.Dnd); } if (xmlDocument.DocumentElement ["Combine"] == null) { throw new InvalidOperationException ("Combine element not found"); } else { solutionDescriptor = SolutionDescriptor.CreateSolutionDescriptor (addin, xmlDocument.DocumentElement ["Combine"], codon.BaseDirectory); } if (xmlDocument.DocumentElement ["Actions"] != null) { foreach (XmlNode xmlElement in xmlDocument.DocumentElement ["Actions"]) { if (xmlElement is XmlElement && xmlElement.Attributes ["filename"] != null) actions.Add (xmlElement.Attributes ["filename"].Value); } } } protected ProjectTemplate (RuntimeAddin addin, string id, ProjectTemplateCodon codon) : this (addin, id, codon, null) { } //methods public void OpenCreatedSolution () { IAsyncOperation asyncOperation = IdeApp.Workspace.OpenWorkspaceItem (createdSolutionName); asyncOperation.WaitForCompleted (); if (asyncOperation.Success) { foreach (string action in actions) { IdeApp.Workbench.OpenDocument (Path.Combine (createdProjectInformation.ProjectBasePath, action)); } } } public WorkspaceItem CreateWorkspaceItem (ProjectCreateInformation cInfo) { WorkspaceItem workspaceItem = solutionDescriptor.CreateEntry (cInfo, this.languagename); this.createdSolutionName = workspaceItem.FileName; this.createdProjectInformation = cInfo; return workspaceItem; } public SolutionEntityItem CreateProject (SolutionItem policyParent, ProjectCreateInformation cInfo) { if (solutionDescriptor.EntryDescriptors.Length == 0) throw new InvalidOperationException ("Solution template doesn't have any project templates"); SolutionEntityItem solutionEntryItem = solutionDescriptor.EntryDescriptors [0].CreateItem (cInfo, this.languagename); solutionDescriptor.EntryDescriptors [0].InitializeItem (policyParent, cInfo, this.languagename, solutionEntryItem); this.createdProjectInformation = cInfo; return solutionEntryItem; } static void OnExtensionChanged (object s, ExtensionNodeEventArgs args) { if (args.Change == ExtensionChange.Add) { ProjectTemplateCodon codon = (ProjectTemplateCodon) args.ExtensionNode; try { ProjectTemplates.Add (new ProjectTemplate (codon.Addin, codon.Id, codon, null)); } catch (Exception e) { string extId = null, addinId = null; if (codon != null) { if (codon.HasId) extId = codon.Id; if (codon.Addin != null) addinId = codon.Addin.Id; } LoggingService.LogError ("Error loading template id {0} in addin {1}:\n{2}", extId ?? "(null)", addinId ?? "(null)", e.ToString ()); } } else { foreach (ProjectTemplate pt in ProjectTemplates) { ProjectTemplateCodon codon = (ProjectTemplateCodon) args.ExtensionNode; if (pt.Id == codon.Id) { ProjectTemplates.Remove (pt); break; } } } } void ExpandLanguageWildcards (List list) { //Template can match all CodeDom .NET languages with a "*" if (list.Contains ("*")) { foreach (ILanguageBinding lb in LanguageBindingService.LanguageBindings) { IDotNetLanguageBinding dnlang = lb as IDotNetLanguageBinding; if (dnlang != null && dnlang.GetCodeDomProvider () != null) list.Add (dnlang.Language); list.Remove ("*"); } } } public bool HasItemFeatures (SolutionFolder parentFolder, ProjectCreateInformation cinfo) { ISolutionItemDescriptor sid = solutionDescriptor.EntryDescriptors [0]; SolutionEntityItem sampleItem = sid.CreateItem (cinfo, languagename); return (SolutionItemFeatures.GetFeatures (parentFolder, sampleItem).Length > 0); } } }