/*
 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.jfr.consumer;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.Duration;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

import jdk.jfr.Timespan;
import jdk.jfr.Timestamp;
import jdk.jfr.ValueDescriptor;
import jdk.jfr.internal.consumer.JdkJfrConsumer;
import jdk.jfr.internal.consumer.ObjectFactory;
import jdk.jfr.internal.PrivateAccess;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.consumer.ObjectContext;
import jdk.jfr.internal.tool.PrettyWriter;

/**
 * A complex data type that consists of one or more fields.
 * <p>
 * This class provides methods to select and query nested objects by passing a
 * dot {@code "."} delimited {@code String} object (for instance,
 * {@code "aaa.bbb"}). A method evaluates a nested object from left to right,
 * and if a part is {@code null}, it throws {@code NullPointerException}.
 *
 * @since 9
 */
public class RecordedObject {

    static{
        JdkJfrConsumer access = new JdkJfrConsumer() {
            public List<Type> readTypes(RecordingFile file) throws IOException {
                return file.readTypes();
            }

            public boolean isLastEventInChunk(RecordingFile file) {
                return file.isLastEventInChunk();
            }

            @Override
            public Object getOffsetDataTime(RecordedObject event, String name) {
                return event.getOffsetDateTime(name);
            }

            @Override
            public RecordedClass newRecordedClass(ObjectContext objectContext, long id, Object[] values) {
                return new RecordedClass(objectContext, id, values);
            }

            @Override
            public RecordedClassLoader newRecordedClassLoader(ObjectContext objectContext, long id, Object[] values) {
                return new RecordedClassLoader(objectContext, id, values);
            }

            @Override
            public Comparator<? super RecordedEvent> eventComparator() {
                return new Comparator<RecordedEvent>()  {
                    @Override
                    public int compare(RecordedEvent e1, RecordedEvent e2) {
                        return Long.compare(e1.endTimeTicks, e2.endTimeTicks);
                    }
                };
            }

            @Override
            public RecordedStackTrace newRecordedStackTrace(ObjectContext objectContext, Object[] values) {
                return new RecordedStackTrace(objectContext, values);
            }

            @Override
            public RecordedThreadGroup newRecordedThreadGroup(ObjectContext objectContext, Object[] values) {
                return new RecordedThreadGroup(objectContext, values);
            }

            @Override
            public RecordedFrame newRecordedFrame(ObjectContext objectContext, Object[] values) {
                return new RecordedFrame(objectContext, values);
            }

            @Override
            public RecordedThread newRecordedThread(ObjectContext objectContext, long id, Object[] values) {
                return new RecordedThread(objectContext, id, values);
            }

            @Override
            public RecordedMethod newRecordedMethod(ObjectContext objectContext, Object[] values) {
                return new RecordedMethod(objectContext, values);
            }

            @Override
            public RecordedEvent newRecordedEvent(ObjectContext objectContext, Object[] values, long startTimeTicks, long endTimeTicks) {
                return new RecordedEvent(objectContext, values, startTimeTicks, endTimeTicks);
            }

            @Override
            public void setStartTicks(RecordedEvent event, long startTicks) {
               event.startTimeTicks = startTicks;
            }

            @Override
            public void setEndTicks(RecordedEvent event, long endTicks) {
               event.endTimeTicks = endTicks;
            }

            @Override
            public Object[] eventValues(RecordedEvent event) {
                return event.objects;
            }
        };
        JdkJfrConsumer.setAccess(access);
    }

    private final static class UnsignedValue {
        private final Object o;

        UnsignedValue(Object o) {
            this.o = o;
        }

        Object value() {
            return o;
        }
    }

    final Object[] objects;
    final ObjectContext objectContext;

    // package private, not to be subclassed outside this package
    RecordedObject(ObjectContext objectContext, Object[] objects) {
        this.objectContext = objectContext;
        this.objects = objects;
    }

    // package private
    final <T> T getTyped(String name, Class<T> clazz, T defaultValue) {
        // Unnecessary to check field presence twice, but this
        // will do for now.
        if (!hasField(name)) {
            return defaultValue;
        }
        T object = getValue(name);
        if (object == null || object.getClass().isAssignableFrom(clazz)) {
            return object;
        } else {
            return defaultValue;
        }
    }

    /**
     * Returns {@code true} if a field with the given name exists, {@code false}
     * otherwise.
     *
     * @param name name of the field to get, not {@code null}
     *
     * @return {@code true} if the field exists, {@code false} otherwise.
     *
     * @see #getFields()
     */
    public boolean hasField(String name) {
        Objects.requireNonNull(name);
        for (ValueDescriptor v : objectContext.fields) {
            if (v.getName().equals(name)) {
                return true;
            }
        }
        int dotIndex = name.indexOf(".");
        if (dotIndex > 0) {
            String structName = name.substring(0, dotIndex);
            for (ValueDescriptor v : objectContext.fields) {
                if (!v.getFields().isEmpty() && v.getName().equals(structName)) {
                    RecordedObject child = getValue(structName);
                    if (child != null) {
                        return child.hasField(name.substring(dotIndex + 1));
                    }
                }
            }
        }
        return false;
    }

    /**
     * Returns the value of the field with the given name.
     * <p>
     * The return type may be a primitive type or a subclass of
     * {@link RecordedObject}.
     * <p>
     * It's possible to index into a nested object by using {@code "."} (for
     * instance {@code "thread.group.parent.name}").
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     * <p>
     * Example
     *
     * <pre>
     * <code>
     * if (event.hasField("intValue")) {
     *   int intValue = event.getValue("intValue");
     *   System.out.println("Int value: " + intValue);
     * }
     *
     * if (event.hasField("objectClass")) {
     *   RecordedClass clazz = event.getValue("objectClass");
     *   System.out.println("Class name: " + clazz.getName());
     * }
     *
     * if (event.hasField("sampledThread")) {
     *   RecordedThread sampledThread = event.getValue("sampledThread");
     *   System.out.println("Sampled thread: " + sampledThread.getName());
     * }
     * </code>
     * </pre>
     *
     * @param <T> the return type
     * @param  name of the field to get, not {@code null}
     * @throws IllegalArgumentException if no field called {@code name} exists
     *
     * @return the value, can be {@code null}
     *
     * @see #hasField(String)
     *
     */
    final public <T> T getValue(String name) {
        @SuppressWarnings("unchecked")
        T t = (T) getValue(name, false);
        return t;
    }

    protected Object objectAt(int index) {
        return objects[index];
    }

    private Object getValue(String name, boolean allowUnsigned) {
        Objects.requireNonNull(name);
        int index = 0;
        for (ValueDescriptor v : objectContext.fields) {
            if (name.equals(v.getName())) {
                Object object = objectAt(index);
                if (object == null) {
                    // error or missing
                    return null;
                }
                if (v.getFields().isEmpty()) {
                    if (allowUnsigned && PrivateAccess.getInstance().isUnsigned(v)) {
                        // Types that are meaningless to widen
                        if (object instanceof Character || object instanceof Long) {
                            return object;
                        }
                        return new UnsignedValue(object);
                    }
                    return object; // primitives and primitive arrays
                } else {
                    if (object instanceof RecordedObject) {
                        // known types from factory
                        return object;
                    }
                    // must be array type
                    Object[] array = (Object[]) object;
                    if (v.isArray()) {
                        // struct array
                        return structifyArray(v, array, 0);
                    }
                    // struct
                    return new RecordedObject(objectContext.getInstance(v), (Object[]) object);
                }
            }
            index++;
        }

        int dotIndex = name.indexOf(".");
        if (dotIndex > 0) {
            String structName = name.substring(0, dotIndex);
            for (ValueDescriptor v : objectContext.fields) {
                if (!v.getFields().isEmpty() && v.getName().equals(structName)) {
                    RecordedObject child = getValue(structName);
                    String subName = name.substring(dotIndex + 1);
                    if (child != null) {
                        return child.getValue(subName, allowUnsigned);
                    } else {
                        // Call getValueDescriptor to trigger IllegalArgumentException if the name is
                        // incorrect. Type can't be validate due to type erasure
                        getValueDescriptor(v.getFields(), subName, null);
                        throw new NullPointerException("Field value for \"" + structName + "\" was null. Can't access nested field \"" + subName + "\"");
                    }
                }
            }
        }
        throw new IllegalArgumentException("Could not find field with name " + name);
    }

    // Returns the leaf value descriptor matches both name or value, or throws an
    // IllegalArgumentException
    private ValueDescriptor getValueDescriptor(List<ValueDescriptor> descriptors, String name, String leafType) {
        int dotIndex = name.indexOf(".");
        if (dotIndex > 0) {
            String first = name.substring(0, dotIndex);
            String second = name.substring(dotIndex + 1);
            for (ValueDescriptor v : descriptors) {
                if (v.getName().equals(first)) {
                    List<ValueDescriptor> fields = v.getFields();
                    if (!fields.isEmpty()) {
                        return getValueDescriptor(v.getFields(), second, leafType);
                    }
                }
            }
            throw new IllegalArgumentException("Attempt to get unknown field \"" + first + "\"");
        }
        for (ValueDescriptor v : descriptors) {
            if (v.getName().equals(name)) {
                if (leafType != null && !v.getTypeName().equals(leafType)) {
                    throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal data type conversion " + leafType);
                }
                return v;
            }
        }
        throw new IllegalArgumentException("\"Attempt to get unknown field \"" + name + "\"");
    }

    // Gets a value, but checks that type and name is correct first
    // This is to prevent a call to getString on a thread field, that is
    // null to succeed.
    private <T> T getTypedValue(String name, String typeName) {
        Objects.requireNonNull(name);
        // Validate name and type first
        getValueDescriptor(objectContext.fields, name, typeName);
        return getValue(name);
    }

    private Object[] structifyArray(ValueDescriptor v, Object[] array, int dimension) {
        if (array == null) {
            return null;
        }
        Object[] structArray = new Object[array.length];
        ObjectContext objContext = objectContext.getInstance(v);
        for (int i = 0; i < structArray.length; i++) {
            Object arrayElement = array[i];
            if (dimension == 0) {
                // No general way to handle structarrays
                // without invoking ObjectFactory for every instance (which may require id)
                if (isStackFrameType(v.getTypeName())) {
                    structArray[i] = new RecordedFrame(objContext, (Object[]) arrayElement);
                } else {
                    structArray[i] = new RecordedObject(objContext, (Object[]) arrayElement);
                }
            } else {
                structArray[i] = structifyArray(v, (Object[]) arrayElement, dimension - 1);
            }
        }
        return structArray;
    }

    private boolean isStackFrameType(String typeName) {
        if (ObjectFactory.STACK_FRAME_VERSION_1.equals(typeName)) {
            return true;
        }
        if (ObjectFactory.STACK_FRAME_VERSION_2.equals(typeName)) {
            return true;
        }
        return false;
    }

    /**
     * Returns an immutable list of the fields for this object.
     *
     * @return the fields, not {@code null}
     */
    public List<ValueDescriptor> getFields() {
        return objectContext.fields;
    }

    /**
     * Returns the value of a field of type {@code boolean}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name name of the field to get, not {@code null}
     *
     * @return the value of the field, {@code true} or {@code false}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field is
     *         not of type {@code boolean}
     *
     * @see #hasField(String)
     * @see #getValue(String)
     */
    public final boolean getBoolean(String name) {
        Object o = getValue(name);
        if (o instanceof Boolean) {
            return ((Boolean) o).booleanValue();
        }
        throw newIllegalArgumentException(name, "boolean");
    }

    /**
     * Returns the value of a field of type {@code byte}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "foo.bar"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field is
     *         not of type {@code byte}
     *
     * @see #hasField(String)
     * @see #getValue(String)
     */
    public final byte getByte(String name) {
        Object o = getValue(name);
        if (o instanceof Byte) {
            return ((Byte) o).byteValue();
        }
        throw newIllegalArgumentException(name, "byte");
    }

    /**
     * Returns the value of a field of type {@code char}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field as a {@code char}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field is
     *         not of type {@code char}
     *
     * @see #hasField(String)
     * @see #getValue(String)
     */
    public final char getChar(String name) {
        Object o = getValue(name);
        if (o instanceof Character) {
            return ((Character) o).charValue();
        }

        throw newIllegalArgumentException(name, "char");
    }

    /**
     * Returns the value of a field of type {@code short} or of another primitive
     * type convertible to type {@code short} by a widening conversion.
     * <p>
     * This method can be used on the following types: {@code short} and {@code byte}.
     * <p>
     * If the field has the {@code @Unsigned} annotation and is of a narrower type
     * than {@code short}, then the value is returned as an unsigned.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field converted to type {@code short}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         value can't be converted to the type {@code short} by a widening
     *         conversion
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final short getShort(String name) {
        Object o = getValue(name, true);
        if (o instanceof Short) {
            return ((Short) o).shortValue();
        }
        if (o instanceof Byte) {
            return ((Byte) o).byteValue();
        }
        if (o instanceof UnsignedValue) {
            Object u = ((UnsignedValue) o).value();
            if (u instanceof Short) {
                return ((Short) u).shortValue();
            }
            if (u instanceof Byte) {
                return (short) Byte.toUnsignedInt(((Byte) u));
            }
        }
        throw newIllegalArgumentException(name, "short");
    }

    /**
     * Returns the value of a field of type {@code int} or of another primitive type
     * that is convertible to type {@code int} by a widening conversion.
     * <p>
     * This method can be used on fields of the following types: {@code int},
     * {@code short}, {@code char}, and {@code byte}.
     * <p>
     * If the field has the {@code @Unsigned} annotation and is of a narrower type
     * than {@code int}, then the value will be returned as an unsigned.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field converted to type {@code int}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         value can't be converted to the type {@code int} by a widening
     *         conversion
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final int getInt(String name) {
        Object o = getValue(name, true);
        if (o instanceof Integer) {
            return ((Integer) o).intValue();
        }
        if (o instanceof Short) {
            return ((Short) o).intValue();
        }
        if (o instanceof Character) {
            return ((Character) o).charValue();
        }
        if (o instanceof Byte) {
            return ((Byte) o).intValue();
        }
        if (o instanceof UnsignedValue) {
            Object u = ((UnsignedValue) o).value();
            if (u instanceof Integer) {
                return ((Integer) u).intValue();
            }
            if (u instanceof Short) {
                return Short.toUnsignedInt(((Short) u));
            }
            if (u instanceof Byte) {
                return Byte.toUnsignedInt(((Byte) u));
            }
        }
        throw newIllegalArgumentException(name, "int");
    }

    /**
     * Returns the value of a field of type {@code float} or of another primitive
     * type convertible to type {@code float} by a widening conversion.
     * <p>
     * This method can be used on fields of the following types: {@code float},
     * {@code long}, {@code int}, {@code short}, {@code char}, and {@code byte}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field converted to type {@code float}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         value can't be converted to the type {@code float} by a widening
     *         conversion
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final float getFloat(String name) {
        Object o = getValue(name);
        if (o instanceof Float) {
            return ((Float) o).floatValue();
        }
        if (o instanceof Long) {
            return ((Long) o).floatValue();
        }
        if (o instanceof Integer) {
            return ((Integer) o).floatValue();
        }
        if (o instanceof Short) {
            return ((Short) o).floatValue();
        }
        if (o instanceof Byte) {
            return ((Byte) o).byteValue();
        }
        if (o instanceof Character) {
            return ((Character) o).charValue();
        }
        throw newIllegalArgumentException(name, "float");
    }

    /**
     * Returns the value of a field of type {@code long} or of another primitive
     * type that is convertible to type {@code long} by a widening conversion.
     * <p>
     * This method can be used on fields of the following types: {@code long},
     * {@code int}, {@code short}, {@code char}, and {@code byte}.
     * <p>
     * If the field has the {@code @Unsigned} annotation and is of a narrower type
     * than {@code long}, then the value will be returned as an unsigned.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field converted to type {@code long}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         value can't be converted to the type {@code long} via a widening
     *         conversion
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final long getLong(String name) {
        Object o = getValue(name, true);
        if (o instanceof Long) {
            return ((Long) o).longValue();
        }
        if (o instanceof Integer) {
            return ((Integer) o).longValue();
        }
        if (o instanceof Short) {
            return ((Short) o).longValue();
        }
        if (o instanceof Character) {
            return ((Character) o).charValue();
        }
        if (o instanceof Byte) {
            return ((Byte) o).longValue();
        }
        if (o instanceof UnsignedValue) {
            Object u = ((UnsignedValue) o).value();
            if (u instanceof Integer) {
                return Integer.toUnsignedLong(((Integer) u));
            }
            if (u instanceof Short) {
                return Short.toUnsignedLong(((Short) u));
            }
            if (u instanceof Byte) {
                return Byte.toUnsignedLong(((Byte) u));
            }
        }
        throw newIllegalArgumentException(name, "long");
    }

    /**
     * Returns the value of a field of type {@code double} or of another primitive
     * type that is convertible to type {@code double} by a widening conversion.
     * <p>
     * This method can be used on fields of the following types: {@code double}, {@code float},
     * {@code long}, {@code int}, {@code short}, {@code char}, and {@code byte}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field converted to type {@code double}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         value can't be converted to the type {@code double} by a widening
     *         conversion
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final double getDouble(String name) {
        Object o = getValue(name);
        if (o instanceof Double) {
            return ((Double) o).doubleValue();
        }
        if (o instanceof Float) {
            return ((Float) o).doubleValue();
        }
        if (o instanceof Long) {
            return ((Long) o).doubleValue();
        }
        if (o instanceof Integer) {
            return ((Integer) o).doubleValue();
        }
        if (o instanceof Short) {
            return ((Short) o).doubleValue();
        }
        if (o instanceof Byte) {
            return ((Byte) o).byteValue();
        }
        if (o instanceof Character) {
            return ((Character) o).charValue();
        }
        throw newIllegalArgumentException(name, "double");
    }

    /**
     * Returns the value of a field of type {@code String}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "foo.bar"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field as a {@code String}, can be {@code null}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         isn't of type {@code String}
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final String getString(String name) {
        return getTypedValue(name, "java.lang.String");
    }

    /**
     * Returns the value of a timespan field.
     * <p>
     * This method can be used on fields annotated with {@code @Timespan}, and of
     * the following types: {@code long}, {@code int}, {@code short}, {@code char},
     * and {@code byte}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return a time span represented as a {@code Duration}, not {@code null}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         value can't be converted to a {@code Duration} object
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final Duration getDuration(String name) {
        Object o = getValue(name);
        if (o instanceof Long) {
            return getDuration(((Long) o).longValue(), name);
        }
        if (o instanceof Integer) {
            return getDuration(((Integer) o).longValue(), name);
        }
        if (o instanceof Short) {
            return getDuration(((Short) o).longValue(), name);
        }
        if (o instanceof Character) {
            return getDuration(((Character) o).charValue(), name);
        }
        if (o instanceof Byte) {
            return getDuration(((Byte) o).longValue(), name);
        }
        if (o instanceof UnsignedValue) {
            Object u = ((UnsignedValue) o).value();
            if (u instanceof Integer) {
                return getDuration(Integer.toUnsignedLong((Integer) u), name);
            }
            if (u instanceof Short) {
                return getDuration(Short.toUnsignedLong((Short) u), name);
            }
            if (u instanceof Byte) {
                return getDuration(Short.toUnsignedLong((Byte) u), name);
            }
        }
        throw newIllegalArgumentException(name, "java,time.Duration");
    }

    private Duration getDuration(long timespan, String name) throws InternalError {
        ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null);
        if (timespan == Long.MIN_VALUE) {
            return Duration.ofSeconds(Long.MIN_VALUE, 0);
        }
        Timespan ts = v.getAnnotation(Timespan.class);
        if (ts != null) {
            switch (ts.value()) {
            case Timespan.MICROSECONDS:
                return Duration.ofNanos(1000 * timespan);
            case Timespan.SECONDS:
                return Duration.ofSeconds(timespan);
            case Timespan.MILLISECONDS:
                return Duration.ofMillis(timespan);
            case Timespan.NANOSECONDS:
                return Duration.ofNanos(timespan);
            case Timespan.TICKS:
                return Duration.ofNanos(objectContext.convertTimespan(timespan));
            }
            throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timespan unit " + ts.value());
        }
        throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with missing @Timespan");
    }

    /**
     * Returns the value of a timestamp field.
     * <p>
     * This method can be used on fields annotated with {@code @Timestamp}, and of
     * the following types: {@code long}, {@code int}, {@code short}, {@code char}
     * and {@code byte}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return a timstamp represented as an {@code Instant}, not {@code null}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         value can't be converted to an {@code Instant} object
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final Instant getInstant(String name) {
        Object o = getValue(name, true);
        if (o instanceof Long) {
            return getInstant(((Long) o).longValue(), name);
        }
        if (o instanceof Integer) {
            return getInstant(((Integer) o).longValue(), name);
        }
        if (o instanceof Short) {
            return getInstant(((Short) o).longValue(), name);
        }
        if (o instanceof Character) {
            return getInstant(((Character) o).charValue(), name);
        }
        if (o instanceof Byte) {
            return getInstant(((Byte) o).longValue(), name);
        }
        if (o instanceof UnsignedValue) {
            Object u = ((UnsignedValue) o).value();
            if (u instanceof Integer) {
                return getInstant(Integer.toUnsignedLong((Integer) u), name);
            }
            if (u instanceof Short) {
                return getInstant(Short.toUnsignedLong((Short) u), name);
            }
            if (u instanceof Byte) {
                return getInstant(Short.toUnsignedLong((Byte) u), name);
            }
        }
        throw newIllegalArgumentException(name, "java.time.Instant");
    }

    private Instant getInstant(long timestamp, String name) {
        ValueDescriptor v = getValueDescriptor(objectContext.fields, name, null);
        Timestamp ts = v.getAnnotation(Timestamp.class);
        if (ts != null) {
            if (timestamp == Long.MIN_VALUE) {
                return Instant.MIN;
            }
            switch (ts.value()) {
            case Timestamp.MILLISECONDS_SINCE_EPOCH:
                return Instant.ofEpochMilli(timestamp);
            case Timestamp.TICKS:
                return Instant.ofEpochSecond(0, objectContext.convertTimestamp(timestamp));
            }
            throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with illegal timestamp unit " + ts.value());
        }
        throw new IllegalArgumentException("Attempt to get " + v.getTypeName() + " field \"" + name + "\" with missing @Timestamp");
    }

    /**
     * Returns the value of a field of type {@code Class}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "aaa.bbb"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field as a {@code RecordedClass}, can be
     *         {@code null}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         isn't of type {@code Class}
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final RecordedClass getClass(String name) {
        return getTypedValue(name, "java.lang.Class");
    }

    /**
     * Returns the value of a field of type {@code Thread}.
     * <p>
     * It's possible to index into a nested object using {@code "."} (for example,
     * {@code "foo.bar"}).
     * <p>
     * A field might change or be removed in a future JDK release. A best practice
     * for callers of this method is to validate the field before attempting access.
     *
     * @param name of the field to get, not {@code null}
     *
     * @return the value of the field as a {@code RecordedThread} object, can be
     *         {@code null}
     *
     * @throws IllegalArgumentException if the field doesn't exist, or the field
     *         isn't of type {@code Thread}
     *
     * @see #hasField(String)
     * @set #getValue(String)
     */
    public final RecordedThread getThread(String name) {
        return getTypedValue(name, "java.lang.Thread");
    }

    /**
     * Returns a textual representation of this object.
     *
     * @return textual description of this object
     */
    @Override
    final public String toString() {
        StringWriter s = new StringWriter();
        PrettyWriter p = new PrettyWriter(new PrintWriter(s));
        p.setStackDepth(5);
        if (this instanceof RecordedEvent) {
            p.print((RecordedEvent) this);
        } else {
            p.print(this, "");
        }
        p.flush(true);
        return s.toString();
    }

    // package private for now. Used by EventWriter
    private OffsetDateTime getOffsetDateTime(String name) {
        Instant instant = getInstant(name);
        if (instant.equals(Instant.MIN)) {
            return OffsetDateTime.MIN;
        }
        return OffsetDateTime.ofInstant(getInstant(name), objectContext.getZoneOffset());
    }

    private static IllegalArgumentException newIllegalArgumentException(String name, String typeName) {
        return new IllegalArgumentException("Attempt to get field \"" + name + "\" with illegal data type conversion " + typeName);
    }
}
