/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "modules/indexeddb/IDBAny.h"

#include "core/dom/DOMStringList.h"
#include "modules/indexeddb/IDBCursorWithValue.h"
#include "modules/indexeddb/IDBDatabase.h"
#include "modules/indexeddb/IDBFactory.h"
#include "modules/indexeddb/IDBIndex.h"
#include "modules/indexeddb/IDBKeyPath.h"
#include "modules/indexeddb/IDBObjectStore.h"

namespace WebCore {

PassRefPtr<IDBAny> IDBAny::createInvalid()
{
    return adoptRef(new IDBAny(UndefinedType));
}

PassRefPtr<IDBAny> IDBAny::createNull()
{
    return adoptRef(new IDBAny(NullType));
}

PassRefPtr<IDBAny> IDBAny::createString(const String& value)
{
    return adoptRef(new IDBAny(value));
}

IDBAny::IDBAny(Type type)
    : m_type(type)
    , m_integer(0)
{
    ASSERT(type == UndefinedType || type == NullType);
}

IDBAny::~IDBAny()
{
}

DOMStringList* IDBAny::domStringList()
{
    ASSERT(m_type == DOMStringListType);
    return m_domStringList.get();
}

IDBCursor* IDBAny::idbCursor()
{
    ASSERT(m_type == IDBCursorType);
    return m_idbCursor.get();
}

IDBCursorWithValue* IDBAny::idbCursorWithValue()
{
    ASSERT(m_type == IDBCursorWithValueType);
    return m_idbCursorWithValue.get();
}

IDBDatabase* IDBAny::idbDatabase()
{
    ASSERT(m_type == IDBDatabaseType);
    return m_idbDatabase.get();
}

IDBFactory* IDBAny::idbFactory()
{
    ASSERT(m_type == IDBFactoryType);
    return m_idbFactory.get();
}

IDBIndex* IDBAny::idbIndex()
{
    ASSERT(m_type == IDBIndexType);
    return m_idbIndex.get();
}

IDBObjectStore* IDBAny::idbObjectStore()
{
    ASSERT(m_type == IDBObjectStoreType);
    return m_idbObjectStore.get();
}

IDBTransaction* IDBAny::idbTransaction()
{
    ASSERT(m_type == IDBTransactionType);
    return m_idbTransaction.get();
}

const ScriptValue& IDBAny::scriptValue()
{
    ASSERT(m_type == ScriptValueType);
    return m_scriptValue;
}

const String& IDBAny::string()
{
    ASSERT(m_type == StringType);
    return m_string;
}

int64_t IDBAny::integer()
{
    ASSERT(m_type == IntegerType);
    return m_integer;
}

IDBAny::IDBAny(PassRefPtr<DOMStringList> value)
    : m_type(DOMStringListType)
    , m_domStringList(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(PassRefPtr<IDBCursorWithValue> value)
    : m_type(IDBCursorWithValueType)
    , m_idbCursorWithValue(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(PassRefPtr<IDBCursor> value)
    : m_type(IDBCursorType)
    , m_idbCursor(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(PassRefPtr<IDBDatabase> value)
    : m_type(IDBDatabaseType)
    , m_idbDatabase(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(PassRefPtr<IDBFactory> value)
    : m_type(IDBFactoryType)
    , m_idbFactory(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(PassRefPtr<IDBIndex> value)
    : m_type(IDBIndexType)
    , m_idbIndex(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(PassRefPtr<IDBTransaction> value)
    : m_type(IDBTransactionType)
    , m_idbTransaction(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(PassRefPtr<IDBObjectStore> value)
    : m_type(IDBObjectStoreType)
    , m_idbObjectStore(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(const ScriptValue& value)
    : m_type(ScriptValueType)
    , m_scriptValue(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(const IDBKeyPath& value)
    : m_type(KeyPathType)
    , m_idbKeyPath(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(const String& value)
    : m_type(StringType)
    , m_string(value)
    , m_integer(0)
{
}

IDBAny::IDBAny(int64_t value)
    : m_type(IntegerType)
    , m_integer(value)
{
}

} // namespace WebCore
