#ifndef SVGListPropertyTearOffHelper_h
#define SVGListPropertyTearOffHelper_h
#include "bindings/v8/ExceptionState.h"
#include "core/svg/properties/SVGPropertyTearOff.h"
#include "wtf/HashMap.h"
#include "wtf/TypeTraits.h"
namespace WebCore {
template<typename ItemProperty>
class ListItemPropertyTraits {
public:
typedef ItemProperty ItemPropertyType;
typedef typename ItemPropertyType::TearOffType ItemTearOffType;
static PassRefPtr<ItemPropertyType> getValueForInsertionFromTearOff(PassRefPtr<ItemTearOffType> passNewItem)
{
RefPtr<ItemTearOffType> newItem = passNewItem;
if (newItem->isImmutable()
|| (newItem->contextElement() && !newItem->target()->ownerList())) {
return newItem->target()->clone();
}
return newItem->target();
}
static PassRefPtr<ItemTearOffType> createTearOff(PassRefPtr<ItemPropertyType> value, SVGElement* contextElement, PropertyIsAnimValType propertyIsAnimVal, const QualifiedName& attributeName)
{
return ItemTearOffType::create(value, contextElement, propertyIsAnimVal, attributeName);
}
};
template<typename Derived, typename ListProperty>
class SVGListPropertyTearOffHelper : public SVGPropertyTearOff<ListProperty> {
public:
typedef ListProperty ListPropertyType;
typedef typename ListPropertyType::ItemPropertyType ItemPropertyType;
typedef typename ItemPropertyType::TearOffType ItemTearOffType;
typedef ListItemPropertyTraits<ItemPropertyType> ItemTraits;
unsigned long length()
{
return toDerived()->target()->length();
}
void clear(ExceptionState& exceptionState)
{
if (toDerived()->isImmutable()) {
exceptionState.throwDOMException(NoModificationAllowedError, "The object is read-only.");
return;
}
toDerived()->target()->clear();
}
PassRefPtr<ItemTearOffType> initialize(PassRefPtr<ItemTearOffType> passItem, ExceptionState& exceptionState)
{
RefPtr<ItemTearOffType> item = passItem;
if (toDerived()->isImmutable()) {
exceptionState.throwDOMException(NoModificationAllowedError, "The object is read-only.");
return nullptr;
}
if (!item) {
exceptionState.throwTypeError("Lists must be initialized with a valid item.");
return nullptr;
}
RefPtr<ItemPropertyType> value = toDerived()->target()->initialize(getValueForInsertionFromTearOff(item));
toDerived()->commitChange();
return createItemTearOff(value.release());
}
PassRefPtr<ItemTearOffType> getItem(unsigned long index, ExceptionState& exceptionState)
{
RefPtr<ItemPropertyType> value = toDerived()->target()->getItem(index, exceptionState);
return createItemTearOff(value.release());
}
PassRefPtr<ItemTearOffType> insertItemBefore(PassRefPtr<ItemTearOffType> passItem, unsigned long index, ExceptionState& exceptionState)
{
RefPtr<ItemTearOffType> item = passItem;
if (toDerived()->isImmutable()) {
exceptionState.throwDOMException(NoModificationAllowedError, "The object is read-only.");
return nullptr;
}
if (!item) {
exceptionState.throwTypeError("An invalid item cannot be inserted to a list.");
return nullptr;
}
RefPtr<ItemPropertyType> value = toDerived()->target()->insertItemBefore(getValueForInsertionFromTearOff(item), index);
toDerived()->commitChange();
return createItemTearOff(value.release());
}
PassRefPtr<ItemTearOffType> replaceItem(PassRefPtr<ItemTearOffType> passItem, unsigned long index, ExceptionState& exceptionState)
{
RefPtr<ItemTearOffType> item = passItem;
if (toDerived()->isImmutable()) {
exceptionState.throwDOMException(NoModificationAllowedError, "The object is read-only.");
return nullptr;
}
if (!item) {
exceptionState.throwTypeError("An invalid item cannot be replaced with an existing list item.");
return nullptr;
}
RefPtr<ItemPropertyType> value = toDerived()->target()->replaceItem(getValueForInsertionFromTearOff(item), index, exceptionState);
toDerived()->commitChange();
return createItemTearOff(value.release());
}
bool anonymousIndexedSetter(unsigned index, PassRefPtr<ItemTearOffType> passItem, ExceptionState& exceptionState)
{
replaceItem(passItem, index, exceptionState);
return true;
}
PassRefPtr<ItemTearOffType> removeItem(unsigned long index, ExceptionState& exceptionState)
{
RefPtr<ItemPropertyType> value = toDerived()->target()->removeItem(index, exceptionState);
toDerived()->commitChange();
return createItemTearOff(value.release());
}
PassRefPtr<ItemTearOffType> appendItem(PassRefPtr<ItemTearOffType> passItem, ExceptionState& exceptionState)
{
RefPtr<ItemTearOffType> item = passItem;
if (toDerived()->isImmutable()) {
exceptionState.throwDOMException(NoModificationAllowedError, "The object is read-only.");
return nullptr;
}
if (!item) {
exceptionState.throwTypeError("An invalid item cannot be appended to a list.");
return nullptr;
}
RefPtr<ItemPropertyType> value = toDerived()->target()->appendItem(getValueForInsertionFromTearOff(item));
toDerived()->commitChange();
return createItemTearOff(value.release());
}
protected:
SVGListPropertyTearOffHelper(PassRefPtr<ListPropertyType> target, SVGElement* contextElement, PropertyIsAnimValType propertyIsAnimVal, const QualifiedName& attributeName = nullQName())
: SVGPropertyTearOff<ListPropertyType>(target, contextElement, propertyIsAnimVal, attributeName)
{
}
static PassRefPtr<ItemPropertyType> getValueForInsertionFromTearOff(PassRefPtr<ItemTearOffType> passNewItem)
{
return ItemTraits::getValueForInsertionFromTearOff(passNewItem);
}
PassRefPtr<ItemTearOffType> createItemTearOff(PassRefPtr<ItemPropertyType> value)
{
if (!value)
return nullptr;
return ItemTraits::createTearOff(value, toDerived()->contextElement(), toDerived()->propertyIsAnimVal(), toDerived()->attributeName());
}
private:
Derived* toDerived() { return static_cast<Derived*>(this); }
};
}
#endif