//=============================================================================
// METHOD    : SPELLwsListDataHandler::write()
//=============================================================================
void SPELLwsListDataHandler::write()
{
	assert( PyList_Check(getObject()));

	unsigned int numItems = PyList_Size( getObject() );

	// Store the number of items
	getStorage()->storeLong( (long) numItems );

	// Store each list item
	for( unsigned int index = 0; index < numItems; index++)
	{
		PyObject* item = PyList_GetItem( getObject(), index );

		try
		{
			SPELLwsDataHandler* handler = SPELLwsDataHandlerFactory::createDataHandler(item);
			handler->setStorage(getStorage());
			// Store the item data code. We need it for reading operation, in order to
			// know which type of handler to create.
			handler->storeDataCode();

			// IMPORTANT in the case of lists and dictionaries, we want to be able to continue
			// the storage evenif there is a problem in the handler processing at this point.
			// If that is the case, a fake empty object will be replaced by the object being
			// processed by the handler, and the dumping of this collection will continue.
			try
			{
				// Store the data
				handler->write();
			}
			catch(SPELLcoreException& ex)
			{
				std::string msg = "WARNING! Storage of element " + ISTR(index) + " failed: " + ex.what();
				LOG_WARN(msg);
				std::cerr << msg << std::endl;
				storeFakeObject( handler->getCode() );
			}
			delete handler;
		}
		catch(SPELLcoreException& ex)
		{
			std::string msg = "WARNING! Failed to create data handler: " + ex.what();
			LOG_WARN(msg);
			storeFakeObject( SPELLwsData::DATA_NONE );
		}

	}
}
//=============================================================================
// METHOD    : SPELLwsDictDataHandler::write()
//=============================================================================
void SPELLwsDictDataHandler::write()
{
	if (getObject() == NULL)
	{
		getStorage()->storeLong( -1 );
		return;
	}

	assert( PyDict_Check(getObject()));

	SPELLpyHandle keys = PyDict_Keys( getObject() );
	unsigned int numItems = PyList_Size( keys.get() );

	DEBUG("[DDH] Storing dictionary items (total " + ISTR(numItems) + ") address " + PSTR(getObject()));

	PyObject* key = NULL;
	PyObject* item = NULL;

	long toStore = 0;
	// Calculate the number of items to store
	// Store each list item
	DEBUG("[DDH] Keys of the dictionary:");
	for( unsigned int index = 0; index < numItems; index++)
	{
		key = PyList_GetItem( keys.get(), index );
		item = PyDict_GetItem( getObject(), key );
		if (SPELLwsWarmStartImpl::shouldFilter(key,item))
		{
			continue;
		}
		else
		{
			DEBUG("     - " + PYSSTR(key));
		}
		toStore++;
	}

	DEBUG("[DDH] Will store " + ISTR(toStore) + " keys");
	// Store the number of items
	getStorage()->storeLong( (long) toStore );

	DEBUG("[DDH] Start checking items");
	if (toStore>0)
	{
		// Store each list item
		for( unsigned int index = 0; index < numItems; index++)
		{
			key = PyList_GetItem( keys.get(), index );
			item = PyDict_GetItem( getObject(), key );

			DEBUG("[DDH] Checking item " + PYCREPR(key));

			// Do not consider filtered values
			if (SPELLwsWarmStartImpl::shouldFilter(key,item)) continue;

			SPELLpythonHelper::instance().checkError();

			DEBUG("		[DDH] Key index " + ISTR(index));
			DEBUG("		[DDH] Key to use" + PYREPR(key));
			DEBUG("		[DDH] Item type:" + PYREPR(PyObject_Type(item)));

			// Handler for the key
			SPELLwsObjectDataHandler keyHandler(key);
			keyHandler.setStorage(getStorage());

			DEBUG("		[DDH] Creating handler");

			// Create a handler for the item
			SPELLwsDataHandler* handler = SPELLwsDataHandlerFactory::createDataHandler(item);
			handler->setStorage(getStorage());

			// Store the key
			DEBUG("		[DDH] Storing key: " + PYREPR(key));
			keyHandler.write();

			// Store the item data code in order to recognise it later
			DEBUG("		[DDH] Storing data code: " + SPELLwsData::codeStr(handler->getCode()));
			handler->storeDataCode();

			// IMPORTANT in the case of lists and dictionaries, we want to be able to continue
			// the storage even if there is a problem in the handler processing at this point.
			// If that is the case, a fake empty object will be replaced by the object being
			// processed by the handler, and the dumping of this collection will continue.
			try
			{
				if (handler->getCode() == SPELLwsData::DATA_CUSTOM_TYPE )
				{
					std::string msg = "WARNING! warm start not supported for custom Python types (" + PYREPR(key) + "=" + PYREPR(item) + ")";
					LOG_WARN(msg);
					SPELLexecutor::instance().getCIF().warning(msg);
					storeFakeObject( SPELLwsData::DATA_NONE );
				}
				else
				{
					// Store the value
					DEBUG("		[DDH] Storing value: " + PYREPR(item));
					handler->write();
					DEBUG("		[DDH] Storing value done");
				}
			}
			catch(SPELLcoreException& ex)
			{
				std::string msg = "WARNING! WS storage of element " + ISTR(index) + " failed: " + ex.what();
				LOG_WARN(msg);
				SPELLexecutor::instance().getCIF().warning(msg);
				storeFakeObject( handler->getCode() );
			}
			delete handler;
		}
	}

	DEBUG("[DDH] Storing dictionary done");
}