All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wicketstuff.datatable_autocomplete.provider.TrieDataProvider Maven / Gradle / Ivy

Go to download

The Datatable autocomplete project provides a Trie datastructure that allows AJAX searches on large datasets fast. It is not memory efficient but it is fast especially to know how many results a given prefix matches. Provides a Datatable component when tied to a textfield will show the matched objects in a table format.

There is a newer version: 1.5.13
Show newest version
/*
 * 
 * ==============================================================================
 * Licensed 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.wicketstuff.datatable_autocomplete.provider;

import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.model.IModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wicketstuff.datatable_autocomplete.provider.utils.DataProviderUtils;
import org.wicketstuff.datatable_autocomplete.trie.ITrieFilter;
import org.wicketstuff.datatable_autocomplete.trie.Trie;

/**
 * @author mocleiri
 * 
 *         A SortableDataProvider connector which loads the data from the backing Trie.
 * 
 */
public class TrieDataProvider extends SortableDataProvider
{

	private static final Logger log = LoggerFactory.getLogger(TrieDataProvider.class);

	private static final long serialVersionUID = 6404076914195910834L;

	// prevents the underlying Trie from being serialized with the provider.
	// it is a big performance problem if the Trie is serialized (especially in
	// AJAX cases).
	protected final ITrieProvider trieProvider;

	private List currentListData = null;

	private final IModel fieldStringModel;

	private final IProviderSorter sorter;

	private ITrieFilter trieResultFilter;

	// default to show no results for an empty string
	private boolean noResultsOnEmptyString = true;

	private boolean matchAnyWhereInString = false;

	private final IModelProvider modelProvider;

	private Map resultLimitMap = new LinkedHashMap();

	protected IModel getInputModel()
	{

		return fieldStringModel;
	}

	/**
	 * @param noResultsOnEmptyString
	 *            the noResultsOnEmptyString to set
	 */
	public void setNoResultsOnEmptyString(boolean noResultsOnEmptyString)
	{

		this.noResultsOnEmptyString = noResultsOnEmptyString;
	}

	/**
	 * @param matchAnyWhereInString
	 *            the matchAnyWhereInString to set
	 */
	public void setMatchAnyWhereInString(boolean matchAnyWhereInString)
	{

		this.matchAnyWhereInString = matchAnyWhereInString;
	}

	/**
	 * @return the matchAnyWhereInString
	 */
	public boolean isMatchAnyWhereInString()
	{
		return matchAnyWhereInString;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider #detach()
	 */
	@Override
	public void detach()
	{

		/*
		 * If we want to support selectable values then we need to make the list last longer than
		 * just one rendered pass.
		 */
		clear();
		super.detach();
	}

	public final void clear()
	{

		if (currentListData != null)
		{
			currentListData.clear();
			currentListData = null;
		}
	}

	/**
	 * @param fieldStringModel
	 * 
	 */
	public TrieDataProvider(ITrieProvider trieProvider, ITrieFilter resultFilter,
		IModel fieldStringModel, IProviderSorter sorter, IModelProvider modelProvider)
	{

		super();
		this.trieProvider = trieProvider;
		trieResultFilter = resultFilter;

		this.fieldStringModel = fieldStringModel;
		this.sorter = sorter;
		this.modelProvider = modelProvider;
	}

	public int size()
	{

		String prefix = fieldStringModel.getObject();

		if (prefix == null)
		{
			return 0;
		}
		else if (noResultsOnEmptyString && prefix.length() == 0)
		{
			// show no results since no input filter specified.
			return 0;
		}
		else
		{
			// if no input is given any element in the entire trie is
			// selectable.
			if (currentListData == null)
			{

				Trie trie = trieProvider.provideTrie();

				if (trie == null)
				{
					log.warn("trie is unexpectantly null!");
					currentListData = new LinkedList();
					return 0;

				}

				// prefix matching

				Integer limit = this.resultLimitMap.get(prefix.length());

				if (limit == null)
				{
					// no limit
					currentListData = trie.getWordList(prefix, this.trieResultFilter);

				}

				else
				{
					currentListData = trie.getWordList(prefix, this.trieResultFilter, limit);

				}

			}

			return currentListData.size();
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.wicket.markup.repeater.data.IDataProvider#iterator(int, int)
	 */
	public Iterator iterator(int first, int count)
	{

		String prefix = fieldStringModel.getObject();

		if (prefix == null || currentListData == null)
			return new LinkedList().iterator();

		SortParam sort = super.getSort();

		if (sort != null && this.currentListData.size() > 1)
		{

			Comparator c = sorter.getComparatorForProperty(sort);

			if (c != null)
				Collections.sort(this.currentListData, c);

		}

		int size = currentListData.size();

		int last = DataProviderUtils.getLastIndex(size, first, count);

		if (first > last)
		{
			log.warn("indexing problem");
			last = DataProviderUtils.getLastIndex(size, first, count);
		}

		return currentListData.subList(first, last).iterator();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.wicket.markup.repeater.data.IDataProvider#model(java.lang. Object)
	 */
	public IModel model(C object)
	{

		return modelProvider.model(object);
	}

	/**
	 * Used to set the upper bounds on results returned based on the length of the prefix being
	 * searched.
	 * 
	 * @param resultMatchMap
	 * 
	 */
	public void setMaxResultMap(Map resultMatchMap)
	{
		this.resultLimitMap = resultMatchMap;

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy