github.com/mattdotmatt/gauge@v0.3.2-0.20160421115137-425a4cdccb62/gauge/concept.go (about) 1 // Copyright 2015 ThoughtWorks, Inc. 2 3 // This file is part of Gauge. 4 5 // Gauge is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 10 // Gauge is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 15 // You should have received a copy of the GNU General Public License 16 // along with Gauge. If not, see <http://www.gnu.org/licenses/>. 17 18 package gauge 19 20 type ConceptDictionary struct { 21 ConceptsMap map[string]*Concept 22 constructionMap map[string][]*Step 23 } 24 25 type Concept struct { 26 ConceptStep *Step 27 FileName string 28 } 29 30 func (cpt *Concept) deepCopy() *Concept { 31 return &Concept{FileName: cpt.FileName, ConceptStep: cpt.ConceptStep.GetCopy()} 32 } 33 34 func NewConceptDictionary() *ConceptDictionary { 35 return &ConceptDictionary{ConceptsMap: make(map[string]*Concept, 0), constructionMap: make(map[string][]*Step, 0)} 36 } 37 38 func (dict *ConceptDictionary) isConcept(step *Step) bool { 39 _, ok := dict.ConceptsMap[step.Value] 40 return ok 41 } 42 43 func (dict *ConceptDictionary) Search(stepValue string) *Concept { 44 if concept, ok := dict.ConceptsMap[stepValue]; ok { 45 return concept 46 } 47 return nil 48 } 49 50 func (dict *ConceptDictionary) ReplaceNestedConceptSteps(conceptStep *Step) { 51 dict.updateStep(conceptStep) 52 for i, stepInsideConcept := range conceptStep.ConceptSteps { 53 if nestedConcept := dict.Search(stepInsideConcept.Value); nestedConcept != nil { 54 //replace step with actual concept 55 conceptStep.ConceptSteps[i].ConceptSteps = nestedConcept.ConceptStep.ConceptSteps 56 conceptStep.ConceptSteps[i].IsConcept = nestedConcept.ConceptStep.IsConcept 57 conceptStep.ConceptSteps[i].Lookup = *nestedConcept.ConceptStep.Lookup.GetCopy() 58 } else { 59 dict.updateStep(stepInsideConcept) 60 } 61 } 62 } 63 64 //mutates the step with concept steps so that anyone who is referencing the step will now refer a concept 65 func (dict *ConceptDictionary) updateStep(step *Step) { 66 dict.constructionMap[step.Value] = append(dict.constructionMap[step.Value], step) 67 if !dict.constructionMap[step.Value][0].IsConcept { 68 dict.constructionMap[step.Value] = append(dict.constructionMap[step.Value], step) 69 for _, allSteps := range dict.constructionMap[step.Value] { 70 allSteps.IsConcept = step.IsConcept 71 allSteps.ConceptSteps = step.ConceptSteps 72 allSteps.Lookup = *step.Lookup.GetCopy() 73 } 74 } 75 } 76 77 func (dict *ConceptDictionary) UpdateLookupForNestedConcepts() { 78 for _, concept := range dict.ConceptsMap { 79 for _, stepInsideConcept := range concept.ConceptStep.ConceptSteps { 80 stepInsideConcept.Parent = concept.ConceptStep 81 if nestedConcept := dict.Search(stepInsideConcept.Value); nestedConcept != nil { 82 for i, arg := range nestedConcept.ConceptStep.Args { 83 stepInsideConcept.Lookup.AddArgValue(arg.Value, &StepArg{ArgType: stepInsideConcept.Args[i].ArgType, Value: stepInsideConcept.Args[i].Value}) 84 } 85 } 86 } 87 } 88 } 89 90 type ByLineNo []*Concept 91 92 func (s ByLineNo) Len() int { 93 return len(s) 94 } 95 96 func (s ByLineNo) Swap(i, j int) { 97 s[i], s[j] = s[j], s[i] 98 } 99 100 func (s ByLineNo) Less(i, j int) bool { 101 return s[i].ConceptStep.LineNo < s[j].ConceptStep.LineNo 102 }