// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file has been auto-generated by code_generator_v8.py. DO NOT MODIFY!

#include "config.h"
#include "bindings/core/v8/UnionTypesCore.h"

#include "bindings/core/v8/V8Node.h"
#include "bindings/core/v8/V8NodeList.h"
#include "bindings/core/v8/V8TestDictionary.h"
#include "bindings/core/v8/V8TestInterface.h"
#include "bindings/core/v8/V8TestInterfaceEmpty.h"
#include "bindings/core/v8/V8TestInterfaceGarbageCollected.h"
#include "bindings/core/v8/V8TestInterfaceWillBeGarbageCollected.h"
#include "bindings/tests/idls/core/TestImplements2.h"
#include "bindings/tests/idls/core/TestImplements3Implementation.h"
#include "bindings/tests/idls/core/TestPartialInterface.h"
#include "bindings/tests/idls/core/TestPartialInterfaceImplementation.h"
#include "core/dom/NameNodeList.h"
#include "core/dom/NodeList.h"
#include "core/dom/StaticNodeList.h"
#include "core/html/LabelsNodeList.h"

namespace blink {

BooleanOrStringOrUnrestrictedDouble::BooleanOrStringOrUnrestrictedDouble()
    : m_type(SpecificTypeNone)
{
}

bool BooleanOrStringOrUnrestrictedDouble::getAsBoolean()
{
    ASSERT(isBoolean());
    return m_boolean;
}

void BooleanOrStringOrUnrestrictedDouble::setBoolean(bool value)
{
    ASSERT(isNull());
    m_boolean = value;
    m_type = SpecificTypeBoolean;
}

String BooleanOrStringOrUnrestrictedDouble::getAsString()
{
    ASSERT(isString());
    return m_string;
}

void BooleanOrStringOrUnrestrictedDouble::setString(String value)
{
    ASSERT(isNull());
    m_string = value;
    m_type = SpecificTypeString;
}

double BooleanOrStringOrUnrestrictedDouble::getAsUnrestrictedDouble()
{
    ASSERT(isUnrestrictedDouble());
    return m_unrestrictedDouble;
}

void BooleanOrStringOrUnrestrictedDouble::setUnrestrictedDouble(double value)
{
    ASSERT(isNull());
    m_unrestrictedDouble = value;
    m_type = SpecificTypeUnrestrictedDouble;
}

void V8BooleanOrStringOrUnrestrictedDouble::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, BooleanOrStringOrUnrestrictedDouble& impl, ExceptionState& exceptionState)
{
    if (v8Value.IsEmpty())
        return;

    if (v8Value->IsBoolean()) {
        impl.setBoolean(v8Value->ToBoolean()->Value());
        return;
    }

    if (v8Value->IsNumber()) {
        TONATIVE_VOID_EXCEPTIONSTATE(double, cppValue, toDouble(v8Value, exceptionState), exceptionState);
        impl.setUnrestrictedDouble(cppValue);
        return;
    }

    {
        TOSTRING_VOID_EXCEPTIONSTATE(V8StringResource<>, cppValue, v8Value, exceptionState);
        impl.setString(cppValue);
        return;
    }

    exceptionState.throwTypeError("Not a valid union member.");
}

v8::Handle<v8::Value> toV8(BooleanOrStringOrUnrestrictedDouble& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    if (impl.isNull())
        return v8::Null(isolate);

    if (impl.isBoolean())
        return v8Boolean(impl.getAsBoolean(), isolate);

    if (impl.isString())
        return v8String(isolate, impl.getAsString());

    if (impl.isUnrestrictedDouble())
        return v8::Number::New(isolate, impl.getAsUnrestrictedDouble());

    ASSERT_NOT_REACHED();
    return v8::Handle<v8::Value>();
}

NodeOrNodeList::NodeOrNodeList()
    : m_type(SpecificTypeNone)
{
}

PassRefPtrWillBeRawPtr<Node> NodeOrNodeList::getAsNode()
{
    ASSERT(isNode());
    return m_node;
}

void NodeOrNodeList::setNode(PassRefPtrWillBeRawPtr<Node> value)
{
    ASSERT(isNull());
    m_node = value;
    m_type = SpecificTypeNode;
}

PassRefPtrWillBeRawPtr<NodeList> NodeOrNodeList::getAsNodeList()
{
    ASSERT(isNodeList());
    return m_nodeList;
}

void NodeOrNodeList::setNodeList(PassRefPtrWillBeRawPtr<NodeList> value)
{
    ASSERT(isNull());
    m_nodeList = value;
    m_type = SpecificTypeNodeList;
}

void NodeOrNodeList::trace(Visitor* visitor)
{
    visitor->trace(m_node);
    visitor->trace(m_nodeList);
}

void V8NodeOrNodeList::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, NodeOrNodeList& impl, ExceptionState& exceptionState)
{
    if (v8Value.IsEmpty())
        return;

    if (V8Node::hasInstance(v8Value, isolate)) {
        RefPtrWillBeRawPtr<Node> cppValue = V8Node::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
        impl.setNode(cppValue);
        return;
    }

    if (V8NodeList::hasInstance(v8Value, isolate)) {
        RefPtrWillBeRawPtr<NodeList> cppValue = V8NodeList::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
        impl.setNodeList(cppValue);
        return;
    }

    exceptionState.throwTypeError("Not a valid union member.");
}

v8::Handle<v8::Value> toV8(NodeOrNodeList& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    if (impl.isNull())
        return v8::Null(isolate);

    if (impl.isNode())
        return toV8(impl.getAsNode(), creationContext, isolate);

    if (impl.isNodeList())
        return toV8(impl.getAsNodeList(), creationContext, isolate);

    ASSERT_NOT_REACHED();
    return v8::Handle<v8::Value>();
}

StringOrDouble::StringOrDouble()
    : m_type(SpecificTypeNone)
{
}

String StringOrDouble::getAsString()
{
    ASSERT(isString());
    return m_string;
}

void StringOrDouble::setString(String value)
{
    ASSERT(isNull());
    m_string = value;
    m_type = SpecificTypeString;
}

double StringOrDouble::getAsDouble()
{
    ASSERT(isDouble());
    return m_double;
}

void StringOrDouble::setDouble(double value)
{
    ASSERT(isNull());
    m_double = value;
    m_type = SpecificTypeDouble;
}

void V8StringOrDouble::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, StringOrDouble& impl, ExceptionState& exceptionState)
{
    if (v8Value.IsEmpty())
        return;

    if (v8Value->IsNumber()) {
        TONATIVE_VOID_EXCEPTIONSTATE(double, cppValue, toDouble(v8Value, exceptionState), exceptionState);
        impl.setDouble(cppValue);
        return;
    }

    {
        TOSTRING_VOID_EXCEPTIONSTATE(V8StringResource<>, cppValue, v8Value, exceptionState);
        impl.setString(cppValue);
        return;
    }

    exceptionState.throwTypeError("Not a valid union member.");
}

v8::Handle<v8::Value> toV8(StringOrDouble& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    if (impl.isNull())
        return v8::Null(isolate);

    if (impl.isString())
        return v8String(isolate, impl.getAsString());

    if (impl.isDouble())
        return v8::Number::New(isolate, impl.getAsDouble());

    ASSERT_NOT_REACHED();
    return v8::Handle<v8::Value>();
}

TestInterfaceGarbageCollectedOrString::TestInterfaceGarbageCollectedOrString()
    : m_type(SpecificTypeNone)
{
}

RawPtr<TestInterfaceGarbageCollected> TestInterfaceGarbageCollectedOrString::getAsTestInterfaceGarbageCollected()
{
    ASSERT(isTestInterfaceGarbageCollected());
    return m_testInterfaceGarbageCollected;
}

void TestInterfaceGarbageCollectedOrString::setTestInterfaceGarbageCollected(RawPtr<TestInterfaceGarbageCollected> value)
{
    ASSERT(isNull());
    m_testInterfaceGarbageCollected = value;
    m_type = SpecificTypeTestInterfaceGarbageCollected;
}

String TestInterfaceGarbageCollectedOrString::getAsString()
{
    ASSERT(isString());
    return m_string;
}

void TestInterfaceGarbageCollectedOrString::setString(String value)
{
    ASSERT(isNull());
    m_string = value;
    m_type = SpecificTypeString;
}

void TestInterfaceGarbageCollectedOrString::trace(Visitor* visitor)
{
    visitor->trace(m_testInterfaceGarbageCollected);
}

void V8TestInterfaceGarbageCollectedOrString::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, TestInterfaceGarbageCollectedOrString& impl, ExceptionState& exceptionState)
{
    if (v8Value.IsEmpty())
        return;

    if (V8TestInterfaceGarbageCollected::hasInstance(v8Value, isolate)) {
        RawPtr<TestInterfaceGarbageCollected> cppValue = V8TestInterfaceGarbageCollected::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
        impl.setTestInterfaceGarbageCollected(cppValue);
        return;
    }

    {
        TOSTRING_VOID_EXCEPTIONSTATE(V8StringResource<>, cppValue, v8Value, exceptionState);
        impl.setString(cppValue);
        return;
    }

    exceptionState.throwTypeError("Not a valid union member.");
}

v8::Handle<v8::Value> toV8(TestInterfaceGarbageCollectedOrString& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    if (impl.isNull())
        return v8::Null(isolate);

    if (impl.isTestInterfaceGarbageCollected())
        return toV8(impl.getAsTestInterfaceGarbageCollected(), creationContext, isolate);

    if (impl.isString())
        return v8String(isolate, impl.getAsString());

    ASSERT_NOT_REACHED();
    return v8::Handle<v8::Value>();
}

TestInterfaceOrLong::TestInterfaceOrLong()
    : m_type(SpecificTypeNone)
{
}

PassRefPtr<TestInterfaceImplementation> TestInterfaceOrLong::getAsTestInterface()
{
    ASSERT(isTestInterface());
    return m_testInterface;
}

void TestInterfaceOrLong::setTestInterface(PassRefPtr<TestInterfaceImplementation> value)
{
    ASSERT(isNull());
    m_testInterface = value;
    m_type = SpecificTypeTestInterface;
}

int TestInterfaceOrLong::getAsLong()
{
    ASSERT(isLong());
    return m_long;
}

void TestInterfaceOrLong::setLong(int value)
{
    ASSERT(isNull());
    m_long = value;
    m_type = SpecificTypeLong;
}

void V8TestInterfaceOrLong::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, TestInterfaceOrLong& impl, ExceptionState& exceptionState)
{
    if (v8Value.IsEmpty())
        return;

    if (V8TestInterface::hasInstance(v8Value, isolate)) {
        RefPtr<TestInterfaceImplementation> cppValue = V8TestInterface::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
        impl.setTestInterface(cppValue);
        return;
    }

    if (v8Value->IsNumber()) {
        TONATIVE_VOID_EXCEPTIONSTATE(int, cppValue, toInt32(v8Value, exceptionState), exceptionState);
        impl.setLong(cppValue);
        return;
    }

    {
        TONATIVE_VOID_EXCEPTIONSTATE(int, cppValue, toInt32(v8Value, exceptionState), exceptionState);
        impl.setLong(cppValue);
        return;
    }

    exceptionState.throwTypeError("Not a valid union member.");
}

v8::Handle<v8::Value> toV8(TestInterfaceOrLong& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    if (impl.isNull())
        return v8::Null(isolate);

    if (impl.isTestInterface())
        return toV8(impl.getAsTestInterface(), creationContext, isolate);

    if (impl.isLong())
        return v8::Integer::New(isolate, impl.getAsLong());

    ASSERT_NOT_REACHED();
    return v8::Handle<v8::Value>();
}

TestInterfaceOrTestInterfaceEmpty::TestInterfaceOrTestInterfaceEmpty()
    : m_type(SpecificTypeNone)
{
}

PassRefPtr<TestInterfaceImplementation> TestInterfaceOrTestInterfaceEmpty::getAsTestInterface()
{
    ASSERT(isTestInterface());
    return m_testInterface;
}

void TestInterfaceOrTestInterfaceEmpty::setTestInterface(PassRefPtr<TestInterfaceImplementation> value)
{
    ASSERT(isNull());
    m_testInterface = value;
    m_type = SpecificTypeTestInterface;
}

PassRefPtr<TestInterfaceEmpty> TestInterfaceOrTestInterfaceEmpty::getAsTestInterfaceEmpty()
{
    ASSERT(isTestInterfaceEmpty());
    return m_testInterfaceEmpty;
}

void TestInterfaceOrTestInterfaceEmpty::setTestInterfaceEmpty(PassRefPtr<TestInterfaceEmpty> value)
{
    ASSERT(isNull());
    m_testInterfaceEmpty = value;
    m_type = SpecificTypeTestInterfaceEmpty;
}

void V8TestInterfaceOrTestInterfaceEmpty::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, TestInterfaceOrTestInterfaceEmpty& impl, ExceptionState& exceptionState)
{
    if (v8Value.IsEmpty())
        return;

    if (V8TestInterface::hasInstance(v8Value, isolate)) {
        RefPtr<TestInterfaceImplementation> cppValue = V8TestInterface::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
        impl.setTestInterface(cppValue);
        return;
    }

    if (V8TestInterfaceEmpty::hasInstance(v8Value, isolate)) {
        RefPtr<TestInterfaceEmpty> cppValue = V8TestInterfaceEmpty::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
        impl.setTestInterfaceEmpty(cppValue);
        return;
    }

    exceptionState.throwTypeError("Not a valid union member.");
}

v8::Handle<v8::Value> toV8(TestInterfaceOrTestInterfaceEmpty& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    if (impl.isNull())
        return v8::Null(isolate);

    if (impl.isTestInterface())
        return toV8(impl.getAsTestInterface(), creationContext, isolate);

    if (impl.isTestInterfaceEmpty())
        return toV8(impl.getAsTestInterfaceEmpty(), creationContext, isolate);

    ASSERT_NOT_REACHED();
    return v8::Handle<v8::Value>();
}

TestInterfaceWillBeGarbageCollectedOrTestDictionary::TestInterfaceWillBeGarbageCollectedOrTestDictionary()
    : m_type(SpecificTypeNone)
{
}

PassRefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected> TestInterfaceWillBeGarbageCollectedOrTestDictionary::getAsTestInterfaceWillBeGarbageCollected()
{
    ASSERT(isTestInterfaceWillBeGarbageCollected());
    return m_testInterfaceWillBeGarbageCollected;
}

void TestInterfaceWillBeGarbageCollectedOrTestDictionary::setTestInterfaceWillBeGarbageCollected(PassRefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected> value)
{
    ASSERT(isNull());
    m_testInterfaceWillBeGarbageCollected = value;
    m_type = SpecificTypeTestInterfaceWillBeGarbageCollected;
}

TestDictionary TestInterfaceWillBeGarbageCollectedOrTestDictionary::getAsTestDictionary()
{
    ASSERT(isTestDictionary());
    return m_testDictionary;
}

void TestInterfaceWillBeGarbageCollectedOrTestDictionary::setTestDictionary(TestDictionary value)
{
    ASSERT(isNull());
    m_testDictionary = value;
    m_type = SpecificTypeTestDictionary;
}

void TestInterfaceWillBeGarbageCollectedOrTestDictionary::trace(Visitor* visitor)
{
    visitor->trace(m_testInterfaceWillBeGarbageCollected);
}

void V8TestInterfaceWillBeGarbageCollectedOrTestDictionary::toImpl(v8::Isolate* isolate, v8::Handle<v8::Value> v8Value, TestInterfaceWillBeGarbageCollectedOrTestDictionary& impl, ExceptionState& exceptionState)
{
    if (v8Value.IsEmpty())
        return;

    if (V8TestInterfaceWillBeGarbageCollected::hasInstance(v8Value, isolate)) {
        RefPtrWillBeRawPtr<TestInterfaceWillBeGarbageCollected> cppValue = V8TestInterfaceWillBeGarbageCollected::toImpl(v8::Handle<v8::Object>::Cast(v8Value));
        impl.setTestInterfaceWillBeGarbageCollected(cppValue);
        return;
    }

    if (isUndefinedOrNull(v8Value) || v8Value->IsObject()) {
        TestDictionary cppValue = V8TestDictionary::toImpl(isolate, v8Value, exceptionState);
        if (!exceptionState.hadException())
            impl.setTestDictionary(cppValue);
        return;
    }

    exceptionState.throwTypeError("Not a valid union member.");
}

v8::Handle<v8::Value> toV8(TestInterfaceWillBeGarbageCollectedOrTestDictionary& impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    if (impl.isNull())
        return v8::Null(isolate);

    if (impl.isTestInterfaceWillBeGarbageCollected())
        return toV8(impl.getAsTestInterfaceWillBeGarbageCollected(), creationContext, isolate);

    if (impl.isTestDictionary())
        return toV8(impl.getAsTestDictionary(), creationContext, isolate);

    ASSERT_NOT_REACHED();
    return v8::Handle<v8::Value>();
}

} // namespace blink
