Lucene.Net  3.0.3
Lucene.Net is a .NET port of the Java Lucene Indexing Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties
TeeSinkTokenFilter.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using System.Collections.Generic;
20 using Attribute = Lucene.Net.Util.Attribute;
21 using AttributeSource = Lucene.Net.Util.AttributeSource;
22 
23 namespace Lucene.Net.Analysis
24 {
25 
68  public sealed class TeeSinkTokenFilter:TokenFilter
69  {
71  {
72  public override bool Accept(AttributeSource source)
73  {
74  return true;
75  }
76  }
77  private readonly LinkedList<WeakReference> sinks = new LinkedList<WeakReference>();
78 
80  public TeeSinkTokenFilter(TokenStream input):base(input)
81  {
82  }
83 
85  public SinkTokenStream NewSinkTokenStream()
86  {
87  return NewSinkTokenStream(ACCEPT_ALL_FILTER);
88  }
89 
95  public SinkTokenStream NewSinkTokenStream(SinkFilter filter)
96  {
97  var sink = new SinkTokenStream(this.CloneAttributes(), filter);
98  sinks.AddLast(new WeakReference(sink));
99  return sink;
100  }
101 
106  public void AddSinkTokenStream(SinkTokenStream sink)
107  {
108  // check that sink has correct factory
109  if (!this.Factory.Equals(sink.Factory))
110  {
111  throw new System.ArgumentException("The supplied sink is not compatible to this tee");
112  }
113  // add eventually missing attribute impls to the existing sink
114  foreach (var impl in this.CloneAttributes().GetAttributeImplsIterator())
115  {
116  sink.AddAttributeImpl(impl);
117  }
118  sinks.AddLast(new WeakReference(sink));
119  }
120 
126  public void ConsumeAllTokens()
127  {
128  while (IncrementToken())
129  {
130  }
131  }
132 
133  public override bool IncrementToken()
134  {
135  if (input.IncrementToken())
136  {
137  // capture state lazily - maybe no SinkFilter accepts this state
138  State state = null;
139  foreach(WeakReference wr in sinks)
140  {
141  var sink = (SinkTokenStream)wr.Target;
142  if (sink != null)
143  {
144  if (sink.Accept(this))
145  {
146  if (state == null)
147  {
148  state = this.CaptureState();
149  }
150  sink.AddState(state);
151  }
152  }
153  }
154  return true;
155  }
156 
157  return false;
158  }
159 
160  public override void End()
161  {
162  base.End();
163  State finalState = CaptureState();
164  foreach(WeakReference wr in sinks)
165  {
166  var sink = (SinkTokenStream)wr.Target;
167  if (sink != null)
168  {
169  sink.SetFinalState(finalState);
170  }
171  }
172  }
173 
175  public abstract class SinkFilter
176  {
180  public abstract bool Accept(AttributeSource source);
181 
185  public virtual void Reset()
186  {
187  // nothing to do; can be overridden
188  }
189  }
190 
191  public sealed class SinkTokenStream : TokenStream
192  {
193  private readonly LinkedList<State> cachedStates = new LinkedList<State>();
194  private State finalState;
195  private IEnumerator<AttributeSource.State> it = null;
196  private readonly SinkFilter filter;
197 
198  internal SinkTokenStream(AttributeSource source, SinkFilter filter)
199  : base(source)
200  {
201  this.filter = filter;
202  }
203 
204  internal /*private*/ bool Accept(AttributeSource source)
205  {
206  return filter.Accept(source);
207  }
208 
209  internal /*private*/ void AddState(AttributeSource.State state)
210  {
211  if (it != null)
212  {
213  throw new System.SystemException("The tee must be consumed before sinks are consumed.");
214  }
215  cachedStates.AddLast(state);
216  }
217 
218  internal /*private*/ void SetFinalState(AttributeSource.State finalState)
219  {
220  this.finalState = finalState;
221  }
222 
223  public override bool IncrementToken()
224  {
225  // lazy init the iterator
226  if (it == null)
227  {
228  it = cachedStates.GetEnumerator();
229  }
230 
231  if (!it.MoveNext())
232  {
233  return false;
234  }
235 
236  State state = it.Current;
237  RestoreState(state);
238  return true;
239  }
240 
241  public override void End()
242  {
243  if (finalState != null)
244  {
245  RestoreState(finalState);
246  }
247  }
248 
249  public override void Reset()
250  {
251  it = cachedStates.GetEnumerator();
252  }
253 
254  protected override void Dispose(bool disposing)
255  {
256  // Do nothing.
257  }
258  }
259 
260  private static readonly SinkFilter ACCEPT_ALL_FILTER;
261  static TeeSinkTokenFilter()
262  {
263  ACCEPT_ALL_FILTER = new AnonymousClassSinkFilter();
264  }
265  }
266 }