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

prompto.value.TupleValue Maven / Gradle / Ivy

The newest version!
package prompto.value;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;

import prompto.error.IndexOutOfRangeError;
import prompto.error.PromptoError;
import prompto.error.ReadWriteError;
import prompto.error.SyntaxError;
import prompto.grammar.Identifier;
import prompto.intrinsic.IterableWithCounts;
import prompto.intrinsic.PromptoTuple;
import prompto.literal.Literal;
import prompto.runtime.Context;
import prompto.store.InvalidValueError;
import prompto.type.TupleType;
import prompto.utils.CodeWriter;

public class TupleValue extends BaseValue implements IContainer, ISliceable  {

	protected PromptoTuple items;
	
	public TupleValue(boolean mutable) {
		super(TupleType.instance());
		this.items = new PromptoTuple<>(mutable);
	}
	
	public TupleValue(PromptoTuple items) {
		super(TupleType.instance());
		this.items = items;
	}
	
	public TupleValue(Collection items, boolean mutable) {
		super(TupleType.instance());
		this.items = new PromptoTuple(items, mutable);
	}

	
	@Override
	public boolean isMutable() {
		return items.isMutable();
	}
	
	@Override
	public PromptoTuple getStorableData() {
		return items;
	}
	
	@Override
	public String toString() {
		String result = items.toString();
		return "(" + result.substring(1,result.length()-1) + ")";
	}
	
	
	@Override
	public JsonNode valueToJsonNode(Context context, Function producer) throws PromptoError {
		ArrayNode result = JsonNodeFactory.instance.arrayNode();
		for(IValue item : items)
			result.add(producer.apply(item));
		return result;
	}

	
	@Override
	public void toJsonStream(Context context, JsonGenerator generator, boolean withType, Map data) throws PromptoError {
		try {
			if(withType) {
				generator.writeStartObject();
				generator.writeFieldName("type");
				generator.writeString(this.getType().getTypeName());
				generator.writeFieldName("value");
			}
			generator.writeStartArray();
			for(IValue value : this.items)
				value.toJsonStream(context, generator, withType, data);
			generator.writeEndArray();
			if(withType)
				generator.writeEndObject();
		} catch(IOException e) {
			throw new ReadWriteError(e.getMessage());
		}
	}

	public void addItem(IValue item) {
		items.add(item);
	}
	
	public PromptoTuple getItems() {
		return items;
	}
	
	public IValue getItem(int index) {
		return items.get(index);
	}
	
	public void setItem(int index, IValue element) {
		items.set(index, element);
	}
	
	@Override
	public int hashCode() {
		return Objects.hash(items);
	}

	@Override
	public boolean equals(Object obj) {
		if(!(obj instanceof TupleValue))
			return false;
		return items.equals(((TupleValue)obj).items);
	}

	public void toDialect(CodeWriter writer) {
		writer.append('(');
		if(items.size()>0) {
			for(Object o : items) {
				if(o instanceof Literal)
					((Literal)o).toDialect(writer);
				else
					writer.append(o.toString());
				writer.append(", ");
			}
			writer.trimLast(2);
		}
		writer.append(')');
	}
	
	@Override
	public TupleValue slice(IntegerValue fi, IntegerValue li) throws IndexOutOfRangeError {
		long _fi = fi == null ? 1L : fi.longValue();
		if (_fi < 0)
			throw new IndexOutOfRangeError();
		long _li = li == null ? items.size() : li.longValue();
		if (_li > items.size())
			throw new IndexOutOfRangeError();
		PromptoTuple sliced = items.slice(_fi, _li); // 1 based
		return new TupleValue(sliced, false);
	}
	
	@Override
	public long getLength() {
		return items.size();
	}

	@Override
	public boolean hasItem(Context context, IValue lval) throws PromptoError {
		return this.items.contains(lval); // TODO interpret before
	}

	
	@Override
	public void setItem(Context context, IValue item, IValue value) {
		if(!(item instanceof IntegerValue))
			throw new InvalidValueError("Expected an Integer, got:" + item.getClass().getName());
		int index = (int)((IntegerValue)item).longValue();
		if(index<1 || index>this.getLength())
			throw new IndexOutOfRangeError();
		this.setItem(index-1, value);
	}

	
	@Override
	public IValue getItem(Context context, IValue index) throws PromptoError {
		if (index instanceof IntegerValue) {
			try {
				int idx = (int)((IntegerValue)index).longValue() - 1;
				return items.get(idx);
			} catch (IndexOutOfBoundsException e) {
				throw new IndexOutOfRangeError();
			}

		} else
			throw new SyntaxError("No such item:" + index.toString());
	}

	@Override
	public IValue plus(Context context, IValue value) throws PromptoError {
        if (value instanceof ListValue)
            return this.merge(((ListValue)value).getItems());
        else if (value instanceof TupleValue)
            return this.merge(((TupleValue)value).getItems());
        else if (value instanceof SetValue)
            return this.merge(((SetValue)value).getItems());
        else
            throw new SyntaxError("Illegal: " + this.type.getTypeName() + " + " + value.getClass().getSimpleName());
    }
	
	protected TupleValue merge(Collection items) {
		PromptoTuple result = new PromptoTuple(false);
		result.addAll(this.items);
		result.addAll(items);
		return new TupleValue(result);
	}
	
	
	@Override
	public IterableWithCounts getIterable(Context context) {
		return new IterableWithCounts() {
			@Override
			public Long getCount() {
				return (long)items.size();
			}
			@Override
			public Long getTotalCount() {
				return (long)items.size();
			}
			@Override
			public Iterator iterator() {
				return items.iterator();
			}
		};
	}

	@Override
	public IValue getMember(Context context, Identifier id, boolean autoCreate) throws PromptoError {
		String name = id.toString();
		if ("count".equals(name))
			return new IntegerValue(items.size());
		else
			return super.getMember(context, id, autoCreate);
	}
	
	
	@Override
	public int compareTo(Context context, IValue value) throws PromptoError {
		if(!(value instanceof TupleValue))
			return super.compareTo(context, value);
		return compareTo(context, (TupleValue)value, new ArrayList());
	}

	public int compareTo(Context context, TupleValue other, Collection directions) throws PromptoError {
		Iterator iterDirs = directions.iterator();
		Iterator iterThis = this.items.iterator();
		Iterator iterOther = other.items.iterator();
		while(iterThis.hasNext() && iterOther.hasNext()) {
			boolean descending = iterDirs.hasNext() ? iterDirs.next() : false;
			// compare items
			IValue thisVal = iterThis.next();
			IValue otherVal = iterOther.next();
			if(thisVal==null && otherVal==null)
				continue;
			else if(thisVal==null)
				return descending ? 1 : -1;
			else if(otherVal==null)
				return descending ? -1 : 1;
			int cmp = thisVal.compareTo(context, otherVal);
			// if not equal, done
			if(cmp!=0) {
				return descending ? -cmp : cmp;
			}
		}
		boolean descending = iterDirs.hasNext() ? iterDirs.next() : false;
		if(iterThis.hasNext())
			return descending ? -1 : 1;
		else if(iterOther.hasNext())
			return descending ? 1 : -1;
		else
			return 0;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy