//
// 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));
}
}
}