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  }