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

se.l4.commons.config.internal.streaming.MapInput Maven / Gradle / Ivy

The newest version!
package se.l4.commons.config.internal.streaming;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import se.l4.commons.serialization.format.AbstractStreamingInput;
import se.l4.commons.serialization.format.StreamingInput;
import se.l4.commons.serialization.format.Token;

/**
 * Implementation of {@link StreamingInput} that works on a objects.
 * 
 * @author Andreas Holstenson
 *
 */
public class MapInput
	extends AbstractStreamingInput
{
	private enum State
	{
		START,
		KEY,
		VALUE,
		END,
		DONE
	}
	
	private State state;
	private State previousState;
	private Token token;
	
	private Map.Entry entry;
	private Iterator> iterator;
	
	private StreamingInput subInput;
	private String key;

	public MapInput(String key, Map root)
	{
		this.key = key;
		state = State.START;
		
		iterator = root.entrySet().iterator();
	}
	
	@Override
	public void close()
		throws IOException
	{
		// Nothing to close
	}
	
	public static StreamingInput resolveInput(String key, Object data)
	{
		if(data instanceof Map)
		{
			return new MapInput(key, (Map) data);
		}
		else if(data instanceof List)
		{
			return new ListInput(key, (List) data);
		}
		else if(data == null)
		{
			return new NullInput(key);
		}
		else
		{
			return new ValueInput(key, data);
		}
	}
	
	private StreamingInput resolveInput()
	{
		String newKey = key.isEmpty() ? entry.getKey() : key + '.' + entry.getKey();
		return resolveInput(newKey, entry.getValue());
	}
	
	@Override
	protected IOException raiseException(String message)
	{
		return new IOException(key + ": " + message);
	}

	@Override
	public Token peek()
		throws IOException
	{
		switch(state)
		{
			case START:
				return Token.OBJECT_START;
			case KEY:
				return Token.KEY;
			case VALUE:
				Token peeked = subInput.peek();
				if(peeked != null)
				{
					return peeked;
				}
				else
				{
					advancePosition();
					return peek();
				}
			case END:
				return Token.OBJECT_END;
		}
		
		return null;
	}

	@Override
	public Token next0()
		throws IOException
	{
		switch(state)
		{
			case START:
				// Check what the next state should be
				advancePosition();
				return token = Token.OBJECT_START;
			case KEY:
				setState(State.VALUE);
				subInput = resolveInput();
				return token = Token.KEY;
			case VALUE:
				/*
				 * Value state, check the sub input until it returns null
				 */
				Token t = subInput.next();
				if(t == null)
				{
					// Nothing left in the value, advance and check again
					advancePosition();
					return next();
				}
				
				setState(State.VALUE);
				return token = t;
			case END:
				setState(State.DONE);
				return token = Token.OBJECT_END;
		}
		
		return token = null;
	}
	
	private void setState(State state)
	{
		previousState = this.state;
		this.state = state;
	}

	private void advancePosition()
	{
		if(iterator.hasNext())
		{
			entry = iterator.next();
			setState(State.KEY);
		}
		else
		{
			setState(State.END);
		}
	}

	@Override
	public Token current()
	{
		return subInput != null ? subInput.current() : token;
	}

	@Override
	public Object getValue()
	{
		switch(previousState)
		{
			case KEY:
				return entry.getKey();
			case VALUE:
				return subInput.getValue();
		}
		
		return null;
	}

	@Override
	public String getString()
	{
		switch(previousState)
		{
			case KEY:
				return entry.getKey();
			case VALUE:
				return subInput.getString();
		}
		
		return null;
	}

	@Override
	public boolean getBoolean()
	{
		switch(previousState)
		{
			case VALUE:
				return subInput.getBoolean();
		}
		
		return false;
	}

	@Override
	public double getDouble()
	{
		switch(previousState)
		{
			case VALUE:
				return subInput.getDouble();
		}
		
		return 0;
	}

	@Override
	public float getFloat()
	{
		switch(previousState)
		{
			case VALUE:
				return subInput.getFloat();
		}
		
		return 0;
	}

	@Override
	public long getLong()
	{
		switch(previousState)
		{
			case VALUE:
				return subInput.getLong();
		}
		
		return 0;
	}

	@Override
	public int getInt()
	{
		switch(previousState)
		{
			case VALUE:
				return subInput.getInt();
		}
		
		return 0;
	}

	@Override
	public short getShort()
	{
		switch(previousState)
		{
			case VALUE:
				return subInput.getShort();
		}
		
		return 0;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy