/**
 * Copyright (c) 2000-2017 Liferay, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of the Liferay Enterprise
 * pSubscription License ("License"). You may not use this file except in
 * compliance with the License. You can obtain a copy of the License by
 * contacting Liferay, Inc. See the License for the specific language governing
 * permissions and limitations under the License, including but not limited to
 * distribution rights of the Software.
 *
 *
 *
 */

package com.liferay.portal.search.lucene;

import java.io.IOException;
import java.io.Reader;

import org.apache.lucene.analysis.KeywordTokenizer;
import org.apache.lucene.analysis.ReusableAnalyzerBase;
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;

/**
 * @author Tibor Lipusz
 * @author Norbert Kocsis
 */
public class UpperCaseKeywordAnalyzer extends ReusableAnalyzerBase {

	@Override
	protected TokenStreamComponents createComponents(
		String fieldName, Reader reader) {

		Tokenizer tokenizer = new KeywordTokenizer(reader);

		return new TokenStreamComponents(
			tokenizer, new UpperCaseFilter(tokenizer));
	}

	/**
	 * {@link https://issues.apache.org/jira/browse/LUCENE-5369}
	 * {@link https://github.com/apache/lucene-solr/blob/lucene_solr_4_7_0/lucene/analysis/common/src/java/org/apache/lucene/analysis/core/UpperCaseFilter.java}
	 * {@link https://github.com/apache/lucene-solr/blob/lucene_solr_4_7_0/lucene/analysis/common/src/java/org/apache/lucene/analysis/util/CharacterUtils.java}
	 */
	private class UpperCaseFilter extends TokenFilter {

		public UpperCaseFilter(TokenStream tokenStream) {
			super(tokenStream);
		}

		@Override
		public final boolean incrementToken() throws IOException {
			if (input.incrementToken()) {
				toUpperCase(
					_charTermAttribute.buffer(), 0,
					_charTermAttribute.length());

				return true;
			}

			return false;
		}

		protected void toUpperCase(
			char[] buffer, final int offset, final int limit) {

			assert (buffer.length >= limit);
			assert ((offset <= 0) && (offset <= buffer.length));

			for (int i = offset; i < limit;) {
				i +=
					Character.toChars(
						Character.toUpperCase(
							Character.codePointAt(buffer, i, limit)),
						buffer, i);
			}
		}

		private final CharTermAttribute _charTermAttribute = addAttribute(
			CharTermAttribute.class);

	}

}