/*
 * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
 *     Yves Roos (yroos@lifl.fr) and others.
 *
 * 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 rationals.transformations;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import rationals.Automaton;
import rationals.Builder;
import rationals.NoSuchStateException;
import rationals.State;
import rationals.Transition;

/**
 * Compute the automaton accessible from a given state
 * @author bailly
 * @version $Id: Accessible.java 2 2006-08-24 14:41:48Z oqube $
 */
public class Accessible<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {

	private State state;

	/**
	 * The state we must start exploration from
	 * 
	 */
	public Accessible(State s) {
		this.state = s;
	}

	/* (non-Javadoc)
	 * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
	 */
	public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
		Set<Transition<L>> trs = a.delta();
		Automaton<L, Tr, T> b = new Automaton<>();
		Map<State, State> stmap = new HashMap<>();
		/* initial state = state */
		State ns = b.addState(true, state.isTerminal());
		stmap.put(state, ns);
		explore(state, stmap, a, b);
		/* explore a and remove transitions from trs */
		Iterator<Transition<L>> it = trs.iterator();
		while(it.hasNext()) {
			Transition<L> tr = it.next();
			State nstart = stmap.get(tr.start());
			State nend = stmap.get(tr.end());
			if(nstart != null && nend != null)
				try {
					b.addTransition(new Transition<>(nstart,tr.label(),nend));
				} catch (NoSuchStateException e) {
					System.err.println(e.getMessage());
					return null;
				}
		}
		return b;
	}

	/**
	 * Recursive function to explore transitions from a state
	 * @param state
	 * @param stmap
	 * @param b
	 */
	private void explore(State curstate, Map<State, State> stmap, Automaton<L, Tr, T> a, Automaton<L, Tr, T> b) {
		Iterator<Transition<L>> it = a.delta(curstate).iterator();
		while(it.hasNext()) {
			Transition<L> tr = it.next();
			State e = tr.end();
			State ne = stmap.get(e);
			if(ne != null)
				continue;
			else {
				ne = b.addState(e.isInitial(),e.isTerminal());
				stmap.put(e,ne);
				explore(e,stmap,a,b);
			}
		}
	}

}

/*
 * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
 *     Yves Roos (yroos@lifl.fr) and others.
 *
 * 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 rationals.transformations;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import rationals.Automaton;
import rationals.Builder;
import rationals.NoSuchStateException;
import rationals.State;
import rationals.Transition;

/**
 * Compute the automaton accessible from a given state
 * @author bailly
 * @version $Id: Accessible.java 2 2006-08-24 14:41:48Z oqube $
 */
public class Accessible<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {

	private State state;

	/**
	 * The state we must start exploration from
	 * 
	 */
	public Accessible(State s) {
		this.state = s;
	}

	/* (non-Javadoc)
	 * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
	 */
	public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
		Set<Transition<L>> trs = a.delta();
		Automaton<L, Tr, T> b = new Automaton<>();
		Map<State, State> stmap = new HashMap<>();
		/* initial state = state */
		State ns = b.addState(true, state.isTerminal());
		stmap.put(state, ns);
		explore(state, stmap, a, b);
		/* explore a and remove transitions from trs */
		Iterator<Transition<L>> it = trs.iterator();
		while(it.hasNext()) {
			Transition<L> tr = it.next();
			State nstart = stmap.get(tr.start());
			State nend = stmap.get(tr.end());
			if(nstart != null && nend != null)
				try {
					b.addTransition(new Transition<>(nstart,tr.label(),nend));
				} catch (NoSuchStateException e) {
					throw new Error(e);
				}
		}
		return b;
	}

	/**
	 * Recursive function to explore transitions from a state
	 * @param state
	 * @param stmap
	 * @param b
	 */
	private void explore(State curstate, Map<State, State> stmap, Automaton<L, Tr, T> a, Automaton<L, Tr, T> b) {
		Iterator<Transition<L>> it = a.delta(curstate).iterator();
		while(it.hasNext()) {
			Transition<L> tr = it.next();
			State e = tr.end();
			State ne = stmap.get(e);
			if(ne != null)
				continue;
			else {
				ne = b.addState(e.isInitial(),e.isTerminal());
				stmap.put(e,ne);
				explore(e,stmap,a,b);
			}
		}
	}

}

Throw Error in case of error.