| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.lucene.analysis; |
| |
| import java.io.Reader; |
| |
| |
| /** |
| * An analyzer wrapper, that doesn't allow to wrap components or readers. |
| * By disallowing it, it means that the thread local resources can be delegated |
| * to the delegate analyzer, and not also be allocated on this analyzer. |
| * This wrapper class is the base class of all analyzers that just delegate to |
| * another analyzer, e.g. per field name. |
| * |
| * <p>This solves the problem of per field analyzer wrapper, where it also |
| * maintains a thread local per field token stream components, while it can |
| * safely delegate those and not also hold these data structures, which can |
| * become expensive memory wise. |
| * |
| * <p><b>Please note:</b> This analyzer uses a private {@link Analyzer.ReuseStrategy}, |
| * which is returned by {@link #getReuseStrategy()}. This strategy is used when |
| * delegating. If you wrap this analyzer again and reuse this strategy, no |
| * delegation is done and the given fallback is used. |
| * |
| * @since 4.10.0 |
| */ |
| public abstract class DelegatingAnalyzerWrapper extends AnalyzerWrapper { |
| |
| /** |
| * Constructor. |
| * @param fallbackStrategy is the strategy to use if delegation is not possible |
| * This is to support the common pattern: |
| * {@code new OtherWrapper(thisWrapper.getReuseStrategy())} |
| */ |
| protected DelegatingAnalyzerWrapper(ReuseStrategy fallbackStrategy) { |
| super(new DelegatingReuseStrategy(fallbackStrategy)); |
| // häckidy-hick-hack, because we cannot call super() with a reference to "this": |
| ((DelegatingReuseStrategy) getReuseStrategy()).wrapper = this; |
| } |
| |
| @Override |
| protected final TokenStreamComponents wrapComponents(String fieldName, TokenStreamComponents components) { |
| return super.wrapComponents(fieldName, components); |
| } |
| |
| @Override |
| protected final TokenStream wrapTokenStreamForNormalization(String fieldName, TokenStream in) { |
| return super.wrapTokenStreamForNormalization(fieldName, in); |
| } |
| |
| @Override |
| protected final Reader wrapReader(String fieldName, Reader reader) { |
| return super.wrapReader(fieldName, reader); |
| } |
| |
| @Override |
| protected final Reader wrapReaderForNormalization(String fieldName, Reader reader) { |
| return super.wrapReaderForNormalization(fieldName, reader); |
| } |
| |
| private static final class DelegatingReuseStrategy extends ReuseStrategy { |
| DelegatingAnalyzerWrapper wrapper; |
| private final ReuseStrategy fallbackStrategy; |
| |
| DelegatingReuseStrategy(ReuseStrategy fallbackStrategy) { |
| this.fallbackStrategy = fallbackStrategy; |
| } |
| |
| @Override |
| public TokenStreamComponents getReusableComponents(Analyzer analyzer, String fieldName) { |
| if (analyzer == wrapper) { |
| final Analyzer wrappedAnalyzer = wrapper.getWrappedAnalyzer(fieldName); |
| return wrappedAnalyzer.getReuseStrategy().getReusableComponents(wrappedAnalyzer, fieldName); |
| } else { |
| return fallbackStrategy.getReusableComponents(analyzer, fieldName); |
| } |
| } |
| |
| @Override |
| public void setReusableComponents(Analyzer analyzer, String fieldName, TokenStreamComponents components) { |
| if (analyzer == wrapper) { |
| final Analyzer wrappedAnalyzer = wrapper.getWrappedAnalyzer(fieldName); |
| wrappedAnalyzer.getReuseStrategy().setReusableComponents(wrappedAnalyzer, fieldName, components); |
| } else { |
| fallbackStrategy.setReusableComponents(analyzer, fieldName, components); |
| } |
| } |
| }; |
| |
| } |