view src/main/java/jungle/core/graph/simple/SimpleVertexes.java @ 8:abed5bd92fcb

commit
author shoshi <shoshi@cr.ie.u-ryukyu.ac.jp>
date Tue, 03 Jul 2012 18:59:28 +0900
parents 1a5eaf5ce085
children
line wrap: on
line source

package jungle.core.graph.simple;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicReference;

import fj.Equal;
import fj.F;
import fj.P2;
import fj.data.List;
import fj.data.Option;

import jungle.core.graph.Graph;
import jungle.core.graph.Vertex;
import jungle.core.graph.Vertexes;

public class SimpleVertexes implements Vertexes
{
	private final String type;
	private final SimpleVertexContext context;
	private final SimpleGraph parent;
	
	public SimpleVertexes(String _type,SimpleGraph _parent,SimpleVertexContext _context)
	{
		parent = _parent;
		type = _type;
		context = _context;
	}
	
	@Override
	public String toString()
	{
		return context.getRelations().get(type).toString();
	}
	
	
	@Override
	public Vertex remove(final int _index)
	{
		if(_index < 0){
			throw new IndexOutOfBoundsException("_index < 0");
		}
		
		SimpleVertex head = null;
		TreeMap<String,List<SimpleVertex>> current = null,update = null;
		do{
			Option<List<SimpleVertex>> value = context.getRelations().get(type);
			
			if(current.length() < _index + 1){
				throw new IndexOutOfBoundsException("list.length() < _index");
			}
			
			P2<List<SimpleVertex>,List<SimpleVertex>> slice = current.splitAt(_index);
			head = slice._2().head();
			update = slice._1().append(slice._2().drop(1));
		}while(!vertexes.compareAndSet(current,update));
		
		return head;
	}

	@Override
	public int size()
	{
		return vertexes.get().length();
	}
	
	@Override
	public Graph getGraph()
	{
		return parent;
	}

	@Override
	public void add(Vertex _v)
	{
		if(_v.getGraph() != parent){
			throw new IllegalArgumentException("Vertex _v is not belongs to same graph");
		}
		
		if(!(_v instanceof SimpleVertex)){
			throw new IllegalArgumentException("Vertex _v is not instanceof SimpleVertex");
		}
		
		List<SimpleVertex> cur,update;
		do{
			cur = vertexes.get();
			update = cur.append(List.list((SimpleVertex)_v));
		}while(!vertexes.compareAndSet(cur,update));
	}
	
	@Override
	public void add(Vertexes _vs)
	{
		if(!(_vs instanceof SimpleVertexes)){
			throw new IllegalArgumentException("Vertexes _vs is not instanceof SimpleVertex");
		}
		
		List<SimpleVertex> list = ((SimpleVertexes)_vs).vertexes.get();
		
		List<SimpleVertex> cur,update;
		do{
			cur = vertexes.get();
			update = cur.append(list);
		}while(!vertexes.compareAndSet(cur,update));
	}
	
	@Override
	public boolean contains(final Vertex _v)
	{
		if(_v.getGraph() != parent){
			throw new IllegalArgumentException("Vertex _v is not a member of graph");
		}
		
		List<SimpleVertex> list = vertexes.get();
		F<SimpleVertex,Boolean> predicate = new F<SimpleVertex,Boolean>(){
			@Override
			public Boolean f(SimpleVertex _target)
			{
				return _v == _target;
			}
		};
		
		return list.exists(predicate);
	}
	
	@Override
	public Iterator<Vertex> iterator()
	{
		List<SimpleVertex> list = vertexes.get();
		final Iterator<SimpleVertex> itr = list.iterator();
		Iterator<Vertex> wrapper = new Iterator<Vertex>(){

			@Override
			public boolean hasNext()
			{
				return itr.hasNext();
			}

			@Override
			public Vertex next()
			{
				return itr.next();
			}

			@Override
			public void remove()
			{
				throw new UnsupportedOperationException("removing is not supported");
			}
		};
		
		return wrapper;
	}
	
	@Override
	public String type()
	{
		return type;
	}
	
	public static Equal<SimpleVertex> VERTEX_EQUAL = Equal.equal(
		new F<SimpleVertex,F<SimpleVertex,Boolean>>(){
			@Override
			public F<SimpleVertex, Boolean> f(final SimpleVertex _v1){
				return new F<SimpleVertex,Boolean>(){
					@Override
					public Boolean f(SimpleVertex _v2){
						return _v1 == _v2;
					}
				};
			}
		});

	@Override
	public boolean removeFirst(final Vertex _v)
	{
		if(_v == null){
			throw new NullPointerException("_v is null");
		}
		
		if(_v instanceof SimpleVertex){
			SimpleGraph g = (SimpleGraph)_v.getGraph();
			if(g != parent){
				throw new IllegalArgumentException("_v is not a part of graph");
			}
		}else{
			throw new IllegalArgumentException("_v is not instanceof SimpleVertex it was " + _v.getClass().getName());
		}
		
		List<SimpleVertex> list,update;
		do{
			list = vertexes.get();
			update = list.delete((SimpleVertex)_v,VERTEX_EQUAL);
		}while(!vertexes.compareAndSet(list,update));
		
		// list and update 's length are different when removing is succeeded
		return list.length() != update.length();
	}
	
	public Collection<Vertex> toCollection()
	{
		Collection<? extends Vertex> c = vertexes.get().toCollection();
		return Collections.unmodifiableCollection(c);
	}

	@Override
	public boolean removeFirst(Vertexes _vs)
	{
		if(_vs == null){
			throw new NullPointerException("_vs is null");
		}
		
		if(_vs instanceof SimpleVertexes){
			Collection<Vertex> vs = ((SimpleVertexes)_vs).toCollection();
			return removeFirst(vs);
		}
	
		throw new IllegalArgumentException("_vs is not a instanceof SimpleVertexes");
	}
	
	@Override
	public boolean removeFirst(final Collection<Vertex> _vs)
	{
		if(_vs == null){
			throw new NullPointerException("_vs is null");
		}
		
		final HashSet<Vertex> tmp = new HashSet<Vertex>(_vs);
		F<SimpleVertex,Boolean> predicate = new F<SimpleVertex,Boolean>(){
			@Override
			public Boolean f(SimpleVertex _target){
				return tmp.remove(_target);
			}
		};
		
		List<SimpleVertex> list,update;
		do{
			list = vertexes.get();
			update = list.removeAll(predicate);
		}while(!vertexes.compareAndSet(list,update));
		
		return list.length() != update.length();
	}

	@Override
	public Vertex at(int _index)
	{
		List<SimpleVertex> list = vertexes.get();
		
		if(_index < 0){
			throw new IndexOutOfBoundsException("index is muinus.");
		}
		
		if(list.length() < _index + 1){
			throw new IndexOutOfBoundsException("vertex.length() < _index");
		}
		
		return list.take(_index + 1).last();
	}

	@Override
	public void add(Vertex _v, int _index)
	{
		
		if(_v instanceof SimpleVertex){
			throw new IllegalArgumentException("_v is not a SimpleVertex");
		}
		
		
		List<SimpleVertex> list = null,update = null;
		do{
			list = vertexes.get();
			if(list.length() < _index){
				throw new IndexOutOfBoundsException("vertex.length() < _index");
			}
			P2<List<SimpleVertex>,List<SimpleVertex>> slice = list.splitAt(_index);
			
			update = slice._1().snoc((SimpleVertex)_v).append(slice._2());
		}while(!vertexes.compareAndSet(list,update));
	}

	@Override
	public void add(Collection<Vertex> _vs)
	{
		final Iterator<Vertex> itr = _vs.iterator();
		Iterable<SimpleVertex> wrapper = new Iterable<SimpleVertex>(){
			@Override
			public Iterator<SimpleVertex> iterator() {
				return new Iterator<SimpleVertex>(){
					@Override
					public boolean hasNext(){
						return itr.hasNext();
					}
					@Override
					public SimpleVertex next(){
						Vertex v = itr.next();
						if(!(v instanceof SimpleVertex)){
							throw new IllegalArgumentException("_vs is including not a SimpleVertex instance.");
						}
						
						if(v.getGraph() != parent){
							throw new IllegalArgumentException("_vs has vertex from other graph instance");
						}
						return (SimpleVertex)v;
					}
					@Override
					public void remove(){
						throw new UnsupportedOperationException("removeing is not supported.");
					}
				};
			}
		};
		
		List<SimpleVertex> a = List.iterableList(wrapper);
		
		List<SimpleVertex> current = null,update = null;
		do{
			current = vertexes.get();
			update = current.append(a);
		}while(!vertexes.compareAndSet(current,update));
	}

	@Override
	public Vertex replace(Vertex _v, int _index)
	{
		if(_index < 0){
			throw new IndexOutOfBoundsException("_index is muinus");
		}
		
		if(_v == null){
			throw new NullPointerException("_v is null");
		}
		
		if(!(_v instanceof SimpleVertex)){
			throw new IllegalArgumentException("_v is not a instanceof SimpleVertex");
		}
		
		SimpleVertex head = null;
		List<SimpleVertex> current = null,update = null;
		do{
			current = vertexes.get();
			if(current.length() < _index + 1){
				throw new IndexOutOfBoundsException("current.length() < _index");
			}
		
			P2<List<SimpleVertex>,List<SimpleVertex>> slice = current.splitAt(_index);
			head = slice._2().head();
			update = slice._1().snoc((SimpleVertex)_v).append(slice._2().drop(1));
		}while(!vertexes.compareAndSet(current,update));
		
		return head;
	}

	@Override
	public boolean replaceFirst(final Vertex _vertex, Vertex _newVertex)
	{
		if(_vertex == null || _newVertex == null){
			throw new NullPointerException("_vertex or _newVertex is null");
		}
		
		if(!(_vertex instanceof SimpleVertex) || !(_newVertex instanceof SimpleVertex)){
			throw new IllegalArgumentException("_v is not a instanceof SimpleVertex");
		}
		
		F<SimpleVertex,Boolean> predicate = new F<SimpleVertex,Boolean>(){
			@Override
			public Boolean f(SimpleVertex _vertex2){
				return _vertex != _vertex2;
			}
		};
		
		List<SimpleVertex> current = vertexes.get(),update = null;
		do{
			P2<List<SimpleVertex>,List<SimpleVertex>> slice = current.span(predicate);
			if(slice._2().length() == 0){
				// not found.
				return false;
			}
			
			update = slice._1().append(slice._2().drop(1).cons((SimpleVertex)_newVertex));
		}while(!vertexes.compareAndSet(current,update));
		
		return true;
	}

	@Override
	public boolean compareAndSwap(int _index, Vertex _vertex, Vertex _newVertex)
	{
		List<SimpleVertex> current = vertexes.get();
		
		if(_vertex == null || _newVertex == null){
			throw new NullPointerException("_vertex or _newVertex is null");
		}
		
		if(current.length() < _index + 1 || _index < 0){
			throw new IndexOutOfBoundsException("list.length() < _index or _index < 0");
		}
		
		final SimpleVertex v1 = (SimpleVertex)_vertex;
		SimpleVertex v2 = (SimpleVertex)_newVertex;
		
		List<SimpleVertex> update = null;
		do{
			P2<List<SimpleVertex>,List<SimpleVertex>> slice = current.splitAt(_index);
			SimpleVertex head = slice._2().head();
			if(head != v1){
				return false;
			}
			
			update = slice._1().append(slice._2().drop(1).cons(v2));
		}while(!vertexes.compareAndSet(current,update));
		
		return true;
	}
	
	@Override
	public int hashCode()
	{
		return context.
	}
}