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  }