// Path: osgi.enroute.trains.api/src/osgi/enroute/trains/cloud/api/Segment.java
// public class Segment extends DTO {
// 
// 	public enum Type {
// 		STRAIGHT, CURVED, SWITCH, SIGNAL, LOCATOR, BLOCK;
// 	}
// 	
// 
// 	/**
// 	 * Our Identity
// 	 */
// 	public String id;
// 	
// 	/**
// 	 * Type of the segment
// 	 */
//  	public Type type;
// 
// 	/**
//  	* Name of the track.This is the name required to get permission 
//  	* from the Track Manager. If this name starts with X then no admission is required. This 
//  	* is generally for switches.
//  	*/
//  	public String track;
//  	
// 	/**
// 	 * Sequence of the segment in the track
// 	 */
// 	public int sequence;
// 
// 	/**
// 	 * Length of the segment in millimeters, can be zero. It an be zero because
// 	 * the relation between the controllers and the switches and the signals is
// 	 * not always 1:1 mappable to controllers. Therefore zero sized segments can
// 	 * be used to map correctly.
// 	 */
// 	public int length;
// 
// 	/**
// 	 * Short code for RFID tag attached to this segment, or 0 for none.
// 	 */
// 	public int tagCode;
// 
// 	/**
// 	 * The associated controller
// 	 */
// 	public int controller = -1;
// 
// 	/**
// 	 * The next segment. Only a switch can have an additional to. The second to
// 	 * is the one selected if the switch is set to its alternative.
// 	 */
// 	public String to[];
// 	
// 	/**
// 	 * The previous segment. Only a switch can have an additional from. The second from
// 	 * is the one selected if the switch is set to its alternative.
// 	 */
// 	public String from[];
// 
// }
// 
// Path: osgi.enroute.trains.util/src/osgi/enroute/trains/track/util/Tracks.java
// public static class SegmentHandler<T> {
// 	public Segment segment;
// 	public SegmentHandler<T> next;
// 	public SegmentHandler<T> prev;
// 
// 	public SegmentHandler(Segment segment) {
// 		this.segment = segment;
// 	}
// 
// 	boolean isPrevAlt(SegmentHandler<T> prev) {
// 		return false;
// 	}
// 
// 	@SuppressWarnings("unchecked")
// 	public T get() {
// 		return (T) this;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return segment.id;
// 	}
// 		
// 	public String getTrack(){
// 		return segment.track;
// 	}
// 
// 	public boolean isMerge() {
// 		return false;
// 	}
// 
// 	public boolean isSwitch() {
// 		return false;
// 	}
// 
// 	public boolean isPlain() {
// 		return true;
// 	}
// 		
// 	public boolean isLocator() {
// 		return false;
// 	}
// 		
// 	public boolean isSignal(){
// 		return false;
// 	}
// 
// 	public LinkedList<SegmentHandler<T>> findForward(SegmentHandler<T> destination) {
// 		LinkedList<SegmentHandler<T>> route = new LinkedList<>();
// 		if (find(route, destination, true))
// 			return new LinkedList<SegmentHandler<T>>(route);
// 		else
// 			return null;
// 	}
// 
// 	public LinkedList<SegmentHandler<T>> findBackward(SegmentHandler<T> destination) {
// 		LinkedList<SegmentHandler<T>> route = new LinkedList<>();
// 		if (find(route, destination, false))
// 			return new LinkedList<SegmentHandler<T>>(route);
// 		else
// 			return null;
// 	}
// 
// 	boolean find(List<SegmentHandler<T>> route, SegmentHandler<T> destination, boolean forward) {
// 		if (route.contains(this)){
// 			return false;
// 		}
// 
// 		route.add(this);
// 
// 		if (this == destination){
// 			return true;
// 		}
// 
// 		Collection<SegmentHandler<T>> choices = move(forward);
// 
// 		if (choices.size() == 1) {
// 			return choices.iterator().next().find(route, destination, forward);
// 		}
// 
// 		int marker = route.size();
// 		for (SegmentHandler<T> choice : choices) {
// 			if (choice.find(route, destination, forward))
// 				return true;
// 					
// 
// 			while(route.size() > marker){
// 				route.remove(marker);
// 			}
// 		}
// 
// 		return false;
// 
// 	}
// 
// 	public Collection<SegmentHandler<T>> move(boolean forward) {
// 		return Collections.singleton(forward ? next : prev);
// 	}
// 
// 	void fixup() {
// 		segment.to = toIds(move(true));
// 		segment.from = toIds(move(false));
// 		segment.length = length();
// 	}
// 
// 	protected int length() {
// 		return 0;
// 	}
// 
// 	protected boolean isRoot() {
// 		return segment.id.equals(rootSegment);
// 	}
// 
// 	/**
// 	 * Events should be handled in subclasses if they have relevant events
// 	 */
// 	public boolean event(Observation e) {
// 		return false;
// 	}
// }


import osgi.enroute.trains.cloud.api.Segment;
import osgi.enroute.trains.track.util.Tracks.SegmentHandler;
		case CURVED:
			handler = curve(segment);
			break;
		case LOCATOR:
			handler = locator(segment);
			break;
		case SIGNAL:
			handler = signal(segment);
			break;
		case STRAIGHT:
			handler = straight(segment);
			break;
		case SWITCH:
			handler = swtch(segment);
			break;
		default:
			throw new IllegalArgumentException("Missing case " + segment.type);
		}
		handler.segment = segment;
		return handler;
	}

	public SegmentHandler<T> block(Segment segment) {
		return new Tracks.BlockHandler<T>(segment);
	}

	public SegmentHandler<T> curve(Segment segment) {
		return new Tracks.CurvedHandler<T>(segment);
	}

// Path: osgi.enroute.trains.api/src/osgi/enroute/trains/cloud/api/Segment.java
// public class Segment extends DTO {
// 
// 	public enum Type {
// 		STRAIGHT, CURVED, SWITCH, SIGNAL, LOCATOR, BLOCK;
// 	}
// 	
// 
// 	/**
// 	 * Our Identity
// 	 */
// 	public String id;
// 	
// 	/**
// 	 * Type of the segment
// 	 */
//  	public Type type;
// 
// 	/**
//  	* Name of the track.This is the name required to get permission 
//  	* from the Track Manager. If this name starts with X then no admission is required. This 
//  	* is generally for switches.
//  	*/
//  	public String track;
//  	
// 	/**
// 	 * Sequence of the segment in the track
// 	 */
// 	public int sequence;
// 
// 	/**
// 	 * Length of the segment in millimeters, can be zero. It an be zero because
// 	 * the relation between the controllers and the switches and the signals is
// 	 * not always 1:1 mappable to controllers. Therefore zero sized segments can
// 	 * be used to map correctly.
// 	 */
// 	public int length;
// 
// 	/**
// 	 * Short code for RFID tag attached to this segment, or 0 for none.
// 	 */
// 	public int tagCode;
// 
// 	/**
// 	 * The associated controller
// 	 */
// 	public int controller = -1;
// 
// 	/**
// 	 * The next segment. Only a switch can have an additional to. The second to
// 	 * is the one selected if the switch is set to its alternative.
// 	 */
// 	public String to[];
// 	
// 	/**
// 	 * The previous segment. Only a switch can have an additional from. The second from
// 	 * is the one selected if the switch is set to its alternative.
// 	 */
// 	public String from[];
// 
// }
// 
// Path: osgi.enroute.trains.util/src/osgi/enroute/trains/track/util/Tracks.java
// public static class SegmentHandler<T> {
// 	public Segment segment;
// 	public SegmentHandler<T> next;
// 	public SegmentHandler<T> prev;
// 
// 	public SegmentHandler(Segment segment) {
// 		this.segment = segment;
// 	}
// 
// 	boolean isPrevAlt(SegmentHandler<T> prev) {
// 		return false;
// 	}
// 
// 	@SuppressWarnings("unchecked")
// 	public T get() {
// 		return (T) this;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return segment.id;
// 	}
// 		
// 	public String getTrack(){
// 		return segment.track;
// 	}
// 
// 	public boolean isMerge() {
// 		return false;
// 	}
// 
// 	public boolean isSwitch() {
// 		return false;
// 	}
// 
// 	public boolean isPlain() {
// 		return true;
// 	}
// 		
// 	public boolean isLocator() {
// 		return false;
// 	}
// 		
// 	public boolean isSignal(){
// 		return false;
// 	}
// 
// 	public LinkedList<SegmentHandler<T>> findForward(SegmentHandler<T> destination) {
// 		LinkedList<SegmentHandler<T>> route = new LinkedList<>();
// 		if (find(route, destination, true))
// 			return new LinkedList<SegmentHandler<T>>(route);
// 		else
// 			return null;
// 	}
// 
// 	public LinkedList<SegmentHandler<T>> findBackward(SegmentHandler<T> destination) {
// 		LinkedList<SegmentHandler<T>> route = new LinkedList<>();
// 		if (find(route, destination, false))
// 			return new LinkedList<SegmentHandler<T>>(route);
// 		else
// 			return null;
// 	}
// 
// 	boolean find(List<SegmentHandler<T>> route, SegmentHandler<T> destination, boolean forward) {
// 		if (route.contains(this)){
// 			return false;
// 		}
// 
// 		route.add(this);
// 
// 		if (this == destination){
// 			return true;
// 		}
// 
// 		Collection<SegmentHandler<T>> choices = move(forward);
// 
// 		if (choices.size() == 1) {
// 			return choices.iterator().next().find(route, destination, forward);
// 		}
// 
// 		int marker = route.size();
// 		for (SegmentHandler<T> choice : choices) {
// 			if (choice.find(route, destination, forward))
// 				return true;
// 					
// 
// 			while(route.size() > marker){
// 				route.remove(marker);
// 			}
// 		}
// 
// 		return false;
// 
// 	}
// 
// 	public Collection<SegmentHandler<T>> move(boolean forward) {
// 		return Collections.singleton(forward ? next : prev);
// 	}
// 
// 	void fixup() {
// 		segment.to = toIds(move(true));
// 		segment.from = toIds(move(false));
// 		segment.length = length();
// 	}
// 
// 	protected int length() {
// 		return 0;
// 	}
// 
// 	protected boolean isRoot() {
// 		return segment.id.equals(rootSegment);
// 	}
// 
// 	/**
// 	 * Events should be handled in subclasses if they have relevant events
// 	 */
// 	public boolean event(Observation e) {
// 		return false;
// 	}
// }


// Path: osgi.enroute.trains.util/src/osgi/enroute/trains/track/util/SegmentFactoryAdapter.java
import osgi.enroute.trains.cloud.api.Segment;
import osgi.enroute.trains.track.util.Tracks.SegmentHandler;

		case CURVED:
			handler = curve(segment);
			break;
		case LOCATOR:
			handler = locator(segment);
			break;
		case SIGNAL:
			handler = signal(segment);
			break;
		case STRAIGHT:
			handler = straight(segment);
			break;
		case SWITCH:
			handler = swtch(segment);
			break;
		default:
			throw new IllegalArgumentException("Missing case " + segment.type);
		}
		handler.segment = segment;
		return handler;
	}

	public SegmentHandler<T> block(Segment segment) {
		return new Tracks.BlockHandler<T>(segment);
	}

	public SegmentHandler<T> curve(Segment segment) {
		return new Tracks.CurvedHandler<T>(segment);
	}

	public SegmentHandler<T> straight(Segment segment) {