/*
* Copyright (C) 2012 Facebook, Inc.
*
* 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 com.facebook.data.types;
/**
* A Datum is meant to be as generic as possible. It presents both the data
* itself along with methods to inspect attributes (getType, isNull). The
* idea is to cover all primitives and make lists and maps easy, and any
* arbitrary extensions possible.
*
* The definition of asBoolean() for say, a MapDatum, will be defined by that
* class. It may choose to throw an UnssupportedOperationException, or to
* return true if the map is not empty. Read each impl's documentation.
*
* Certainly, if the underlying impl is a BooleanDatum, asBoolean()
* should return true/false accordingly
*
* Onte note: unless otherwise stated, implementations need NOT be thread safe
*/
public interface Datum extends Comparable<Datum> {
/**
* all as*() methods will make a best effort to return the underlying Datum as the requested type
*
* ex:
*
* <pre>
* IntegerDatum fuu = ...;
* String bar = fuu.asString(); // no reason this should fail
*
* StringDatum s = ...;
* IntegerDatum n = s.asInteger(); // might throw NumberFormatException
*
* Currently, one helper method exists:
*
* {@link DatumType#isLongCompatible(Datum)} which tells you if the type is something such
* that asLong() will succeed (obviously includes long, int, short, byte, bool, and some other
* special cases)
*
* Users may write their own condition that asserts the valid DatumTypes for their conversion
* based on their data (ex: they know all String data is numeric)
*
* one OPTIONAL TODO: add method canBeX() or something that encapsulates logic.
*
* StringDatum can look at the chars and see if they are [0-9] for integers (longs) when
* asked canBeIneger()
* or canBeDouble() would check for canBeInteger() || (match X\.Y)
*
* or something similar. Possible future work to give users to avoid exceptions if they
* don't mind adding precondition statements
* </pre>
*
* @return
*/
boolean asBoolean();
byte asByte();
short asShort();
int asInteger();
long asLong();
float asFloat();
double asDouble();
String asString();
/**
* what this returns really doesn't matter. It need only be deterministic
* so that MurmurHash can take it as input and hash. It should probably
* also be fast to make distinct counting fast
*
* many Datums don't yet implement this
* @return
*/
byte[] asBytes();
/**
* should be equivalent to
*
* <pre>
* datum.getType() == DatumType.NULL
* </pre>
*
* kept for historical and conciseness reasons
*
* @return
*/
boolean isNull();
/**
* see {@link DatumType} for a list of valid values
* @returns
*/
DatumType getType();
/**
* currently a loose contract that will return whatever "raw" object the Datum is wrapping.
* This is intuitive with primitives, and probably so with Lists and Maps. Each implmentation
* wiil document it's asRaw() as it sees fit
*
* @return
*/
Object asRaw();
}