term_locations.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright (c) 2014 Couchbase, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package highlight
  15. import (
  16. "reflect"
  17. "sort"
  18. "github.com/blevesearch/bleve/search"
  19. )
  20. type TermLocation struct {
  21. Term string
  22. ArrayPositions search.ArrayPositions
  23. Pos int
  24. Start int
  25. End int
  26. }
  27. func (tl *TermLocation) Overlaps(other *TermLocation) bool {
  28. if reflect.DeepEqual(tl.ArrayPositions, other.ArrayPositions) {
  29. if other.Start >= tl.Start && other.Start < tl.End {
  30. return true
  31. } else if tl.Start >= other.Start && tl.Start < other.End {
  32. return true
  33. }
  34. }
  35. return false
  36. }
  37. type TermLocations []*TermLocation
  38. func (t TermLocations) Len() int { return len(t) }
  39. func (t TermLocations) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
  40. func (t TermLocations) Less(i, j int) bool {
  41. shortestArrayPositions := len(t[i].ArrayPositions)
  42. if len(t[j].ArrayPositions) < shortestArrayPositions {
  43. shortestArrayPositions = len(t[j].ArrayPositions)
  44. }
  45. // compare all the common array positions
  46. for api := 0; api < shortestArrayPositions; api++ {
  47. if t[i].ArrayPositions[api] < t[j].ArrayPositions[api] {
  48. return true
  49. }
  50. if t[i].ArrayPositions[api] > t[j].ArrayPositions[api] {
  51. return false
  52. }
  53. }
  54. // all the common array positions are the same
  55. if len(t[i].ArrayPositions) < len(t[j].ArrayPositions) {
  56. return true // j array positions, longer so greater
  57. } else if len(t[i].ArrayPositions) > len(t[j].ArrayPositions) {
  58. return false // j array positions, shorter so less
  59. }
  60. // array positions the same, compare starts
  61. return t[i].Start < t[j].Start
  62. }
  63. func (t TermLocations) MergeOverlapping() {
  64. var lastTl *TermLocation
  65. for i, tl := range t {
  66. if lastTl == nil && tl != nil {
  67. lastTl = tl
  68. } else if lastTl != nil && tl != nil {
  69. if lastTl.Overlaps(tl) {
  70. // ok merge this with previous
  71. lastTl.End = tl.End
  72. t[i] = nil
  73. }
  74. }
  75. }
  76. }
  77. func OrderTermLocations(tlm search.TermLocationMap) TermLocations {
  78. rv := make(TermLocations, 0)
  79. for term, locations := range tlm {
  80. for _, location := range locations {
  81. tl := TermLocation{
  82. Term: term,
  83. ArrayPositions: location.ArrayPositions,
  84. Pos: int(location.Pos),
  85. Start: int(location.Start),
  86. End: int(location.End),
  87. }
  88. rv = append(rv, &tl)
  89. }
  90. }
  91. sort.Sort(rv)
  92. return rv
  93. }