// // ExtensionNodeDescription.cs // // Author: // Lluis Sanchez Gual // // Copyright (C) 2007 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.Xml; using System.Collections.Specialized; using Mono.Addins.Serialization; namespace Mono.Addins.Description { /// /// An extension node definition. /// public class ExtensionNodeDescription: ObjectDescription, NodeElement { ExtensionNodeDescriptionCollection childNodes; string[] attributes; string nodeName; /// /// Initializes a new instance of the class. /// /// /// Node name. /// public ExtensionNodeDescription (string nodeName) { this.nodeName = nodeName; } internal ExtensionNodeDescription (XmlElement elem) { Element = elem; nodeName = elem.LocalName; } internal ExtensionNodeDescription () { } /// /// Gets the type of the node. /// /// /// The node type. /// /// /// This method only works when the add-in description to which the node belongs has been /// loaded from an add-in registry. /// public ExtensionNodeType GetNodeType () { if (Parent is Extension) { Extension ext = (Extension) Parent; object ob = ext.GetExtendedObject (); if (ob is ExtensionPoint) { ExtensionPoint ep = (ExtensionPoint) ob; return ep.NodeSet.GetAllowedNodeTypes () [NodeName]; } else if (ob is ExtensionNodeDescription) { ExtensionNodeDescription pn = (ExtensionNodeDescription) ob; ExtensionNodeType pt = ((ExtensionNodeDescription) pn).GetNodeType (); if (pt != null) return pt.GetAllowedNodeTypes () [NodeName]; } } else if (Parent is ExtensionNodeDescription) { ExtensionNodeType pt = ((ExtensionNodeDescription) Parent).GetNodeType (); if (pt != null) return pt.GetAllowedNodeTypes () [NodeName]; } return null; } /// /// Gets the extension path under which this node is registered /// /// /// The parent path. /// /// /// For example, if the id of the node is 'ThisNode', and the node is a child of another node with id 'ParentNode', and /// that parent node is defined in an extension with the path '/Core/MainExtension', then the parent path is 'Core/MainExtension/ParentNode'. /// public string GetParentPath () { if (Parent is Extension) return ((Extension)Parent).Path; else if (Parent is ExtensionNodeDescription) { ExtensionNodeDescription pn = (ExtensionNodeDescription) Parent; return pn.GetParentPath () + "/" + pn.Id; } else return string.Empty; } internal override void Verify (string location, StringCollection errors) { if (nodeName == null || nodeName.Length == 0) errors.Add (location + "Node: NodeName can't be empty."); ChildNodes.Verify (location + NodeName + "/", errors); } /// /// Gets or sets the name of the node. /// /// /// The name of the node. /// public string NodeName { get { return nodeName; } internal set { if (Element != null) throw new InvalidOperationException ("Can't change node name of xml element"); nodeName = value; } } /// /// Gets or sets the identifier of the node. /// /// /// The identifier. /// public string Id { get { return GetAttribute ("id"); } set { SetAttribute ("id", value); } } /// /// Gets or sets the identifier of the node after which this node has to be inserted /// /// /// The identifier of the reference node /// public string InsertAfter { get { return GetAttribute ("insertafter"); } set { if (value == null || value.Length == 0) RemoveAttribute ("insertafter"); else SetAttribute ("insertafter", value); } } /// /// Gets or sets the identifier of the node before which this node has to be inserted /// /// /// The identifier of the reference node /// public string InsertBefore { get { return GetAttribute ("insertbefore"); } set { if (value == null || value.Length == 0) RemoveAttribute ("insertbefore"); else SetAttribute ("insertbefore", value); } } /// /// Gets a value indicating whether this node is a condition. /// /// /// true if this node is a condition; otherwise, false. /// public bool IsCondition { get { return nodeName == "Condition" || nodeName == "ComplexCondition"; } } internal override void SaveXml (XmlElement parent) { CreateElement (parent, nodeName); if (attributes != null) { for (int n = 0; n < attributes.Length; n += 2) Element.SetAttribute (attributes [n], attributes [n + 1]); } ChildNodes.SaveXml (Element); } /// /// Gets the value of an attribute. /// /// /// The value of the attribute, or an empty string if the attribute is not defined. /// /// /// Name of the attribute. /// public string GetAttribute (string key) { if (Element != null) return Element.GetAttribute (key); if (attributes == null) return string.Empty; for (int n=0; n /// Sets the value of an attribute. /// /// /// Name of the attribute /// /// /// The value. /// public void SetAttribute (string key, string value) { if (Element != null) { Element.SetAttribute (key, value); return; } if (value == null) value = string.Empty; if (attributes == null) { attributes = new string [2]; attributes [0] = key; attributes [1] = value; return; } for (int n=0; n /// Removes an attribute. /// /// /// Name of the attribute to remove. /// public void RemoveAttribute (string name) { if (Element != null) { Element.RemoveAttribute (name); return; } if (attributes == null) return; for (int n=0; n /// Gets the attributes of the node. /// /// /// The attributes. /// public NodeAttribute[] Attributes { get { string [] result = SaveXmlAttributes (); if (result == null || result.Length == 0) return new NodeAttribute [0]; NodeAttribute[] ats = new NodeAttribute [result.Length / 2]; for (int n=0; n /// Gets the child nodes. /// /// /// The child nodes. /// public ExtensionNodeDescriptionCollection ChildNodes { get { if (childNodes == null) { childNodes = new ExtensionNodeDescriptionCollection (this); if (Element != null) { foreach (XmlNode nod in Element.ChildNodes) { if (nod is XmlElement) childNodes.Add (new ExtensionNodeDescription ((XmlElement)nod)); } } } return childNodes; } } NodeElementCollection NodeElement.ChildNodes { get { return ChildNodes; } } string[] SaveXmlAttributes () { if (Element != null) { var result = new string [Element.Attributes.Count * 2]; for (int n = 0; n < result.Length; n += 2) { XmlAttribute at = Element.Attributes [n / 2]; result [n] = at.LocalName; result [n + 1] = at.Value; } return result; } return attributes; } internal override void Write (BinaryXmlWriter writer) { writer.WriteValue ("nodeName", nodeName); writer.WriteValue ("attributes", SaveXmlAttributes ()); writer.WriteValue ("ChildNodes", ChildNodes); } internal override void Read (BinaryXmlReader reader) { nodeName = reader.ReadStringValue ("nodeName"); attributes = (string[]) reader.ReadValue ("attributes"); childNodes = (ExtensionNodeDescriptionCollection) reader.ReadValue ("ChildNodes", new ExtensionNodeDescriptionCollection (this)); } } }