/*
* Copyright (c) 2002-2017 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.driver.v1;
import java.util.List;
import java.util.Map;
import org.neo4j.driver.v1.exceptions.ClientException;
import org.neo4j.driver.v1.exceptions.value.LossyCoercion;
import org.neo4j.driver.v1.exceptions.value.Uncoercible;
import org.neo4j.driver.v1.types.Entity;
import org.neo4j.driver.v1.types.MapAccessor;
import org.neo4j.driver.v1.types.MapAccessorWithDefaultValue;
import org.neo4j.driver.v1.types.Node;
import org.neo4j.driver.v1.types.Path;
import org.neo4j.driver.v1.types.Relationship;
import org.neo4j.driver.v1.types.Type;
import org.neo4j.driver.v1.types.TypeSystem;
import org.neo4j.driver.v1.util.Experimental;
import org.neo4j.driver.v1.util.Function;
import org.neo4j.driver.v1.util.Immutable;
/**
* A unit of data that adheres to the Neo4j type system.
*
* This interface describes a number of <code>isType</code> methods along with
* <code>typeValue</code> methods. The first set of these correlate with types from
* the Neo4j Type System and are used to determine which Neo4j type is represented.
* The second set of methods perform coercions to Java types (wherever possible).
* For example, a common String value should be tested for using <code>isString</code>
* and extracted using <code>stringValue</code>.
*
* <h2>Navigating a tree structure</h2>
*
* Because Neo4j often handles dynamic structures, this interface is designed to help
* you handle such structures in Java. Specifically, {@link Value} lets you navigate arbitrary tree
* structures without having to resort to type casting.
*
* Given a tree structure like:
*
* <pre>
* {@code
* {
* users : [
* { name : "Anders" },
* { name : "John" }
* ]
* }
* }
* </pre>
*
* You can retrieve the name of the second user, John, like so:
*
* <pre class="docTest:ValueDocIT#classDocTreeExample">
* {@code
* String username = value.get("users").get(1).get("name").asString();
* }
* </pre>
*
* You can also easily iterate over the users:
*
* <pre class="docTest:ValueDocIT#classDocIterationExample">
* {@code
* List<String> names = new LinkedList<>();
* for(Value user : value.get("users").values() )
* {
* names.add(user.get("name").asString());
* }
* }
* </pre>
* @since 1.0
*/
@Immutable
public interface Value extends MapAccessor, MapAccessorWithDefaultValue
{
/**
* If the underlying value is a collection type, return the number of values in the collection.
* <p>
* For {@link TypeSystem#LIST()} list} values, this will return the size of the list.
* <p>
* For {@link TypeSystem#MAP() map} values, this will return the number of entries in the map.
* <p>
* For {@link TypeSystem#NODE() node} and {@link TypeSystem#RELATIONSHIP()} relationship} values,
* this will return the number of properties.
* <p>
* For {@link TypeSystem#PATH() path} values, this returns the length (number of relationships) in the path.
*
* @return the number of values in an underlying collection
*/
int size();
/**
* If this value represents a list or map, test if the collection is empty.
*
* @return <tt>true</tt> if size() is 0, otherwise <tt>false</tt>
*/
boolean isEmpty();
/**
* If the underlying value supports {@link #get(String) key-based indexing}, return an iterable of the keys in the
* map, this applies to {@link TypeSystem#MAP() map}, {@link #asNode() node} and {@link
* TypeSystem#RELATIONSHIP()} relationship} values.
*
* @return the keys in the value
*/
@Override
Iterable<String> keys();
/**
* Retrieve the value at the given index
*
* @param index the index of the value
* @return the value or a {@link org.neo4j.driver.internal.value.NullValue} if the index is out of bounds
* @throws ClientException if record has not been initialized
*/
Value get( int index );
/** @return The type of this value as defined in the Neo4j type system */
@Experimental
Type type();
/**
* Test if this value is a value of the given type
*
* @param type the given type
* @return type.isTypeOf( this )
*/
@Experimental
boolean hasType( Type type );
/**
* @return <tt>true</tt> if the value is a Boolean value and has the value True.
*/
boolean isTrue();
/**
* @return <tt>true</tt> if the value is a Boolean value and has the value False.
*/
boolean isFalse();
/**
* @return <tt>true</tt> if the value is a Null, otherwise <tt>false</tt>
*/
boolean isNull();
/**
* This returns a java standard library representation of the underlying value,
* using a java type that is "sensible" given the underlying type. The mapping
* for common types is as follows:
*
* <ul>
* <li>{@link TypeSystem#INTEGER()} - {@link Long}</li>
* <li>{@link TypeSystem#FLOAT()} - {@link Double}</li>
* <li>{@link TypeSystem#NUMBER()} - {@link Number}</li>
* <li>{@link TypeSystem#STRING()} - {@link String}</li>
* <li>{@link TypeSystem#BOOLEAN()} - {@link Boolean}</li>
* <li>{@link TypeSystem#NULL()} - {@code null}</li>
* <li>{@link TypeSystem#NODE()} - {@link Node}</li>
* <li>{@link TypeSystem#RELATIONSHIP()} - {@link Relationship}</li>
* <li>{@link TypeSystem#PATH()} - {@link Path}</li>
* <li>{@link TypeSystem#MAP()} - {@link Map}</li>
* <li>{@link TypeSystem#LIST()} - {@link List}</li>
* </ul>
*
* Note that the types in {@link TypeSystem} refers to the Neo4j type system
* where {@link TypeSystem#INTEGER()} and {@link TypeSystem#FLOAT()} are both
* 64-bit precision. This is why these types return java {@link Long} and
* {@link Double}, respectively.
*
* @return the value as a Java Object
*/
Object asObject();
/**
* @return the value as a Java boolean, if possible.
* @throws Uncoercible if value types are incompatible.
*/
boolean asBoolean();
/**
* @return the value as a Java String, if possible.
* @throws Uncoercible if value types are incompatible.
*/
String asString();
/**
* @return the value as a Java Number, if possible.
* @throws Uncoercible if value types are incompatible.
*/
Number asNumber();
/**
* Returns a Java long if no precision is lost in the conversion.
*
* @return the value as a Java long.
* @throws LossyCoercion if it is not possible to convert the value without loosing precision.
* @throws Uncoercible if value types are incompatible.
*/
long asLong();
/**
* Returns a Java int if no precision is lost in the conversion.
*
* @return the value as a Java int.
* @throws LossyCoercion if it is not possible to convert the value without loosing precision.
* @throws Uncoercible if value types are incompatible.
*/
int asInt();
/**
* Returns a Java double if no precision is lost in the conversion.
*
* @return the value as a Java double.
* @throws LossyCoercion if it is not possible to convert the value without loosing precision.
* @throws Uncoercible if value types are incompatible.
*/
double asDouble();
/**
* Returns a Java float if no precision is lost in the conversion.
*
* @return the value as a Java float.
* @throws LossyCoercion if it is not possible to convert the value without loosing precision.
* @throws Uncoercible if value types are incompatible.
*/
float asFloat();
/**
* If the underlying type can be viewed as a list, returns a java list of
* values, where each value has been converted using {@link #asObject()}.
*
* @see #asObject()
* @return the value as a Java list of values, if possible
*/
List<Object> asList();
/**
* @param mapFunction a function to map from Value to T. See {@link Values} for some predefined functions, such
* as {@link Values#ofBoolean()}, {@link Values#ofList(Function)}.
* @param <T> the type of target list elements
* @see Values for a long list of built-in conversion functions
* @return the value as a list of T obtained by mapping from the list elements, if possible
*/
<T> List<T> asList( Function<Value, T> mapFunction );
/**
* @return the value as a {@link Entity}, if possible.
* @throws Uncoercible if value types are incompatible.
*/
Entity asEntity();
/**
* @return the value as a {@link Node}, if possible.
* @throws Uncoercible if value types are incompatible.
*/
Node asNode();
/**
* @return the value as a {@link Relationship}, if possible.
* @throws Uncoercible if value types are incompatible.
*/
Relationship asRelationship();
/**
* @return the value as a {@link Path}, if possible.
* @throws Uncoercible if value types are incompatible.
*/
Path asPath();
// Force implementation
@Override
boolean equals( Object other );
// Force implementation
@Override
int hashCode();
//Force implementation
@Override
String toString();
}