1 // 2 // Copyright (c) 2013-2017 Carsten Sonne Larsen <cs@innolan.net> 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 using System; 23 using System.Collections.Generic; 24 using System.Linq; 25 using Ntp.Analyzer.Config.Node.Navigation; 26 using Ntp.Analyzer.Config.Syntax.Option; 27 using Ntp.Analyzer.Config.Syntax.Setting; 28 using Ntp.Analyzer.Config.Table; 29 30 namespace Ntp.Analyzer.Config.Syntax 31 { 32 public class MenuItemSyntaxNode : SyntaxNode<MenuItemConfiguration> 33 { MenuItemSyntaxNode(string name, int line)34 public MenuItemSyntaxNode(string name, int line) 35 : base(Symbol.KeywordItem, name, line) 36 { 37 type = MenuItemType.Unknown; 38 } 39 40 private ISyntaxNode linkable; 41 42 private Uri location; 43 private MenuItemType type; 44 InternalCompile()45 protected override MenuItemConfiguration InternalCompile() 46 { 47 var caption = Nodes.SingleOrDefault(n => n.Symbol == Symbol.KeywordCaption) as StringSettingNode; 48 var dropdown = Nodes.SingleOrDefault(n => n.Symbol == Symbol.KeywordDropdown) as StringSettingNode; 49 var submenu = Nodes.SingleOrDefault(n => n.Symbol == Symbol.KeywordMenu) as MenuSyntaxNode; 50 51 // NOTICE: Consider another method to archive the same result 52 ILinkable compiledLinkable = null; 53 if (linkable != null) 54 { 55 linkable.CompileNode(); 56 compiledLinkable = linkable.CompiledNode as ILinkable; 57 } 58 59 switch (type) 60 { 61 case MenuItemType.Spacer: 62 return new SpacerMenuItemConfiguration(Name); 63 case MenuItemType.Header: 64 return new HeaderMenuItemConfiguration(Name, caption?.Value); 65 case MenuItemType.Name: 66 return new HeadMenuItemConfiguration(Name, caption?.Value, location); 67 case MenuItemType.Link: 68 return new LinkMenuItemConfiguration(Name, caption?.Value, location); 69 case MenuItemType.Page: 70 return new PageMenuItemConfiguration(Name, caption?.Value, compiledLinkable); 71 case MenuItemType.Dropdown: 72 return new DropdownItemConfiguration(Name, dropdown?.Value, submenu?.Compile()); 73 case MenuItemType.Unknown: 74 return null; 75 default: 76 return null; 77 } 78 } 79 InternalResolve(SymbolTable table)80 protected override void InternalResolve(SymbolTable table) 81 { 82 if (type == MenuItemType.Unknown) 83 { 84 var typeNode = Nodes.SingleOrDefault(n => n.Symbol == Symbol.KeywordType) as MenuItemTypeNode; 85 if (typeNode != null) 86 type = typeNode.ItemType; 87 } 88 89 if (type == MenuItemType.Page) 90 { 91 var pageName = Nodes.SingleOrDefault(n => n.Symbol == Symbol.KeywordPage) as StringSettingNode; 92 if (pageName == null) 93 return; 94 95 linkable = table.Lookup(pageName.Value); 96 } 97 } 98 ValidateMandatories()99 protected override void ValidateMandatories() 100 { 101 CheckIsUnique(new List<Symbol> 102 { 103 Symbol.KeywordPage, 104 Symbol.KeywordCaption, 105 Symbol.KeywordLink, 106 Symbol.KeywordDropdown, 107 Symbol.KeywordType, 108 Symbol.KeywordContent 109 }); 110 111 if (Nodes.Count(n => n.Symbol == Symbol.KeywordDropdown) > 0) 112 { 113 type = MenuItemType.Dropdown; 114 } 115 else if (Nodes.Count(n => n.Symbol == Symbol.KeywordPage) > 0) 116 { 117 type = MenuItemType.Page; 118 } 119 else if (Nodes.Count(n => n.Symbol == Symbol.KeywordLink) > 0) 120 { 121 type = MenuItemType.Link; 122 } 123 else 124 { 125 CheckAllIsPresent(new List<Symbol> {Symbol.KeywordType}); 126 } 127 } 128 ValidateReferences(SymbolTable table)129 protected override void ValidateReferences(SymbolTable table) 130 { 131 var pageName = Nodes.SingleOrDefault(n => n.Symbol == Symbol.KeywordPage) as StringSettingNode; 132 if (pageName != null) 133 { 134 string keyword = Keyword.Find(Symbol.KeywordItem).Name; 135 var reference = table.Lookup(pageName.Value); 136 if (reference == null) 137 { 138 AddReferenceNameError(pageName, keyword, pageName.Value); 139 } 140 } 141 142 var link = Nodes.SingleOrDefault(n => n.Symbol == Symbol.KeywordLink) as StringSettingNode; 143 if (link == null) 144 return; 145 146 var linkKeyword = Keyword.Find(Symbol.KeywordLink).Name; 147 location = CheckLink(link.Value, linkKeyword); 148 } 149 ValidateTypes()150 protected override void ValidateTypes() 151 { 152 CheckTypeIs<StringSettingNode>(Symbol.KeywordPage); 153 CheckTypeIs<StringSettingNode>(Symbol.KeywordCaption); 154 CheckTypeIs<StringSettingNode>(Symbol.KeywordLink); 155 CheckTypeIs<StringSettingNode>(Symbol.KeywordDropdown); 156 CheckTypeIs<MenuItemTypeNode>(Symbol.KeywordType); 157 } 158 } 159 }