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

io.continual.services.model.impl.common.SimpleTraversal Maven / Gradle / Ivy

There is a newer version: 0.3.23
Show newest version
package io.continual.services.model.impl.common;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Set;
import java.util.TreeSet;

import io.continual.services.model.core.Model;
import io.continual.services.model.core.ModelItemFilter;
import io.continual.services.model.core.ModelPathList;
import io.continual.services.model.core.ModelRelation;
import io.continual.services.model.core.ModelRequestContext;
import io.continual.services.model.core.ModelTraversal;
import io.continual.services.model.core.data.BasicModelObject;
import io.continual.services.model.core.data.ModelObject;
import io.continual.services.model.core.exceptions.ModelRequestException;
import io.continual.services.model.core.exceptions.ModelServiceException;
import io.continual.util.naming.Path;

/**
 * A simple, non-optimized traversal implementation
 */
public class SimpleTraversal implements ModelTraversal
{
	public SimpleTraversal ( Model m )
	{
		fModel = m;
		fStart = null;
		fSteps = new LinkedList<>();
	}

	@Override
	public ModelTraversal startAt ( Path p )
	{
		fStart = Collections.singleton ( p );
		return this;
	}

	@Override
	public ModelTraversal startWith ( Set p )
	{
		fStart = p;
		return this;
	}

	@Override
	public ModelTraversal traverseOutbound ( String relation )
	{
		fSteps.add ( new Step ()
		{
			public void execute ( StepContext sc ) throws ModelRequestException, ModelServiceException
			{
				final TreeSet result = new TreeSet<> ();
				for ( Path p : sc.fCurrentSet )
				{
					for ( ModelRelation mr : fModel.selectRelations ( p )
							.named ( relation )
							.outboundOnly ()
							.getRelations ( sc.fMrc )
						)
					{
						result.add ( mr.getTo () );
					}
				}
				sc.replaceSet ( result );
			}
		} );
		return this;
	}

	@Override
	public ModelTraversal traverseInbound ( String relation )
	{
		fSteps.add ( new Step ()
		{
			public void execute ( StepContext sc ) throws ModelRequestException, ModelServiceException
			{
				final TreeSet result = new TreeSet<> ();
				for ( Path p : sc.fCurrentSet )
				{
					for ( ModelRelation mr : fModel.selectRelations ( p )
						.named ( relation )
						.inboundOnly ()
						.getRelations ( sc.fMrc )
					)
					{
						result.add ( mr.getFrom () );
					}
				}
				sc.replaceSet ( result );
			}
		} );
		return this;
	}

	@Override
	public ModelTraversal labelSet ( String label )
	{
		fSteps.add ( new Step ()
		{
			public void execute ( StepContext sc ) throws ModelRequestException, ModelServiceException
			{
				final TreeSet capture = new TreeSet<> ();
				capture.addAll ( sc.fCurrentSet );
				sc.fCaptures.put ( label, capture );
			}
		} );
		return this;
	}

	@Override
	public ModelTraversal excludeSet ( String label )
	{
		fSteps.add ( new Step ()
		{
			public void execute ( StepContext sc ) throws ModelRequestException, ModelServiceException
			{
				final TreeSet captured = sc.fCaptures.get ( label );
				if ( captured != null )
				{
					final TreeSet newSet = new TreeSet<> ();
					for ( Path p : sc.fCurrentSet )
					{
						if ( !captured.contains ( p ) )
						{
							newSet.add ( p );
						}
					}
					sc.replaceSet ( newSet );
				}
			}
		} );
		return this;
	}

	@Override
	public ModelTraversal filterSet ( ModelItemFilter filter )
	{
		fSteps.add ( new Step ()
		{
			public void execute ( StepContext sc ) throws ModelRequestException, ModelServiceException
			{
				final TreeSet newSet = new TreeSet<> ();
				for ( Path p : sc.fCurrentSet )
				{
					final BasicModelObject mo = fModel.load ( sc.fMrc, p );
					final ModelObject moda = mo.getData ();
					if ( filter.matches ( moda ) )
					{
						newSet.add ( p );
					}
				}
				sc.replaceSet ( newSet );
			}
		} );
		return this;
	}

	@Override
	public ModelPathList execute ( ModelRequestContext context ) throws ModelRequestException, ModelServiceException
	{
		if ( fStart.isEmpty () ) throw new ModelRequestException ( "Traversal has no start node." );

		final StepContext sc = new StepContext ( context );
		sc.fCurrentSet.addAll ( fStart );

		for ( Step s : fSteps )
		{
			s.execute ( sc );
			if ( sc.fCurrentSet.size () == 0 )
			{
				// short circuit this traversal
				break;
			}
		}

		return ModelPathList.wrap ( sc.fCurrentSet );
	}

	private final Model fModel;
	private final LinkedList fSteps;
	private Set fStart;

	private class StepContext
	{
		public StepContext ( ModelRequestContext mrc ) { fMrc = mrc; }
		public void replaceSet ( TreeSet set )
		{
			fCurrentSet = set;
		}
		
		final ModelRequestContext fMrc;
		TreeSet fCurrentSet = new TreeSet<> ();
		HashMap> fCaptures = new HashMap<>();
	};
	
	private interface Step
	{
		public void execute ( StepContext sc ) throws ModelRequestException, ModelServiceException;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy