github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/search/explanation.go (about) 1 package search 2 3 import ( 4 "bytes" 5 "fmt" 6 ) 7 8 // search/Explanation.java 9 10 type Explanation interface { 11 // Indicate whether or not this Explanation models a good match. 12 // By default, an Explanation represents a "match" if the value is positive. 13 IsMatch() bool 14 // The value assigned to this explanation node. 15 Value() float32 16 } 17 18 type ExplanationSPI interface { 19 Explanation 20 // A short one line summary which should contian all high level information 21 // about this Explanation, without the Details. 22 Summary() string 23 Details() []Explanation 24 } 25 26 /* Expert: Describes the score computation for document and query. */ 27 type ExplanationImpl struct { 28 spi ExplanationSPI 29 value float32 // the value of this node 30 description string // what it represents 31 details []Explanation // sub-explanations 32 } 33 34 func newExplanation(value float32, description string) *ExplanationImpl { 35 ans := &ExplanationImpl{value: value, description: description} 36 ans.spi = ans 37 return ans 38 } 39 40 func (exp *ExplanationImpl) IsMatch() bool { return exp.value > 0.0 } 41 func (exp *ExplanationImpl) Value() float32 { return exp.value } 42 func (exp *ExplanationImpl) Description() string { return exp.description } 43 44 func (exp *ExplanationImpl) Summary() string { 45 return fmt.Sprintf("%v = %v", exp.value, exp.description) 46 } 47 48 // The sub-nodes of this explanation node. 49 func (exp *ExplanationImpl) Details() []Explanation { 50 return exp.details 51 } 52 53 // Adds a sub-node to this explanation node 54 func (exp *ExplanationImpl) addDetail(detail Explanation) { 55 exp.details = append(exp.details, detail) 56 } 57 58 // Render an explanation as text. 59 func (exp *ExplanationImpl) String() string { 60 return explanationToString(exp.spi, 0) 61 } 62 63 func explanationToString(exp ExplanationSPI, depth int) string { 64 assert(depth <= 1000) // potential dead loop 65 var buf bytes.Buffer 66 for i := 0; i < depth; i++ { 67 buf.WriteString(" ") 68 } 69 buf.WriteString(exp.Summary()) 70 buf.WriteString("\n") 71 72 for _, v := range exp.Details() { 73 buf.WriteString(explanationToString(v.(ExplanationSPI), depth+1)) 74 } 75 76 return buf.String() 77 } 78 79 // search/ComplexExplanation.java 80 81 /* 82 Expert: Describes the score computation for the doucment and query, 83 and can distinguish a match independent of a postive value. 84 */ 85 type ComplexExplanation struct { 86 *ExplanationImpl 87 match interface{} 88 } 89 90 func newEmptyComplexExplanation() *ComplexExplanation { 91 ans := new(ComplexExplanation) 92 ans.ExplanationImpl = new(ExplanationImpl) 93 ans.spi = ans 94 return ans 95 } 96 97 func newComplexExplanation(match bool, value float32, desc string) *ComplexExplanation { 98 ans := new(ComplexExplanation) 99 ans.ExplanationImpl = newExplanation(value, desc) 100 ans.spi = ans 101 ans.match = match 102 return ans 103 } 104 105 /* 106 Indicates whether or not this Explanation models a good match. 107 108 If the match status is explicitly set (i.e.: not nil) this method 109 uses it; otherwise it defers to the superclass. 110 */ 111 func (e *ComplexExplanation) IsMatch() bool { 112 return e.match != nil && e.match.(bool) || e.match == nil && e.ExplanationImpl.IsMatch() 113 } 114 115 func (e *ComplexExplanation) Summary() string { 116 if e.match == nil { 117 return e.ExplanationImpl.Summary() 118 } 119 return fmt.Sprintf("%v = %v %v", e.Value(), 120 map[bool]string{true: "(MATCH)", false: "(NON_MATCH)"}[e.IsMatch()], 121 e.Description()) 122 }