public bool TryGetValue(string key, out string value) { // do not use trygetvalue from dictionary. We need default handling in Get value = Get(key); return(value != null || Attributes.ContainsKey(DomData.TokenID(key, true))); }
/// <summary> /// Sets style setting with no parsing /// </summary> /// <param name="name"></param> /// <param name="value"></param> public void SetRaw(string name, string value) { bool hadStyles = HasStyles; Styles[DomData.TokenID(name, true)] = value; UpdateIndex(hadStyles); }
bool ICollection <KeyValuePair <string, string> > .Remove(KeyValuePair <string, string> item) { //if (ContainsKey(item.Key) // && Attributes[DomData.TokenID(item.Key,true)] == item.Value) //{ // return Remove(item.Key); //} //else //{ // return false; //} int index = InnerKeys.IndexOf(DomData.TokenID(item.Key, true)); if (index < 0) { return(false); } else { if (InnerValues[index] == item.Value) { return(Remove(item.Key)); } else { return(false); } } }
/// <summary> /// Returns all the keys that should be in the index for this item (keys for class, tag, attributes, and id) /// </summary> /// <returns></returns> public IEnumerable <string> IndexKeys() { string path = Path; yield return("" + DomData.indexSeparator + path); yield return(IndexKey("+", nodeNameID, path)); string id = Id; if (!String.IsNullOrEmpty(id)) { yield return(IndexKey("#", DomData.TokenID(id), path)); } if (HasClasses) { foreach (ushort clsId in _Classes) { yield return(IndexKey(".", clsId, path)); } } if (HasAttributes) { foreach (ushort attrId in Attributes.GetAttributeIds()) { yield return(IndexKey("!", attrId, path)); } } }
public bool AddClass(string name) { bool result = false; bool addedFirstClass = false; foreach (string cls in name.SplitClean()) { if (!HasClass(cls)) { if (_Classes == null) { _Classes = new List <ushort>(); } ushort tokenId = DomData.TokenID(cls); addedFirstClass = !HasClasses; _Classes.Add(tokenId); if (!IsDisconnected) { Document.AddToIndex(IndexKey(".", tokenId), this); } result = true; } if (addedFirstClass && !IsDisconnected) { // Must index the attributes for search just on attribute too Document.AddToIndex(Attributes.IndexKey(DomData.ClassAttrId), this); } } return(result); }
protected IEnumerable <KeyValuePair <string, string> > GetAttributes() { foreach (var kvp in Attributes) { yield return(new KeyValuePair <string, string>(DomData.TokenName(kvp.Key), kvp.Value)); } }
protected IEnumerable <KeyValuePair <string, string> > stylesEnumerable() { foreach (var kvp in Styles) { yield return(new KeyValuePair <string, string>(DomData.TokenName(kvp.Key), kvp.Value)); } yield break; }
internal string IndexKey(string prefix, ushort keyTokenId, string path) { #if DEBUG_PATH return(prefix + DomData.TokenName(keyTokenId) + DomData.indexSeparator + path); #else return(prefix + (char)keyTokenId + DomData.indexSeparator + path); #endif }
internal string IndexKey(string prefix, string key, string path) { #if DEBUG_PATH return(prefix + key + DomData.indexSeparator + path); #else return(IndexKey(prefix, DomData.TokenID(key), path)); #endif }
public string IndexKey(ushort attrId) { #if DEBUG_PATH return("!" + DomData.TokenName(attrId) + DomData.indexSeparator + Owner.Path); #else return("!" + (char)attrId + DomData.indexSeparator + Owner.Path); #endif }
protected string Get(string name) { name = name.CleanUp(); if (string.IsNullOrEmpty(name)) { return(null); } return(Get(DomData.TokenID(name, true))); }
/// <summary> /// Adding an attribute implementation /// </summary> /// <param name="name"></param> /// <param name="value"></param> protected void Set(string name, string value) { if (String.IsNullOrEmpty(name)) { throw new ArgumentException("Cannot set an attribute with no name."); } name = name.CleanUp(); Set(DomData.TokenID(name, true), value); }
void ICollection <KeyValuePair <string, string> > .CopyTo(KeyValuePair <string, string>[] array, int arrayIndex) { array = new KeyValuePair <string, string> [Styles.Count]; int index = 0; foreach (var kvp in Styles) { array[index++] = new KeyValuePair <string, string>(DomData.TokenName(kvp.Key), kvp.Value); } }
/// <summary> /// Sets a boolean only attribute having no value /// </summary> /// <param name="name"></param> internal void SetBooleanAttribute(string name) { ushort tokenId = DomData.TokenID(name, true); if (!Attributes.ContainsKey(tokenId)) { AddToIndex(tokenId); } Attributes[tokenId] = null; }
protected IEnumerable <KeyValuePair <string, string> > GetAttributes() { //foreach (var kvp in Attributes) //{ // yield return new KeyValuePair<string, string>(DomData.TokenName(kvp.Key).ToLower(), kvp.Value); //} for (int i = 0; i < InnerKeys.Count; i++) { yield return(new KeyValuePair <string, string>(DomData.TokenName(InnerKeys[i]).ToLower(), InnerValues[i])); } }
bool ICollection <KeyValuePair <string, string> > .Remove(KeyValuePair <string, string> item) { if (ContainsKey(item.Key) && Attributes[DomData.TokenID(item.Key, true)] == item.Value) { return(Remove(item.Key)); } else { return(false); } }
public void TestDomReadWriteResourceCreateWithArticleResourceWithResourceLinkage() { // Arrange var serviceModel = ClrSampleData.ServiceModelWithBlogResourceTypes; var articleResourceType = serviceModel.GetResourceType <Article>(); var articleTitleAttribute = articleResourceType.GetClrAttributeInfo(StaticReflection.GetMemberName <Article>(x => x.Title)); var commentResourceType = serviceModel.GetResourceType <Comment>(); var personResourceType = serviceModel.GetResourceType <Person>(); var expectedArticle = ApiSampleData.ArticleResourceWithResourceLinkage; var expectedAuthor = ApiSampleData.PersonResource; var expectedComment1 = ApiSampleData.CommentResource1; var expectedComment2 = ApiSampleData.CommentResource2; // Act var actual = DomReadWriteResource.Create( DomType.CreateFromResourceType(articleResourceType), DomId.CreateFromApiResourceIdentity(articleResourceType, expectedArticle), DomAttributes.Create( DomAttribute.CreateFromApiResource(articleTitleAttribute, expectedArticle)), DomReadWriteRelationships.Create( DomReadWriteRelationship.Create(ApiSampleData.ArticleToAuthorRel, DomReadWriteLinks.Create( DomReadWriteLink.Create(Keywords.Self, DomHRef.Create(ApiSampleData.ArticleToRelationshipsToAuthorHRef)), DomReadWriteLink.Create(Keywords.Related, DomHRef.Create(ApiSampleData.ArticleToAuthorHRef))), DomData.CreateFromResourceIdentifier( DomReadWriteResourceIdentifier.Create( DomType.CreateFromResourceType(personResourceType), DomId.CreateFromApiResourceIdentity(personResourceType, expectedAuthor)))), DomReadWriteRelationship.Create(ApiSampleData.ArticleToCommentsRel, DomReadWriteLinks.Create( DomReadWriteLink.Create(Keywords.Self, DomHRef.Create(ApiSampleData.ArticleToRelationshipsToCommentsHRef)), DomReadWriteLink.Create(Keywords.Related, DomHRef.Create(ApiSampleData.ArticleToCommentsHRef))), DomDataCollection.CreateFromResourceIdentifiers( DomReadWriteResourceIdentifier.Create( DomType.CreateFromResourceType(commentResourceType), DomId.CreateFromApiResourceIdentity(commentResourceType, expectedComment1)), DomReadWriteResourceIdentifier.Create( DomType.CreateFromResourceType(commentResourceType), DomId.CreateFromApiResourceIdentity(commentResourceType, expectedComment2))))), DomReadWriteLinks.Create( DomReadWriteLink.Create(Keywords.Canonical, DomHRef.Create(ApiSampleData.ArticleHRef)), DomReadWriteLink.Create(Keywords.Self, DomHRef.Create(ApiSampleData.ArticleHRef))), DomReadOnlyMeta.Create(ApiSampleData.ResourceMeta)); this.OutputDomTree(actual); // Assert DomReadWriteResourceAssert.Equal(expectedArticle, actual); }
public override string ToString() { string style = String.Empty; if (HasStyles) { foreach (var kvp in Styles) { style += DomData.TokenName(kvp.Key) + ":" + kvp.Value + ";"; } } return(style); }
protected string Get(string name) { string value; if (Styles.TryGetValue(DomData.TokenID(name, true), out value)) { return(value); } else { return(null); } }
void ICollection <KeyValuePair <string, string> > .CopyTo(KeyValuePair <string, string>[] array, int arrayIndex) { //array = new KeyValuePair<string, string>[Attributes.Count]; //int index = 0; //foreach (var kvp in Attributes) //{ // array[index++] = new KeyValuePair<string, string>(DomData.TokenName(kvp.Key), kvp.Value); //} array = new KeyValuePair <string, string> [InnerKeys.Count]; for (int index = 0; index < InnerKeys.Count; index++) { array[index++] = new KeyValuePair <string, string>(DomData.TokenName(InnerKeys[index]), InnerValues[index]); } }
bool ICollection <KeyValuePair <string, string> > .Contains(KeyValuePair <string, string> item) { //return ContainsKey(item.Key) //&& Attributes[DomData.TokenID(item.Key,true)] == item.Value; int index = InnerKeys.IndexOf(DomData.TokenID(item.Key, true)); if (index < 0) { return(false); } else { return(InnerValues[index] == item.Value); } }
public override bool RemoveAttribute(string name) { if (_Attributes == null) { return(false); } ushort tokenId = DomData.TokenID(name, true); if (tokenId == DomData.ClassAttrId) { _Classes = null; return(true); } else { return(Attributes.Remove(name.ToLower())); } }
public bool RemoveClass(string name) { bool result = false; foreach (string cls in name.SplitClean()) { if (HasClass(cls)) { ushort tokenId = DomData.TokenID(cls); _Classes.Remove(tokenId); if (!IsDisconnected) { Document.RemoveFromIndex(IndexKey(".", tokenId)); if (!HasClasses) { Document.RemoveFromIndex(Attributes.IndexKey(DomData.ClassAttrId)); } } result = true; } } return(result); }
bool ICollection <KeyValuePair <string, string> > .Remove(KeyValuePair <string, string> item) { var kvp = new KeyValuePair <ushort, string>(DomData.TokenID(item.Key), item.Value); return(Styles.Remove(kvp)); }
public override bool TryGetAttribute(string name, out string value) { return(TryGetAttribute(DomData.TokenID(name, true), out value)); }
/// <summary> /// Returns the value of an attribute or a default value if it could not be found. /// </summary> /// <param name="name"></param> /// <returns></returns> public override string GetAttribute(string name, string defaultValue) { return(GetAttribute(DomData.TokenID(name, true), defaultValue)); }
public bool HasClass(string name) { return(HasClasses && _Classes.Contains(DomData.TokenID(name))); }
/// <summary> /// Select from DOM using index. First non-class/tag/id selector will result in this being passed off to GetMatches /// </summary> /// <param name="document"></param> /// <returns></returns> public IEnumerable <IDomObject> Select(IDomDocument document, IEnumerable <IDomObject> context) { if (Selectors == null) { throw new ArgumentException("No selectors provided."); } if (Selectors.Count == 0) { yield break; } Document = document; IEnumerable <IDomObject> lastResult = null; HashSet <IDomObject> output = new HashSet <IDomObject>(); IEnumerable <IDomObject> selectionSource = context; // Disable the index if there is no context (e.g. disconnected elements) bool useIndex = context.IsNullOrEmpty() || !context.First().IsDisconnected; // Copy the list because it may change during the process ActiveSelectors = new List <Selector>(Selectors); for (activeSelectorId = 0; activeSelectorId < ActiveSelectors.Count; activeSelectorId++) { var selector = ActiveSelectors[activeSelectorId]; CombinatorType combinatorType = selector.CombinatorType; SelectorType selectorType = selector.SelectorType; TraversalType traversalType = selector.TraversalType; // Determine what kind of combining method we will use with previous selection results if (activeSelectorId != 0) { switch (combinatorType) { case CombinatorType.Cumulative: // do nothing break; case CombinatorType.Root: selectionSource = context; if (lastResult != null) { output.AddRange(lastResult); lastResult = null; } break; case CombinatorType.Chained: selectionSource = lastResult; lastResult = null; break; // default (chained): leave lastresult alone } } HashSet <IDomObject> tempResult = null; IEnumerable <IDomObject> interimResult = null; string key = ""; if (useIndex && !selector.NoIndex) { #if DEBUG_PATH if (type.HasFlag(SelectorType.Attribute)) { key = "!" + selector.AttributeName; type &= ~SelectorType.Attribute; if (selector.AttributeValue != null) { InsertAttributeValueSelector(selector); } } else if (type.HasFlag(SelectorType.Tag)) { key = "+" + selector.Tag; type &= ~SelectorType.Tag; } else if (type.HasFlag(SelectorType.ID)) { key = "#" + selector.ID; type &= ~SelectorType.ID; } else if (type.HasFlag(SelectorType.Class)) { key = "." + selector.Class; type &= ~SelectorType.Class; } #else if (selectorType.HasFlag(SelectorType.Attribute)) { key = "!" + (char)DomData.TokenID(selector.AttributeName); selectorType &= ~SelectorType.Attribute; if (selector.AttributeValue != null) { InsertAttributeValueSelector(selector); } } else if (selectorType.HasFlag(SelectorType.Tag)) { key = "+" + (char)DomData.TokenID(selector.Tag, true); selectorType &= ~SelectorType.Tag; } else if (selectorType.HasFlag(SelectorType.ID)) { key = "#" + (char)DomData.TokenID(selector.ID); selectorType &= ~SelectorType.ID; } else if (selectorType.HasFlag(SelectorType.Class)) { key = "." + (char)DomData.TokenID(selector.Class); selectorType &= ~SelectorType.Class; } #endif } // If part of the selector was indexed, key will not be empty. Return initial set from the // index. If any selectors remain after this they will be searched the hard way. if (key != String.Empty) { int depth = 0; bool descendants = true; switch (traversalType) { case TraversalType.Child: depth = selector.ChildDepth;; descendants = false; break; case TraversalType.Filter: depth = 0; descendants = false; break; case TraversalType.Descendent: depth = 1; descendants = true; break; } if (selectionSource == null) { interimResult = document.QueryIndex(key + DomData.indexSeparator, depth, descendants); } else { interimResult = new HashSet <IDomObject>(); foreach (IDomObject obj in selectionSource) { ((HashSet <IDomObject>)interimResult) .AddRange(document.QueryIndex(key + DomData.indexSeparator + obj.Path, depth, descendants)); } } } else if (selectorType.HasFlag(SelectorType.Elements)) { selectorType &= ~SelectorType.Elements; HashSet <IDomObject> source = new HashSet <IDomObject>(selectionSource); interimResult = new HashSet <IDomObject>(); foreach (IDomObject obj in selectionSource) { key = DomData.indexSeparator + obj.Path; HashSet <IDomObject> srcKeys = new HashSet <IDomObject>(document.QueryIndex(key)); foreach (IDomObject match in selector.SelectElements) { if (srcKeys.Contains(match)) { ((HashSet <IDomObject>)interimResult).Add(match); } } } } // TODO - GetMatch should work if passed with no selectors (returning nothing), now it returns everything // 12/10/11 - this todo is not verified, much has changed since it was written. TODO confirm this and // fix if needed. If having the conversation with self again, remove comments and forget it. This is // an example of why comments can do more harm than good. if ((selectorType & ~(SelectorType.SubSelectorNot | SelectorType.SubSelectorHas)) != 0) { IEnumerable <IDomObject> finalSelectWithin = interimResult ?? (combinatorType == CombinatorType.Chained ? lastResult : null) ?? selectionSource ?? document.ChildElements; // if there are no temporary results (b/c there was no indexed selector) then use the whole set interimResult = GetMatches(finalSelectWithin, selector); } // Deal with subselectors: has() and not() test for the presence of a selector within the children of // an element. This is essentially similar to the manual selection above. if (selectorType.HasFlag(SelectorType.SubSelectorHas) || selectorType.HasFlag(SelectorType.SubSelectorNot)) { bool isHasSelector = selectorType.HasFlag(SelectorType.SubSelectorHas); IEnumerable <IDomObject> subSelectWithin = interimResult ?? (combinatorType == CombinatorType.Chained ? lastResult : null) ?? selectionSource; // subselects are a filter. start a new interim result. HashSet <IDomObject> filteredResults = new HashSet <IDomObject>(); foreach (IDomObject obj in subSelectWithin) { bool match = true; foreach (var sub in selector.SubSelectors) { List <IDomObject> listOfOne = new List <IDomObject>(); listOfOne.Add(obj); bool has = !sub.Select(document, listOfOne).IsNullOrEmpty(); match &= isHasSelector == has; } if (match) { filteredResults.Add(obj); } } interimResult = filteredResults; } tempResult = new HashSet <IDomObject>(); if (lastResult != null) { tempResult.AddRange(lastResult); } if (interimResult != null) { tempResult.AddRange(interimResult); } lastResult = tempResult; } if (lastResult != null) { output.AddRange(lastResult); } if (output.IsNullOrEmpty()) { yield break; } else { // Selectors always return in DOM order. Selections may end up in a different order but // we always sort here. foreach (IDomObject item in output.OrderBy(item => item.Path, StringComparer.Ordinal)) { yield return(item); } } ActiveSelectors.Clear(); }
bool IDictionary <string, string> .ContainsKey(string key) { return(Styles.ContainsKey(DomData.TokenID(key, true))); }
bool ICollection <KeyValuePair <string, string> > .Contains(KeyValuePair <string, string> item) { return(Styles.Contains(new KeyValuePair <ushort, string>(DomData.TokenID(item.Key), item.Value))); }