/// <inheritdoc/> internal override bool UpdateDataFrom(AXmlObject source) { if (!base.UpdateDataFrom(source)) return false; AXmlText src = (AXmlText)source; if (this.EscapedValue != src.EscapedValue || this.Value != src.Value) { OnChanging(); this.EscapedValue = src.EscapedValue; this.Value = src.Value; OnChanged(); return true; } else { return false; } }
/// <inheritdoc/> internal override bool UpdateDataFrom(AXmlObject source) { if (!base.UpdateDataFrom(source)) return false; AXmlElement src = (AXmlElement)source; // Clear the cache for this - quite expensive attributesAndElements = null; if (this.IsProperlyNested != src.IsProperlyNested || this.HasStartOrEmptyTag != src.HasStartOrEmptyTag || this.HasEndTag != src.HasEndTag) { OnChanging(); this.IsProperlyNested = src.IsProperlyNested; this.HasStartOrEmptyTag = src.HasStartOrEmptyTag; this.HasEndTag = src.HasEndTag; OnChanged(); return true; } else { return false; } }
/// <summary> /// To be used exclusively by the children update algorithm. /// Insert child and keep links consistent. /// </summary> void InsertChild(int index, AXmlObject item) { AXmlParser.Log("Inserting {0} at index {1}", item, index); Assert(this.Document != null, "Can not insert to dangling object"); Assert(item.Parent != this, "Can not own item twice"); SetParentPointersInTree(item); this.Children.InsertItemAt(index, item); this.Document.OnObjectInserted(index, item); }
/// <summary> Recursively fix all parent pointer in a tree </summary> /// <remarks> /// Cache constraint: /// If cached item has parent set, then the whole subtree must be consistent and document set /// </remarks> void SetParentPointersInTree(AXmlObject item) { // All items come from the parser cache if (item.Parent == null) { // Dangling object - either a new parser object or removed tree (still cached) item.Parent = this; item.Document = this.Document; AXmlContainer container = item as AXmlContainer; if (container != null) { foreach(AXmlObject child in container.Children) { container.SetParentPointersInTree(child); } } } else if (item.Parent == this) { // If node is attached and then deattached, it will have null parent pointer // but valid subtree - so its children will alredy have correct parent pointer // like in this case // item.DebugCheckConsistency(false); // Rest of the tree is consistent - do not recurse } else { // From cache & parent set => consitent subtree // item.DebugCheckConsistency(false); // The parent (or any futher parents) can not be part of parsed document // becuase otherwise this item would be included twice => safe to change parents // Maintain cache constraint by setting parents to null foreach(AXmlObject ancest in item.GetAncestors().ToList()) { ancest.Parent = null; } item.Parent = this; // Rest of the tree is consistent - do not recurse } }
/// <inheritdoc/> internal override bool UpdateDataFrom(AXmlObject source) { if (!base.UpdateDataFrom(source)) return false; AXmlAttribute src = (AXmlAttribute)source; if (this.Name != src.Name || this.EqualsSign != src.EqualsSign || this.QuotedValue != src.QuotedValue || this.Value != src.Value) { OnChanging(); this.Name = src.Name; this.EqualsSign = src.EqualsSign; this.QuotedValue = src.QuotedValue; this.Value = src.Value; OnChanged(); return true; } else { return false; } }
// Only these four methods should be used to modify the collection /// <summary> To be used exlucively by the parser </summary> internal void AddChild(AXmlObject item) { // Childs can be only added to newly parsed items Assert(this.Parent == null, "I have to be new"); Assert(item.IsCached, "Added item must be in cache"); // Do not set parent pointer this.Children.InsertItemAt(this.Children.Count, item); }
/// <inheritdoc/> internal override bool UpdateDataFrom(AXmlObject source) { if (!base.UpdateDataFrom(source)) return false; AXmlTag src = (AXmlTag)source; if (this.OpeningBracket != src.OpeningBracket || this.Name != src.Name || this.ClosingBracket != src.ClosingBracket) { OnChanging(); this.OpeningBracket = src.OpeningBracket; this.Name = src.Name; this.ClosingBracket = src.ClosingBracket; OnChanged(); return true; } else { return false; } }
internal void OnObjectRemoved(int index, AXmlObject obj) { if (ObjectRemoved != null) ObjectRemoved(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new AXmlObject[] { obj }.ToList(), index)); }
internal void OnObjectChanging(AXmlObject obj) { if (ObjectChanging != null) ObjectChanging(this, new AXmlObjectEventArgs() { Object = obj } ); }
/// <summary> Copy all data from the 'source' to this object </summary> /// <remarks> Returns true if any updates were done </remarks> internal virtual bool UpdateDataFrom(AXmlObject source) { Assert(this.GetType() == source.GetType(), "Source has different type"); DebugAssert(this.StartOffset == source.StartOffset, "Source has different StartOffset"); if (this.LastUpdatedFrom == source) { DebugAssert(this.EndOffset == source.EndOffset, "Source has different EndOffset"); return false; } Assert(!this.IsCached, "Can not update cached item"); Assert(source.IsCached, "Must update from cache"); this.LastUpdatedFrom = source; this.StartOffset = source.StartOffset; // In some cases we are just updating objects of that same // type and position and hoping to be luckily right this.EndOffset = source.EndOffset; // Do not bother comparing - assume changed if non-null if (this.syntaxErrors != null || source.syntaxErrors != null) { // May be called again in derived class - oh, well, does not matter OnChanging(); this.Document.Parser.TrackedSegments.RemoveSyntaxErrorsOf(this); if (source.syntaxErrors == null) { this.syntaxErrors = null; } else { this.syntaxErrors = new List<SyntaxError>(); foreach(var error in source.MySyntaxErrors) { // The object differs, so create our own copy // The source still might need it in the future and we do not want to break it this.AddSyntaxError(error.Clone(this)); } } this.Document.Parser.TrackedSegments.AddSyntaxErrorsOf(this); OnChanged(); } return true; }
/// <summary> Is call to UpdateDataFrom is allowed? </summary> internal bool CanUpdateDataFrom(AXmlObject source) { return this.GetType() == source.GetType() && this.StartOffset == source.StartOffset && (this.LastUpdatedFrom == source || !this.IsCached); }