github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/util/attributes.go (about) 1 package util 2 3 import ( 4 "reflect" 5 ) 6 7 // util/Attribute.java 8 9 /* Base interface for attributes. */ 10 type Attribute interface { 11 } 12 13 // util/AttributeImpl.java 14 15 /* 16 Base class for Attributes that can be added to a AttributeSource. 17 18 Attributes are used to add data in a dynamic, yet type-safe way to a 19 source of usually streamed ojects, e.g. a TokenStream. 20 */ 21 type AttributeImpl interface { 22 Interfaces() []string 23 Clone() AttributeImpl 24 // Clears the values in this AttributeImpl and resets it to its 25 // default value. If this implementation implements more than one 26 // Attribute interface, it clears all. 27 Clear() 28 CopyTo(target AttributeImpl) 29 } 30 31 // util/AttributeFactory.java 32 33 /* An AttributeFactory creates instances of AttributeImpls. */ 34 type AttributeFactory interface { 35 Create(string) AttributeImpl 36 } 37 38 // util/AttributeSource.java 39 40 /* This class holds the state of an AttributeSource */ 41 type AttributeState struct { 42 attribute AttributeImpl 43 next *AttributeState 44 } 45 46 func (s *AttributeState) Clone() *AttributeState { 47 ans := new(AttributeState) 48 ans.attribute = s.attribute.Clone() 49 if s.next != nil { 50 ans.next = s.next.Clone() 51 } 52 return ans 53 } 54 55 /* 56 An AttributeSource contains a list of different AttributeImpls, and 57 methods to add and get them. There can only be a single instance of 58 an attribute in the same AttributeSource instance. This is ensured by 59 passing in the actual type of the Attribute (reflect.TypeOf(Attribute)) 60 to the #AddAttribute(Type), which then checks if an instance of that 61 type is already present. If yes, it returns the instance, otherwise 62 it creates a new instance and returns it. 63 */ 64 type AttributeSource struct { 65 attributes map[string]AttributeImpl 66 attributeImpls map[reflect.Type]AttributeImpl 67 _currentState []*AttributeState 68 factory AttributeFactory 69 } 70 71 /* An AttributeSource using the default attribute factory */ 72 // func NewAttributeSource() *AttributeSource { 73 // return NewAttributeSourceWith(DEFAULT_ATTRIBUTE_FACTORY) 74 // } 75 76 /* An AttributeSource that uses the same attributes as the supplied one. */ 77 func NewAttributeSourceFrom(input *AttributeSource) *AttributeSource { 78 assert2(input != nil, "input AttributeSource must not be null") 79 return &AttributeSource{ 80 attributes: input.attributes, 81 attributeImpls: input.attributeImpls, 82 _currentState: input._currentState, 83 factory: input.factory, 84 } 85 } 86 87 /* An AttributeSource using the supplied AttributeFactory for creating new Attribute instance. */ 88 func NewAttributeSourceWith(factory AttributeFactory) *AttributeSource { 89 // Note that Lucene Java use LinkedHashMap to keep insert order. 90 // But it's used by Solr only and GoLucene doesn't have plan to 91 // port GoSolr. So we use plain map here. 92 return &AttributeSource{ 93 attributes: make(map[string]AttributeImpl), 94 attributeImpls: make(map[reflect.Type]AttributeImpl), 95 _currentState: make([]*AttributeState, 1), 96 factory: factory, 97 } 98 } 99 100 /* 101 Expert: Adds a custom AttributeImpl instance with one or more 102 Attribute interfaces. 103 104 Please note: it is not guaranteed, that att is added to the 105 AttributeSource, because the provided attributes may already exist. 106 You should always retrieve the wanted attributes using Get() after 107 adding with this method and cast to you class. 108 109 The recommended way to use custom implementations is using an 110 AttributeFactory. 111 */ 112 func (as *AttributeSource) AddImpl(att AttributeImpl) { 113 typ := reflect.TypeOf(att) 114 if _, ok := as.attributeImpls[typ]; ok { 115 return 116 } 117 118 // add all interfaces of this AttributeImpl to the maps 119 for _, curInterface := range att.Interfaces() { 120 // Attribute is a superclass of this interface 121 if _, ok := as.attributes[curInterface]; !ok { 122 // invalidate state to force recomputation in captureState() 123 as._currentState[0] = nil 124 as.attributes[curInterface] = att 125 as.attributeImpls[typ] = att 126 } 127 } 128 } 129 130 /* Returns true, iff this AttributeSource has any attributes */ 131 func (as *AttributeSource) hasAny() bool { 132 return len(as.attributes) > 0 133 } 134 135 /* Returns true, iff this AttributeSource contains the passed-in Attribute. */ 136 func (as *AttributeSource) Has(s string) bool { 137 _, ok := as.attributes[s] 138 return ok 139 } 140 141 /* 142 The caller must pass in a Attribute instance. This method first 143 checks if an instance of that type is already in this AttributeSource 144 and returns it. Otherwise a new instance is created, added to this 145 AttributeSource and returned. 146 */ 147 func (as *AttributeSource) Add(s string) Attribute { 148 attImpl, ok := as.attributes[s] 149 if !ok { 150 attImpl = as.factory.Create(s) 151 as.AddImpl(attImpl) 152 } 153 return attImpl 154 } 155 156 /* Returns the instance of the passe in Attribute contained in this AttributeSource */ 157 func (as *AttributeSource) Get(s string) Attribute { 158 return as.attributes[s] 159 } 160 161 func (as *AttributeSource) currentState() *AttributeState { 162 s := as._currentState[0] 163 if s != nil || !as.hasAny() { 164 return s 165 } 166 s = new(AttributeState) 167 var c *AttributeState 168 for _, v := range as.attributeImpls { 169 if c == nil { 170 c = s 171 c.attribute = v 172 } else { 173 c.next = &AttributeState{attribute: v} 174 c = c.next 175 } 176 } 177 return s 178 } 179 180 func (as *AttributeSource) CaptureState() (state *AttributeState) { 181 if state = as.currentState(); state != nil { 182 state = state.Clone() 183 } 184 return 185 } 186 187 func (as *AttributeSource) RestoreState(state *AttributeState) { 188 if state == nil { 189 return 190 } 191 192 for { 193 targetImpl, ok := as.attributeImpls[reflect.TypeOf(state.attribute)] 194 assert2(ok, 195 "State contains AttributeImpl of type %v that is not in in this AttributeSource", 196 reflect.TypeOf(state.attribute).Name()) 197 state.attribute.CopyTo(targetImpl) 198 state = state.next 199 if state == nil { 200 break 201 } 202 } 203 } 204 205 /* 206 Resets all Attributes in this AttributeSource by calling 207 AttributeImpl.clear() on each Attribute implementation. 208 */ 209 func (as *AttributeSource) Clear() { 210 for state := as.currentState(); state != nil; state = state.next { 211 state.attribute.Clear() 212 } 213 } 214 215 /* 216 Returns a string consisting of the class's simple name, the hex 217 representation of the identity hash code, and the current reflection 218 of all attributes. 219 */ 220 func (as *AttributeSource) String() string { 221 panic("not implemented yet") 222 }