/*
* Copyright 2010 Outerthought bvba
*
* 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.lilyproject.repository.api;
import java.util.Comparator;
import java.util.Set;
import org.lilyproject.bytes.api.DataInput;
import org.lilyproject.bytes.api.DataOutput;
/**
* A value type represents the type of the value of a {@link FieldType}.
*
* <p>
* It represents a particular kind of value like a String, Long, ...
*
* <p>
* Value types exist also to represent java.util.List (ListValueType) and
* {@link HierarchyPath} (PathValueType) which can contain values of another
* value type including ListValueType and PathValueType again thus allowing
* multiple levels of nesting.</br>
*
* <p>
* A value type to represent a Record also exists. This record is used to
* represent what is also known as a complex type. It can be regarded as normal
* Record, but with a few restrictions:
* <ul>
* <li>It has no version</li>
* <li>It has one (non-versioned) record type, and all its fields must be
* defined in that record type</li>
* <li>All its fields are non-versioned</li>
* <li>It is stored in its entirety inside a field of the surrounding record</li>
* <li>Blob fields are not allowed</li>
* </ul>
*
* <p>
* It is the responsibility of a ValueType to convert the values to/from byte
* representation, as used for storage in the repository. See the methods
* {@link #write(Object, org.lilyproject.bytes.api.DataOutput, IdentityRecordStack)}
* and {@link #read(org.lilyproject.bytes.api.DataInput)}.
*
* <p>
* Value types are retrieved from the {@link TypeManager} using the
* method {@link TypeManager#getValueType(String)}. A name (e.g.
* "STRING") uniquely represents the value type, and some value types can
* include extra information (typeParams) defining the value type. For example
* to define a list should contain strings.
* See the javadoc of that method for the complete list of supported value types
* and the parameters needed to get an instance of them.
*
*/
public interface ValueType {
/**
* Read and decodes object of the type represented by this value type from a {@link DataInput}.
*
* @param dataInput the DataInput from which the valueType should read and decode its data
*
* @throws UnknownValueTypeEncodingException if the version of the encoding stored within the
* input data is not supported.
*/
<T> T read(DataInput dataInput) throws RepositoryException, InterruptedException;
<T> T read(byte[] data) throws RepositoryException, InterruptedException;
/**
* Encodes an object of the type represented by this value type to a
* {@link DataOutput}.
*
* @param value
* the object to encode and write
* @param dataOutput
* the DataOutput on which to write the data
* @param parentRecords
* a stack of parentRecords to check for self-nested
* records.
*/
void write(Object value, DataOutput dataOutput, IdentityRecordStack parentRecords)
throws RepositoryException, InterruptedException;
/**
* Encodes an object of the type represented by this value type to a byte[].
*
* <p>Should only be used internally for Avro data transport.
*
*/
byte[] toBytes(Object value, IdentityRecordStack parentRecords) throws RepositoryException,
InterruptedException;
/**
* Returns the Java class for the values of this value type.
*
* <p>
* For example: java.util.List or java.lang.String
*/
Class getType();
/**
* Returns a set of all values contained in this value.
*
* <p>
* In case of a ListValueType or PathValueType, these are the nested values.
*/
Set<Object> getValues(Object value);
public int hashCode();
boolean equals(Object obj);
/**
* A comparator that can compare the values corresponding to this value type.
*
* <p>If comparing values is not supported, null is returned.</p>
*
* <p>This method should be lightweight to call, so preferably return the same instance on each invocation.</p>
*/
Comparator getComparator();
/**
* @return the base name of the value type (e.g. "STRING") without any extra parameters for the type.
* See {@link TypeManager#getValueType(String)} for a list of all possible value types and their names.
*/
String getBaseName();
/**
* @return the name of the value type where the optional parameters of the type are
* enclosed in "<>" after the simple name. For example: "LIST<STRING>"
*/
String getName();
/**
* ListValueType and PathValueType can again contain other value types.
*
* <p>
* This method returns the nested value type (1 level deep) or null if it
* is not a ListValueType or PathValueType.
*/
ValueType getNestedValueType();
/**
* ListValueType and PathValueType can again contain other value types.
*
* <p>
* This method returns the deepest level (non List or Path) value type,
* or the current value type if it is not a list or path.
*/
ValueType getDeepestValueType();
/**
* ListValueType and PathValueType can again contain other value types.
*
* <p>
* This method returns the number of nesting levels until the base value
* type is reached. For non List or Path value types the returned value is 1.
*
* <p>
* This method is used by the Repository and BlobIncubator when checking if
* a blob is already used by the record.
*/
int getNestingLevel();
/**
* @deprecated Use {@link #getBaseName()}.equals("LIST") instead.
*
* @return true in case of a ListValueType, false in all other cases.
*/
boolean isMultiValue();
/**
* @deprecated Use {@link #getBaseName()}.equals("PATH") or
* {@link #getNestedValueType()}.{@link #getBaseName()}.equals("PATH") instead.
*
* @return true in case of a PathValueType or if a PathValueType is nested in a ListValueType
*/
boolean isHierarchical();
}