/// <summary> /// Traverses the specified path, inserting <see cref="BranchNode"/>s as necessary, until the end of the path /// is reached, at which point the <paramref name="leafNodeProvider"/> is called to provide a leaf node to insert. /// </summary> protected void Insert(Path path, int pathDepth, Converter <PathSegment, ActionModelNode> leafNodeProvider) { int segmentCount = path.Segments.Count; if (segmentCount < 2) { throw new ArgumentException(SR.ExceptionInvalidActionPath); } PathSegment segment = path.Segments[pathDepth]; if (pathDepth + 1 == segmentCount) { // this is the last path segment -> leaf node _childNodes.Add(leafNodeProvider(segment)); } else { ActionModelNode child = FindChild(segment); if (child == null) { child = new BranchNode(segment); _childNodes.Add(child); } child.Insert(path, pathDepth + 1, leafNodeProvider); } }
/// <summary> /// Creates a copy of the subtree beginning at this node. /// </summary> protected ActionModelNode CloneTree() { ActionModelNode clone = CloneNode(this.PathSegment); foreach (ActionModelNode child in _childNodes) { clone._childNodes.Add(child.CloneTree()); } return(clone); }
/// <summary> /// Persists an in-memory abstract action model to the XML model. /// </summary> /// <remarks> /// This method functions as a counterpart to <see cref="BuildAbstractActionModel"/>. The specified abstract action model /// (created by <see cref="BuildAbstractActionModel"/>, or potentially modified further) is flattened and its nodes /// written out to the XML mode, replacing any existing model at the same qualified site. This allows action model /// configuration interfaces to make changes to the action model. /// </remarks> /// <param name="namespace">A namespace to qualify the site.</param> /// <param name="site">The site.</param> /// <param name="abstractActionModel">The abstract action model to be persisted.</param> /// <returns>An <see cref="ActionModelNode"/> representing the root of the action model.</returns> public void PersistAbstractActionModel(string @namespace, string site, ActionModelRoot abstractActionModel) { // do one time initialization if (_actionModelXmlDoc == null) { Initialize(); } XmlElement separatorTemplate = _actionModelXmlDoc.CreateElement("separator"); string actionModelId = string.Format("{0}:{1}", @namespace, site); XmlElement xmlActionModel = FindXmlActionModel(actionModelId); if (xmlActionModel != null) { // clear the action model List <XmlNode> childrenToClear = CollectionUtils.Cast <XmlNode>(xmlActionModel.ChildNodes); foreach (XmlNode childNode in childrenToClear) { xmlActionModel.RemoveChild(childNode); } } else { // add a new action model this.GetActionModelsNode().AppendChild(xmlActionModel = CreateXmlActionModel(actionModelId)); } ActionModelNode[] leafNodes = abstractActionModel.GetLeafNodesInOrder(); for (int n = 0; n < leafNodes.Length; n++) { ActionModelNode leafNode = leafNodes[n]; if (leafNode is ActionNode) { xmlActionModel.AppendChild(CreateXmlAction(_actionModelXmlDoc, ((ActionNode)leafNode).Action)); } else if (leafNode is SeparatorNode) { xmlActionModel.AppendChild(separatorTemplate.Clone()); } } if (!_temporary) { this.ActionModelsXml = _actionModelXmlDoc; this.Save(); } }
/// <summary> /// Merges the specified model into this model. /// </summary> public void Merge(ActionModelNode other) { foreach (ActionModelNode otherChild in other._childNodes) { ActionModelNode thisChild = FindChild(otherChild.PathSegment); if (thisChild != null) { thisChild.Merge(otherChild); } else { _childNodes.Add(otherChild.CloneTree()); } } }