GraphSearchAlgorithmBuilder.java

package eu.javaexperience.algorithm.search.graph;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;

import eu.javaexperience.asserts.AssertArgument;
import eu.javaexperience.exceptions.UnimplementedCaseException;
import eu.javaexperience.interfaces.simple.getBy.GetBy1;
import eu.javaexperience.interfaces.simple.publish.SimplePublish1;
import eu.javaexperience.interfaces.simple.publish.SimplePublish2;

public class GraphSearchAlgorithmBuilder<V, E>
{
	public GraphSearchDirection searchDirection = GraphSearchDirection.FORWARD;
	public ArrayList<GetBy1<Boolean, Entry<GraphSearchTraveledPath<V, E>, V>>> extendFilters = new ArrayList<>();
	public Comparator<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>> orderExtends = null;
	public SimplePublish2<List<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>>, Collection<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>>> extendSelector;
	
	
	public GraphSearchAlgorithm<V, E> build()
	{
		final SimplePublish2<List<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>>, Collection<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>>> extendSelector = this.extendSelector;
		AssertArgument.assertNotNull(extendSelector, "ExtendSelector must be given, so ");
		
		final GraphSearchDirection searchDirection = this.searchDirection;
		final ArrayList<GetBy1<Boolean, Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>>> extendFilters = (ArrayList<GetBy1<Boolean, Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>>>) this.extendFilters.clone();
		
		final Comparator<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>> orderExtends = this.orderExtends;
		
		
		return new GraphSearchAlgorithm<V, E>()
		{
			@Override
			public void initSearch(GraphSearcher<V, E> search)
			{
				switch(searchDirection)
				{
					case BACKWARD: 		search.initBackwardSearch();	break;
					case BIDIRECTIONAL:	search.initTwoSideSearch();		break;
					case FORWARD:		search.initForwardSearch();		break;
					default:			throw new UnimplementedCaseException(searchDirection);
				}
			}

			@Override
			public boolean mergeBranches
			(
				GraphSearcher<V, E> search,
				List<Entry<GraphSearchTraveledPath<V, E>, GraphSearchTraveledPath<V, E>>> mergePairs
			)
			{
				if(searchDirection == GraphSearchDirection.BIDIRECTIONAL)
				{
					return GraphSearchAlgorithms.mergeBranches(search, mergePairs);
				}
				
				return false;
			}
			
			@Override
			public void extendSearchFront
			(
				GraphSearcher<V, E> search,
				List<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>> possibleExtends,
				Collection<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>> selectedExtends,
				Collection<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>> closedExtends
			)
			{
				ArrayList<Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>> select = new	ArrayList<>();
				
				kint:for(Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>> p:possibleExtends)
				{
					for(GetBy1<Boolean, Entry<GraphSearchTraveledPath<V, E>, Entry<E, V>>> f:extendFilters)
					{
						Boolean ret = f.getBy(p);
						if(Boolean.FALSE == ret)
						{
							closedExtends.add(p);
							continue kint;
						}
						else if(Boolean.TRUE == ret)
						{
							select.add(p);
							continue kint;
						}
						//if null we skip it (in next iteration it might be selected)
					}
				}
				
				if(null != orderExtends)
				{
					Collections.sort(select, orderExtends);
				}
				
				extendSelector.publish(select, selectedExtends);
			}
		};
	}

	public GraphSearchDirection getSearchDirection()
	{
		return searchDirection;
	}
	
	public void setSearchDirection(GraphSearchDirection searchDirection)
	{
		this.searchDirection = searchDirection;
	}
}