package net.ranides.assira.grammar.properties;

import net.ranides.assira.functional.Functions.Function2;
import net.ranides.assira.grammar.G4Node;
import net.ranides.assira.trace.PreparedException;

import java.util.NoSuchElementException;

/**
 * Typesafe key used to retrieve properties from nodes.
 * You can store any object and retrieve it by name, or you can use G4NodeProperty and avoid explicit type casting.
 *
 * @param <V> type of value stored in property
 */
public class G4NodeProperty<V> {

    private static final Function2<String, G4Node, NoSuchElementException> REQUIRED = PreparedException
        .runtime(NoSuchElementException.class)
        .message("Required property: {0} for tree: {1}")
        .params()
        .withParam(String.class)
        .withParam((G4Node node) -> node.path())
        .function();

    private final Class<V> type;

    private final String name;

    private G4NodeProperty(Class<V> type, String name) {
        this.type = type;
        this.name = name;
    }

    public static <V> G4NodeProperty<V> of(Class<V> type, String name) {
        return new G4NodeProperty<>(type, name);
    }

    public static G4NodeProperty<Object> of(String name) {
        return new G4NodeProperty<>(Object.class, name);
    }

    public Class<V> type() {
        return type;
    }

    public String name() {
        return name;
    }
}
