initial commit

This commit is contained in:
2018-09-09 13:37:13 +01:00
commit 5087e092c1
31 changed files with 1991 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
package org.oggio88.worth.buffer;
import lombok.SneakyThrows;
import java.io.Reader;
public class CircularBuffer {
private int[] buffer;
private Reader reader;
private int delta = 0, cursor = 0;
public CircularBuffer(Reader reader, int size) {
this.reader = reader;
buffer = new int[size];
}
@SneakyThrows
public int next() {
if (delta < 0)
return buffer[Math.floorMod(cursor + delta++, buffer.length)];
else {
int result = reader.read();
if (result < 0) return result;
buffer[cursor] = result;
cursor = (cursor + 1) % buffer.length;
return result;
}
}
public int prev() {
return buffer[cursor + --delta >= 0 ? cursor + delta : cursor + delta + buffer.length];
}
public int size() {
return buffer.length;
}
}

View File

@@ -0,0 +1,7 @@
package org.oggio88.worth.exception;
public class IOException extends WorthException {
public IOException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,7 @@
package org.oggio88.worth.exception;
public class NotImplementedException extends WorthException {
public NotImplementedException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,7 @@
package org.oggio88.worth.exception;
public class ParseException extends WorthException {
public ParseException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,7 @@
package org.oggio88.worth.exception;
public class TypeException extends WorthException {
public TypeException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,7 @@
package org.oggio88.worth.exception;
public class WorthException extends RuntimeException {
public WorthException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,105 @@
package org.oggio88.worth.serialization;
import lombok.RequiredArgsConstructor;
import org.oggio88.worth.exception.NotImplementedException;
import org.oggio88.worth.value.ArrayValue;
import org.oggio88.worth.value.ObjectValue;
import org.oggio88.worth.xface.Dumper;
import org.oggio88.worth.xface.Value;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;
public abstract class ValueDumper implements Dumper {
@RequiredArgsConstructor
protected static class StackLevel {
public int index = 0;
public final Value value;
}
protected static class ArrayStackLevel extends StackLevel implements Iterator<Value> {
private final Iterator<Value> iterator = value.asArray().iterator();
@Override
public Value next() {
++index;
return iterator.next();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
public ArrayStackLevel(ArrayValue value) {
super(value);
}
}
protected static class ObjectStackLevel extends StackLevel implements Iterator<Map.Entry<String, Value>> {
private final Iterator<Map.Entry<String, Value>> iterator = value.asObject().entrySet().iterator();
@Override
public Map.Entry<String, Value> next() {
++index;
return iterator.next();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
public ObjectStackLevel(ObjectValue value) {
super(value);
}
}
protected Stack<StackLevel> stack;
protected ValueDumper() {
stack = new Stack<>();
}
@Override
public void dump(Value value, OutputStream stream) {
throw new NotImplementedException("Method not implemented");
}
@Override
public void dump(Value value, Writer writer) {
throw new NotImplementedException("Method not implemented");
}
@Override
public void dump(Value value, OutputStream stream, Charset encoding) {
dump(value, new OutputStreamWriter(stream, encoding));
}
protected abstract void beginObject();
protected abstract void endObject();
protected abstract void beginArray();
protected abstract void endArray();
protected abstract void objectKey(String key);
protected abstract void stringValue(String value);
protected abstract void integerValue(long value);
protected abstract void floatValue(double value);
protected abstract void booleanValue(boolean value);
protected abstract void nullValue();
}

View File

@@ -0,0 +1,116 @@
package org.oggio88.worth.serialization;
import lombok.RequiredArgsConstructor;
import org.oggio88.worth.exception.NotImplementedException;
import org.oggio88.worth.utils.WorthUtils;
import org.oggio88.worth.value.ArrayValue;
import org.oggio88.worth.value.BooleanValue;
import org.oggio88.worth.value.FloatValue;
import org.oggio88.worth.value.IntegerValue;
import org.oggio88.worth.value.ObjectValue;
import org.oggio88.worth.value.StringValue;
import org.oggio88.worth.xface.Parser;
import org.oggio88.worth.xface.Value;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Stack;
public class ValueParser implements Parser {
@RequiredArgsConstructor
protected static class StackLevel {
public final Value value;
}
protected static class ArrayStackLevel extends StackLevel {
public ArrayStackLevel() {
super(new ArrayValue());
}
}
protected static class ObjectStackLevel extends StackLevel {
public String currentKey;
public ObjectStackLevel() {
super(ObjectValue.newInstance());
}
}
protected Stack<StackLevel> stack;
private void add2Last(Value value) {
StackLevel last = stack.lastElement();
ArrayStackLevel asl;
ObjectStackLevel osl;
if ((asl = WorthUtils.dynamicCast(last, ArrayStackLevel.class)) != null)
asl.value.add(value);
else if ((osl = WorthUtils.dynamicCast(last, ObjectStackLevel.class)) != null) {
osl.value.put(osl.currentKey, value);
osl.currentKey = null;
}
}
protected ValueParser() {
stack = new Stack<>();
stack.push(new ArrayStackLevel());
}
@Override
public Value parse(InputStream is) {
throw new NotImplementedException("Method not implemented");
}
@Override
public Value parse(Reader reader) {
throw new NotImplementedException("Method not implemented");
}
@Override
public Value parse(InputStream stream, Charset encoding) {
return parse(new InputStreamReader(stream, encoding));
}
protected void beginObject() {
stack.push(new ObjectStackLevel());
}
protected void endObject() {
add2Last(stack.pop().value);
}
protected void beginArray() {
stack.push(new ArrayStackLevel());
}
protected void endArray() {
add2Last(stack.pop().value);
}
protected void objectKey(String key) {
ObjectStackLevel osl = (ObjectStackLevel) stack.lastElement();
osl.currentKey = key;
}
protected void stringValue(String value) {
add2Last(new StringValue(value));
}
protected void integerValue(long value) {
add2Last(new IntegerValue(value));
}
protected void floatValue(double value) {
add2Last(new FloatValue(value));
}
protected void booleanValue(boolean value) {
add2Last(new BooleanValue(value));
}
protected void nullValue() {
add2Last(Value.Null);
}
}

View File

@@ -0,0 +1,183 @@
package org.oggio88.worth.serialization.json;
import lombok.SneakyThrows;
import org.oggio88.worth.serialization.ValueDumper;
import org.oggio88.worth.value.ArrayValue;
import org.oggio88.worth.value.ObjectValue;
import org.oggio88.worth.xface.Dumper;
import org.oggio88.worth.xface.Value;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;
import java.util.function.Consumer;
import static org.oggio88.worth.utils.WorthUtils.dynamicCast;
public class JSONDumper extends ValueDumper {
public static Dumper newInstance() {
return new JSONDumper();
}
protected Writer writer;
@Override
public void dump(Value value, OutputStream stream) {
dump(value, new OutputStreamWriter(stream));
}
@Override
@SneakyThrows
public void dump(Value value, Writer writer) {
this.writer = writer;
final Consumer<Value> handle_value = (v) -> {
switch (v.type()) {
case NULL:
nullValue();
break;
case BOOLEAN:
booleanValue(v.asBoolean());
break;
case INTEGER:
integerValue(v.asInteger());
break;
case DOUBLE:
floatValue(v.asFloat());
break;
case STRING:
stringValue(v.asString());
break;
case ARRAY:
stack.push(new ArrayStackLevel(dynamicCast(v, ArrayValue.class)));
beginArray();
break;
case OBJECT:
stack.push(new ObjectStackLevel(dynamicCast(v, ObjectValue.class)));
beginObject();
break;
}
};
handle_value.accept(value);
while (stack.size() > 0) {
StackLevel last = stack.lastElement();
ArrayStackLevel arrayStackLevel;
ObjectStackLevel objectStackLevel;
if ((arrayStackLevel = dynamicCast(last, ArrayStackLevel.class)) != null) {
if (arrayStackLevel.hasNext()) {
if (arrayStackLevel.index > 0) {
writer.write(",");
}
handle_value.accept(arrayStackLevel.next());
} else {
endArray();
stack.pop();
}
} else if ((objectStackLevel = dynamicCast(last, ObjectStackLevel.class)) != null) {
if (objectStackLevel.hasNext()) {
if (objectStackLevel.index > 0) {
writer.write(",");
}
Map.Entry<String, Value> entry = objectStackLevel.next();
objectKey(entry.getKey());
writer.write(":");
handle_value.accept(entry.getValue());
} else {
endObject();
stack.pop();
}
}
}
this.writer.flush();
this.writer = null;
}
@Override
@SneakyThrows
protected void beginObject() {
this.writer.write("{");
}
@Override
@SneakyThrows
protected void endObject() {
this.writer.write("}");
}
@Override
@SneakyThrows
protected void beginArray() {
this.writer.write("[");
}
@Override
@SneakyThrows
protected void endArray() {
this.writer.write("]");
}
@Override
@SneakyThrows
protected void objectKey(String key) {
this.writer.write("\"" + key + "\"");
}
@Override
@SneakyThrows
protected void stringValue(String value) {
StringBuilder sb = new StringBuilder();
for (char c : value.toCharArray()) {
switch (c) {
case '"':
sb.append("\\\"");
break;
case '\r':
sb.append("\\r");
break;
case '\n':
sb.append("\\n");
break;
case '\t':
sb.append("\\t");
break;
case '\\':
sb.append("\\\\");
break;
default: {
if (c < 128)
sb.append(c);
else {
sb.append("\\u").append(String.format("%04X", (int) c));
}
}
}
}
this.writer.write("\"" + sb.toString() + "\"");
}
@Override
@SneakyThrows
protected void integerValue(long value) {
this.writer.write(Long.toString(value));
}
@Override
@SneakyThrows
protected void floatValue(double value) {
this.writer.write(Double.toString(value));
}
@Override
@SneakyThrows
protected void booleanValue(boolean value) {
this.writer.write(Boolean.toString(value));
}
@Override
@SneakyThrows
protected void nullValue() {
this.writer.write("null");
}
}

View File

@@ -0,0 +1,227 @@
package org.oggio88.worth.serialization.json;
import lombok.SneakyThrows;
import org.oggio88.worth.buffer.CircularBuffer;
import org.oggio88.worth.exception.IOException;
import org.oggio88.worth.exception.NotImplementedException;
import org.oggio88.worth.exception.ParseException;
import org.oggio88.worth.serialization.ValueParser;
import org.oggio88.worth.utils.WorthUtils;
import org.oggio88.worth.xface.Parser;
import org.oggio88.worth.xface.Value;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.function.Function;
public class JSONParser extends ValueParser {
private int currentLine = 1, currentColumn = 1;
private static boolean isBlank(int c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
private static boolean isDecimal(int c) {
return c >= '0' && c <= '9' || c == '+' || c == '-' || c == '.' || c == 'e';
}
private static int parseHex(CircularBuffer circularBuffer) {
int result = 0;
while (true) {
int c = circularBuffer.next();
if (c >= '0' && c <= '9') {
result = result << 4;
result += (c - '0');
} else if (c >= 'a' && c <= 'f') {
result = result << 4;
result += 10 + (c - 'a');
} else if (c >= 'A' && c <= 'F') {
result = result << 4;
result += 10 + (c - 'A');
} else {
circularBuffer.prev();
break;
}
}
return result;
}
private final void parseNumber(CircularBuffer circularBuffer) {
StringBuilder sb = new StringBuilder();
while (true) {
int b = circularBuffer.next();
if (isDecimal(b)) {
sb.appendCodePoint(b);
} else {
circularBuffer.prev();
break;
}
}
String text = sb.toString();
if (text.indexOf('.') > 0) {
floatValue(Double.valueOf(text));
} else {
integerValue(Long.valueOf(text));
}
}
private final String readString(CircularBuffer circularBuffer) {
StringBuilder sb = new StringBuilder();
boolean escape = false;
while (true) {
int c = circularBuffer.next();
if (c < 0) {
circularBuffer.prev();
break;
} else if (escape) {
switch (c) {
case '"':
sb.append('\"');
break;
case 'r':
sb.append('\r');
break;
case 'n':
sb.append('\n');
break;
case 't':
sb.append('\t');
break;
case '\\':
sb.append('\\');
break;
case 'u':
int codePoint = parseHex(circularBuffer);
sb.appendCodePoint(codePoint);
break;
default:
throw error(ParseException::new, "Unrecognized escape sequence '\\%c'", c);
}
escape = false;
} else if (c == '\\') {
escape = true;
} else if (c == '\"') {
break;
} else {
sb.appendCodePoint(c);
}
}
return sb.toString();
}
private final void consumeExpected(CircularBuffer circularBuffer, String expected, String errorMessage) {
for (int i = 0; i < expected.length(); i++) {
int c = circularBuffer.next();
if (c < 0) {
throw error(IOException::new, "Unexpected end of stream");
}
if (c != expected.codePointAt(i)) throw error(ParseException::new, errorMessage);
}
}
private <T extends RuntimeException> T error(Function<String, T> constructor, String fmt, Object... args) {
return constructor.apply(
String.format("Error at line %d column %d: %s",
currentLine, currentColumn, String.format(fmt, args)));
}
public static Parser newInstance() {
return new JSONParser();
}
@Override
public Value parse(InputStream stream) {
return parse(new InputStreamReader(stream));
}
@Override
@SneakyThrows
public Value parse(Reader reader) {
final CircularBuffer circularBuffer = new CircularBuffer(reader, 8) {
@Override
public int next() {
int result = super.next();
if (result == '\n') {
++currentLine;
currentColumn = 1;
} else {
++currentColumn;
}
return result;
}
@Override
public int prev() {
int result = super.prev();
if (result == '\n') {
--currentLine;
} else {
--currentColumn;
}
return result;
}
};
try {
while (true) {
int c = circularBuffer.next();
if (c == -1) {
break;
} else if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
continue;
} else if (c == '{') {
beginObject();
} else if (c == '}') {
endObject();
} else if (c == '[') {
beginArray();
} else if (c == ']') {
endArray();
} else if (isDecimal(c)) {
circularBuffer.prev();
try {
parseNumber(circularBuffer);
} catch (NumberFormatException nfe) {
}
} else if (c == '\"') {
String text = readString(circularBuffer);
ObjectStackLevel osl;
if ((osl = WorthUtils.dynamicCast(stack.lastElement(), ObjectStackLevel.class)) != null && osl.currentKey == null) {
objectKey(text);
} else {
stringValue(text);
}
} else if (c == 't') {
consumeExpected(circularBuffer, "rue", "Unrecognized boolean value");
booleanValue(true);
} else if (c == 'f') {
consumeExpected(circularBuffer, "alse", "Unrecognized boolean value");
booleanValue(false);
} else if (c == 'n') {
consumeExpected(circularBuffer, "ull", "Unrecognized null value");
nullValue();
}
}
if (stack.size() > 1) {
char c;
if (stack.lastElement() instanceof ArrayStackLevel) {
c = ']';
} else if (stack.lastElement() instanceof ObjectStackLevel) {
c = '}';
} else {
throw new NotImplementedException("This should never happen");
}
throw error(ParseException::new, "Missing '%c' token", c);
}
return WorthUtils.dynamicCast(stack.lastElement(), ArrayStackLevel.class).value.get(0);
} catch (NumberFormatException e) {
throw error(ParseException::new, e.getMessage());
} finally {
stack.clear();
}
}
}

View File

@@ -0,0 +1,26 @@
package org.oggio88.worth.utils;
import lombok.SneakyThrows;
import java.util.concurrent.Callable;
public class WorthUtils {
@SneakyThrows
public static <T> T uncheckCall(final Callable<T> callable) {
return callable.call();
}
public static <T> T dynamicCast(final Object o, final Class<T> cls) {
if (cls.isInstance(o)) {
return (T) o;
} else {
return null;
}
}
public static boolean equalsNullSafe(Object o1, Object o2) {
if (o1 == null) return o2 == null;
else return o1.equals(o2);
}
}

View File

@@ -0,0 +1,69 @@
package org.oggio88.worth.value;
import lombok.EqualsAndHashCode;
import org.oggio88.worth.xface.Value;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@EqualsAndHashCode
public class ArrayValue implements Value, Iterable<Value> {
private final List<Value> value;
public ArrayValue() {
this.value = new ArrayList();
}
public ArrayValue(List<Value> value) {
this.value = value;
}
@Override
public Type type() {
return Type.ARRAY;
}
@Override
public void add(Value value) {
this.value.add(value);
}
@Override
public Value get(int index) {
return value.get(index);
}
@Override
public Value pop() {
Value last = tail();
value.remove(value.size() - 1);
return last;
}
@Override
public Value head() {
return value.get(0);
}
@Override
public Value tail() {
return value.get(value.size() - 1);
}
@Override
public List<Value> asArray() {
return value;
}
@Override
public Iterator<Value> iterator() {
return value.iterator();
}
public int size() {
return value.size();
}
}

View File

@@ -0,0 +1,24 @@
package org.oggio88.worth.value;
import lombok.EqualsAndHashCode;
import org.oggio88.worth.xface.Value;
@EqualsAndHashCode
public class BooleanValue implements Value {
private final boolean value;
public BooleanValue(boolean value) {
this.value = value;
}
@Override
public Type type() {
return Type.BOOLEAN;
}
@Override
public boolean asBoolean() {
return value;
}
}

View File

@@ -0,0 +1,24 @@
package org.oggio88.worth.value;
import lombok.EqualsAndHashCode;
import org.oggio88.worth.xface.Value;
@EqualsAndHashCode
public class FloatValue implements Value {
private final double value;
public FloatValue(double value) {
this.value = value;
}
@Override
public Type type() {
return Type.DOUBLE;
}
@Override
public double asFloat() {
return value;
}
}

View File

@@ -0,0 +1,24 @@
package org.oggio88.worth.value;
import lombok.EqualsAndHashCode;
import org.oggio88.worth.xface.Value;
@EqualsAndHashCode
public class IntegerValue implements Value {
private final long value;
public IntegerValue(long value) {
this.value = value;
}
@Override
public Type type() {
return Type.INTEGER;
}
@Override
public long asInteger() {
return value;
}
}

View File

@@ -0,0 +1,13 @@
package org.oggio88.worth.value;
import lombok.EqualsAndHashCode;
import org.oggio88.worth.xface.Value;
@EqualsAndHashCode
public class NullValue implements Value {
@Override
public Type type() {
return Type.NULL;
}
}

View File

@@ -0,0 +1,185 @@
package org.oggio88.worth.value;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.oggio88.worth.xface.Value;
import java.util.*;
import static org.oggio88.worth.utils.WorthUtils.equalsNullSafe;
public interface ObjectValue extends Value, Iterable<Map.Entry<String, Value>> {
boolean listBasedImplementation = Boolean.valueOf(
System.getProperty("org.oggio88.javason.value.ObjectValue.listBasedImplementation", "false"));
boolean preserveKeyOrder = Boolean.valueOf(
System.getProperty("org.oggio88.javason.value.MapObjectValue.preserveKeyOrder", "false"));
static ObjectValue newInstance() {
if (listBasedImplementation) {
return new MapObjectValue();
} else {
return new MapObjectValue();
}
}
@Override
default Type type() {
return Type.OBJECT;
}
}
final class ObjectEntry<K, V> implements Map.Entry<K, V> {
private final K key;
private V value;
public ObjectEntry(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
V old = this.value;
this.value = value;
return old;
}
}
@EqualsAndHashCode
class MapObjectValue implements ObjectValue {
private final Map<String, Value> value;
public MapObjectValue() {
this.value = ObjectValue.preserveKeyOrder ? new LinkedHashMap() : new HashMap();
}
public MapObjectValue(Map<String, Value> value) {
this.value = value;
}
@Override
public Map<String, Value> asObject() {
return value;
}
@Override
public Value get(String key) {
Value result = value.get(key);
if (result == null) {
result = Value.Null;
value.put(key, result);
}
return result;
}
@Override
public Value getOrDefault(String key, Value defaultValue) {
if (value.containsKey(key))
return value.get(key);
else
return defaultValue;
}
@Override
public Value getOrPut(String key, Value value2Put) {
if (value.containsKey(key))
return value.get(key);
else {
put(key, value2Put);
return value2Put;
}
}
@Override
public void put(String key, Value value2Put) {
this.value.put(key, value2Put);
}
@Override
public boolean has(String key) {
return value.containsKey(key);
}
@Override
public Iterator<Map.Entry<String, Value>> iterator() {
return value.entrySet().iterator();
}
}
@NoArgsConstructor
@EqualsAndHashCode
class ListObjectValue implements ObjectValue {
private final List<Map.Entry<String, Value>> value = new ArrayList();
public ListObjectValue(Map<String, Value> map) {
this.value.addAll(map.entrySet());
}
@Override
public Map<String, Value> asObject() {
Map<String, Value> result = preserveKeyOrder ? new LinkedHashMap() : new HashMap();
for (Map.Entry<String, Value> entry : value) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
@Override
public Value get(String key) {
for (Map.Entry<String, Value> entry : value) {
if(equalsNullSafe(entry.getKey(), key)) return entry.getValue();
}
return Value.Null;
}
@Override
public Value getOrDefault(String key, Value defaultValue) {
for (Map.Entry<String, Value> entry : value) {
if(equalsNullSafe(entry.getKey(), key)) return entry.getValue();
}
return defaultValue;
}
@Override
public Value getOrPut(String key, Value value2Put) {
for (Map.Entry<String, Value> entry : value) {
if(equalsNullSafe(entry.getKey(), key)) return entry.getValue();
}
put(key, value2Put);
return value2Put;
}
@Override
public void put(String key, Value value2Put) {
value.add(new ObjectEntry(key, value2Put));
}
@Override
public boolean has(String key) {
for (Map.Entry<String, Value> entry : value) {
if(equalsNullSafe(entry.getKey(), key)) return true;
}
return false;
}
@Override
public Iterator<Map.Entry<String, Value>> iterator() {
return value.iterator();
}
}

View File

@@ -0,0 +1,25 @@
package org.oggio88.worth.value;
import lombok.EqualsAndHashCode;
import org.oggio88.worth.xface.Value;
@EqualsAndHashCode
public class StringValue implements Value {
private final String value;
public StringValue(String value)
{
this.value = value;
}
@Override
public Type type() {
return Type.STRING;
}
@Override
public String asString() {
return value;
}
}

View File

@@ -0,0 +1,13 @@
package org.oggio88.worth.xface;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.charset.Charset;
public interface Dumper {
void dump(Value value, OutputStream is);
void dump(Value value, Writer reader);
void dump(Value value, OutputStream stream, Charset encoding);
}

View File

@@ -0,0 +1,14 @@
package org.oggio88.worth.xface;
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.Charset;
public interface Parser {
Value parse(InputStream is);
Value parse(Reader reader);
Value parse(InputStream stream, Charset encoding);
}

View File

@@ -0,0 +1,82 @@
package org.oggio88.worth.xface;
import org.oggio88.worth.exception.TypeException;
import org.oggio88.worth.value.NullValue;
import java.util.List;
import java.util.Map;
public interface Value {
Value Null = new NullValue();
enum Type {
OBJECT, ARRAY, STRING, DOUBLE, INTEGER, BOOLEAN, NULL
}
Type type();
default boolean asBoolean() {
throw new TypeException("Not a boolean");
}
default long asInteger() {
throw new TypeException("Not an integer");
}
default double asFloat() {
throw new TypeException("Not a float");
}
default String asString() {
throw new TypeException("Not a String");
}
default List<Value> asArray() {
throw new TypeException("Not an array");
}
default Map<String, Value> asObject() {
throw new TypeException("Not an object");
}
default void add(Value value) {
throw new TypeException("Not an array");
}
default Value pop() {
throw new TypeException("Not an array");
}
default Value head() {
throw new TypeException("Not an array");
}
default Value tail() {
throw new TypeException("Not an array");
}
default Value get(int index) {
throw new TypeException("Not an array");
}
default void put(String key, Value value) {
throw new TypeException("Not an object");
}
default Value get(String key) {
throw new TypeException("Not an object");
}
default Value getOrDefault(String key, Value defaultValue) {
throw new TypeException("Not an object");
}
default Value getOrPut(String key, Value value2Put) {
throw new TypeException("Not an object");
}
default boolean has(String key) {
throw new TypeException("Not an object");
}
}