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

org.etlunit.parser.ETLTestValueObjectBuilder Maven / Gradle / Ivy

There is a newer version: 1.6.9
Show newest version
package org.etlunit.parser;

import java.util.*;

public class ETLTestValueObjectBuilder
{
	enum stack_type
	{
		list,
		map
	}

	enum value_type
	{
		valueObject,
		string,
		pojo,
		json
	}

	class StackItem
	{
		final Map mapContext;
		final List listContext;
		final String myAttributeName;

		final stack_type type;

		StackItem(List list)
		{
			mapContext = null;
			listContext = list;
			myAttributeName = null;
			type = stack_type.list;
		}

		StackItem(Map map)
		{
			mapContext = map;
			listContext = null;
			myAttributeName = null;
			type = stack_type.map;
		}

		StackItem(stack_type type, String attributeName)
		{
			this.type = type;
			this.myAttributeName = attributeName;

			switch (type)
			{

				case list:
					listContext = new ArrayList();
					mapContext = null;
					break;
				case map:
					listContext = null;
					mapContext = new HashMap();
					break;
				default:
					throw new IllegalArgumentException();
			}
		}
	}

	private final LinkedList stack = new LinkedList();
	private String currentAttributeName = null;
	private final ETLTestValueObject base;

	public ETLTestValueObjectBuilder()
	{
		base = null;
	}

	public ETLTestValueObjectBuilder(ETLTestValueObject base)
	{
		this.base = base;

		switch (base.getValueType())
		{
			case quoted_string:
				throw new IllegalArgumentException("Cannot extend a string value");
			case object:
				stack.add(new StackItem(base.getValueAsMap()));
				break;
			case list:
				stack.add(new StackItem(base.getValueAsList()));
				break;
			case literal:
				throw new IllegalArgumentException("Cannot extend a string value");
			case pojo:
				throw new IllegalArgumentException("Cannot extend a pojo value");
		}
	}

	public ETLTestValueObjectBuilder object()
	{
		stack.push(new StackItem(stack_type.map, currentAttributeName));
		currentAttributeName = null;

		return this;
	}

	public ETLTestValueObjectBuilder list()
	{
		stack.push(new StackItem(stack_type.list, currentAttributeName));
		currentAttributeName = null;

		return this;
	}

	public ETLTestValueObjectBuilder key(String name)
	{
		if (stack.size() == 0)
		{
			throw new IllegalStateException("Builder does not have a current state");
		}
		else if (currentAttributeName != null)
		{
			throw new IllegalStateException("Builder already has a key context");
		}
		else if (stack.peek().type == stack_type.list)
		{
			throw new IllegalStateException("Lists do not have keys");
		}
		else
		{
			StackItem si = stack.peek();

			if (si.type == stack_type.map && si.mapContext.containsKey(name))
			{
				throw new IllegalStateException("Key name '" + name + "' has already been used in this context");
			}
		}

		currentAttributeName = name;

		return this;
	}

	public ETLTestValueObjectBuilder removeKey(String name)
	{
		if (stack.size() == 0)
		{
			throw new IllegalStateException("Builder does not have a current state");
		}
		else if (currentAttributeName != null)
		{
			throw new IllegalStateException("Builder already has a key context");
		}
		else if (stack.peek().type == stack_type.list)
		{
			throw new IllegalStateException("Lists do not have keys");
		}
		else
		{
			StackItem si = stack.peek();

			if (si.type == stack_type.map && !si.mapContext.containsKey(name))
			{
				throw new IllegalStateException("Key name '" + name + "' does not exist in this context");
			}

			si.mapContext.remove(name);
		}

		return this;
	}

	public boolean hasKey(String name)
	{
		if (stack.size() == 0)
		{
			throw new IllegalStateException("Builder does not have a current state");
		}
		else if (stack.peek().type == stack_type.list)
		{
			throw new IllegalStateException("Lists do not have keys");
		}
		else
		{
			StackItem si = stack.peek();

			if (si.type == stack_type.map && si.mapContext.containsKey(name))
			{
				return true;
			}
		}

		return false;
	}

	public ETLTestValueObjectBuilder value(String val)
	{
		return value(val, value_type.string);
	}

	public ETLTestValueObjectBuilder value(ETLTestValueObject val)
	{
		return value(val, value_type.valueObject);
	}

	public ETLTestValueObjectBuilder pojoValue(Object val)
	{
		return value(val, value_type.pojo);
	}

	public ETLTestValueObjectBuilder jsonValue(Object val)
	{
		return value(val, value_type.json);
	}

	private ETLTestValueObjectBuilder value(Object val, value_type type)
	{
		if (stack.size() == 0)
		{
			throw new IllegalStateException("Builder does not have a current state");
		}

		//if the current context is a list, append to the list
		StackItem st = stack.peek();

		ETLTestValueObject valObj = null;

		switch (type)
		{
			case valueObject:
				valObj = (ETLTestValueObject) val;
				break;
			case string:
				valObj = new ETLTestValueObjectImpl((String) val);
				break;
			case pojo:
				valObj = new ETLTestValueObjectImpl(val);
				break;
			case json:
				try
				{
					valObj = ETLTestParser.loadObject((String) val);
				}
				catch (ParseException e)
				{
					throw new IllegalArgumentException("Json object is not valid");
				}
				break;
		}

		if (st.type == stack_type.list)
		{
			st.listContext.add(valObj);
		}
		else if (currentAttributeName == null)
		{
			throw new IllegalStateException("Values on objects need a key value first");
		}
		else
		{
			st.mapContext.put(currentAttributeName, valObj);
			// key value can only be used once
			currentAttributeName = null;
		}

		return this;
	}

	public ETLTestValueObjectBuilder endList()
	{
		StackItem st = stack.peek();

		// if the list is our only context, do nothing
		if (st.type == stack_type.map)
		{
			throw new IllegalStateException("Object not in context");
		}
		else if (stack.size() == 1)
		{
			return this;
		}

		// pop the list and decide what to do with it
		st = stack.pop();

		ETLTestValueObjectImpl valueObject = new ETLTestValueObjectImpl(st.listContext);

		// if the next item down is a list, then add this item onto that list
		StackItem enclosing = stack.peek();

		if (enclosing.type == stack_type.list)
		{
			enclosing.listContext.add(valueObject);
		}
		else if (st.myAttributeName == null)
		{
			throw new IllegalStateException("List needs a key name");
		}
		else
		{
			// we must have a key to map this element to
			enclosing.mapContext.put(st.myAttributeName, valueObject);
		}

		return this;
	}

	public ETLTestValueObjectBuilder endObject()
	{
		StackItem child = stack.peek();

		//if this is the root object, do nothing
		if (currentAttributeName != null)
		{
			throw new IllegalStateException("Key " + currentAttributeName + " has not ben given a value");
		}
		else if (child.type == stack_type.list)
		{
			throw new IllegalStateException("Object not in context");
		}
		else if (stack.size() == 1)
		{
			return this;
		}

		// pop this element off, and attach this object to it's parent
		child = stack.pop();
		StackItem parent = stack.peek();

		ETLTestValueObjectImpl valueObject = new ETLTestValueObjectImpl(child.mapContext);

		// ensure that the child is in fact an object
		if (parent.type == stack_type.list)
		{
			// just add to the end of the list
			parent.listContext.add(valueObject);
		}
		else if (child.myAttributeName == null)
		{
			throw new IllegalStateException("Object needs a key name");
		}
		else
		{
			parent.mapContext.put(child.myAttributeName, valueObject);
		}

		return this;
	}

	public ETLTestValueObject toObject()
	{
		if (stack.size() == 0)
		{
			throw new IllegalStateException("Builder does not have a current state");
		}

		StackItem st = stack.peek();

		switch (st.type)
		{
			case list:
				return new ETLTestValueObjectImpl(st.listContext);
			case map:
				return new ETLTestValueObjectImpl(st.mapContext);
			default:
				throw new IllegalStateException("");
		}
	}

	public ETLTestValueObjectBuilder removeAllKeys(String... keys)
	{
		for (String key : keys)
		{
			if (hasKey(key))
			{
				removeKey(key);
			}
		}

		return this;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy