//==============================================================================
ObjectHandle SetReflectedPropertyCommand::execute(
	const ObjectHandle & arguments ) const
{
	ReflectedPropertyCommandArgument * commandArgs =
		arguments.getBase< ReflectedPropertyCommandArgument >();
	auto objManager = definitionManager_.getObjectManager();
	assert( objManager != nullptr );
	ObjectHandle object = objManager->getObject( commandArgs->getContextId() );
	if (!object.isValid())
	{
		return CommandErrorCode::INVALID_ARGUMENTS;
	}
	PropertyAccessor property = object.getDefinition( definitionManager_ )->bindProperty( 
		commandArgs->getPropertyPath(), object );
	if (property.isValid() == false)
	{
		//Can't set
		return CommandErrorCode::INVALID_ARGUMENTS;
	}
	const Variant & data = commandArgs->getPropertyValue();
	bool br = property.setValue( data );
	if (!br)
	{
		return CommandErrorCode::INVALID_VALUE;
	}

	// Do not return the object
	// CommandInstance will hold a reference to the return value
	// and the CommandInstance is stored in the undo/redo history forever
	// This is due to a circular reference in CommandManagerImpl::pushFrame
	return nullptr;
}
Example #2
0
bool BaseGenericObject::addProperty(const char* name, const Variant& value, MetaData metadata, bool enableNotification)
{
	const IClassDefinition& definition = *this->getDefinition();
	ObjectHandle provider = this->getDerivedType();

	auto definitionModifier = definition.getDetails().getDefinitionModifier();
	if (definitionModifier == nullptr)
	{
		return false;
	}

	Collection testCollection;
	bool isCollection = value.tryCast<Collection>(testCollection);

	if (!definitionModifier->addProperty(name, value.type()->typeId(), std::move(metadata), isCollection))
	{
		return false;
	}

	PropertyAccessor accessor = definition.bindProperty(name, provider);
	if (enableNotification)
	{
		return accessor.setValue(value);
	}
	else
	{
		return accessor.setValueWithoutNotification(value);
	}
}
Example #3
0
Variant c_XMLReader::t___get(Variant name) {
  INSTANCE_METHOD_INJECTION_BUILTIN(XMLReader, XMLReader::__get);
  const xmlChar *retchar = NULL;
	int retint = 0;

  PropertyAccessor *propertyMap = xmlreader_properties_map.get(name);
  if (m_ptr) {
    if (propertyMap->getter_char) {
      retchar = propertyMap->getter_char(m_ptr);
    } else if (propertyMap->getter_int) {
      retint = propertyMap->getter_int(m_ptr);
    }
  }

  switch (propertyMap->return_type) {
    case KindOfString:
      if (retchar) {
        return String((char*)retchar, CopyString);
      } else {
        return String("");
      }
    case KindOfBoolean:
      return (retint ? true : false);

    case KindOfInt64:
      return retint;

    default:
      return null;
  }
  return null;
}
Example #4
0
	Variant getValue( const PropertyAccessor & pa )
	{
		// This createKey is added as a work-around for objects that were
		// not registered with the IObjectManager properly on creation.
		//
		// Objects need a key to be shared with other plugins.
		// E.g. getValue() will be sharing your object with plg_command_manager.
		//
		// Better to register your object with IObjectManager::registerObject()
		// or IObjectManager::registerUnmanagedObject() when you create the
		// ObjectHandle.
		//
		// @see IObjectManager
		Key key;
		if (!createKey( pa, key ))
		{
			return pa.getValue();
		}

		// TODO: assert access is only on the main thread
		auto range = commands_.equal_range( key );
		for (auto it = range.first; it != range.second; ++it)
		{
			auto instance = it->second;
			commandManager_.waitForInstance(instance);
		}
		commands_.erase( range.first, range.second );

		return pa.getValue();
	}
Example #5
0
	void setValue( const PropertyAccessor & pa, const Variant & data )
	{
		Key key;
		if (!createKey( pa, key ))
		{
			pa.setValue( data );
			return;
		}

		std::unique_ptr< ReflectedPropertyCommandArgument > args( new ReflectedPropertyCommandArgument );
		args->setContextId( key.first );
		args->setPath( key.second.c_str() );
		args->setValue( data );
		
		// Access is only on the main thread
		assert( std::this_thread::get_id() == commandManager_.ownerThreadId() );

		const auto commandId = getClassIdentifier< SetReflectedPropertyCommand >();
		const auto pArgsDefinition =
			pa.getDefinitionManager()->getDefinition< ReflectedPropertyCommandArgument >();
		ObjectHandle commandArgs( std::move( args ), pArgsDefinition );
		auto command = commandManager_.queueCommand( commandId, commandArgs );

		// Queuing may cause it to execute straight away
		// Based on the thread affinity of SetReflectedPropertyCommand
		if (!command->isComplete())
		{
			commands_.emplace( std::pair< Key, CommandInstancePtr >( key, command ) );
		}
	}
Example #6
0
TEST_F( TestCommandFixture, creatMacro )
{
	auto & controller = getReflectionController();

	auto objHandle = klass_->createManagedObject();

	PropertyAccessor counter = klass_->bindProperty("counter", objHandle );
	CHECK(counter.isValid());

	const int TEST_VALUE = 57;
	{
		int value = TEST_VALUE;
		controller.setValue( counter, value );
	}

	{
		// TODO: wait on controller
		controller.getValue( counter );
	}

	{
		auto & commandSystemProvider = getCommandSystemProvider();
		auto & history = commandSystemProvider.getHistory();
		commandSystemProvider.createMacro( history );
		CHECK(commandSystemProvider.getMacros().empty() == false );
	}
}
//==============================================================================
std::string RPURU::resolveContextObjectPropertyPath(const ObjectHandle& contextObject, const char* propertyPath,
                                                    IDefinitionManager& definitionManager)
{
	assert(contextObject != nullptr);
	const auto classDef = contextObject.getDefinition(definitionManager);
	assert(classDef != nullptr);
	std::string tmp = propertyPath;
	std::vector<std::string> paths;
	paths.push_back(tmp);

	char* pch;
	pch = strtok(const_cast<char*>(tmp.c_str()), ".");
	if (pch != NULL)
	{
		pch = strtok(NULL, ".");
		while (pch != NULL)
		{
			paths.push_back(pch);
			pch = strtok(NULL, ".");
		}
	}
	PropertyAccessor pa;
	for (auto& path : paths)
	{
		resolveProperty(contextObject, *classDef, path.c_str(), pa, definitionManager);
		if (pa.isValid())
		{
			break;
		}
	}
	return pa.getFullPath();
}
Example #8
0
Variant BaseGenericObject::invokeProperty(const char* name, const ReflectedMethodParameters& parameters)
{
	const IClassDefinition& definition = *this->getDefinition();
	ObjectHandle provider = this->getDerivedType();
	PropertyAccessor accessor = definition.bindProperty(name, provider);
	if (!accessor.isValid())
	{
		TF_ASSERT(false && "Property could not be found");
		return Variant();
	}
	return accessor.invoke(parameters);
}
Example #9
0
TEST_F( TestCommandFixture, undo_redo )
{
	auto & controller = getReflectionController();

	auto objHandle = klass_->createManagedObject();

	PropertyAccessor counter = klass_->bindProperty("counter", objHandle );
	CHECK(counter.isValid());
	int oldValue = -1;
	{
		Variant variant = counter.getValue();
		CHECK(variant.tryCast( oldValue ));
	}
	auto & commandSystemProvider = getCommandSystemProvider();
	const int TEST_VALUE = 57;
	{
		int value = TEST_VALUE;
		
		controller.setValue( counter, value );
	}

	{
		int value = 0;
		Variant variant = controller.getValue( counter );
		CHECK(variant.tryCast( value ));
		CHECK_EQUAL(TEST_VALUE, value);
	}

	{
		commandSystemProvider.undo();
		CHECK(!commandSystemProvider.canUndo());
		CHECK(commandSystemProvider.canRedo());

		int value = 0;
		Variant variant = controller.getValue( counter );
		CHECK(variant.tryCast( value ));
		CHECK_EQUAL(oldValue, value);
	}

	{
		commandSystemProvider.redo();
		CHECK(commandSystemProvider.canUndo());
		CHECK(!commandSystemProvider.canRedo());

		int value = 0;
		Variant variant = controller.getValue( counter );
		CHECK(variant.tryCast( value ));
		CHECK_EQUAL(TEST_VALUE, value);
	}
}
Example #10
0
void DialogTestModel::callBasicDialog(bool modal)
{
	assert(context_ != nullptr);
	auto uiFramework = context_->queryInterface<IUIFramework>();
	assert(uiFramework != nullptr);

	IDialog::ClosedCallback callback = [this](IDialog& dialog) {
		assert(definition_ != nullptr);
		PropertyAccessor accessor = definition_->bindProperty("basicDialogResult", this);
		accessor.setValue(dialog.result());
	};

	const IDialog::Mode mode = modal ? IDialog::Mode::MODAL : IDialog::Mode::MODELESS;
	uiFramework->showDialog("plg_dialog_test/basic_dialog.qml", mode, callback);
}
Example #11
0
//! @brief read a text Bow file and fills a lexicon
//! @param fileIn the file to read
//! @param reader the file reader
//! @param lex the lexicon to fill
//! @param propertyAccessor
//! @param referenceProperties
void readBowFileText(ifstream& fileIn,
                     BoWBinaryReader& reader,
                     Lexicon& lex,
                     const PropertyAccessor& propertyAccessor,
                     set<LinguisticCode>& referenceProperties
                    )
{
    BoWText text;
    reader.readBoWText(fileIn,text);

    bool filterCategory = false;
    if ( referenceProperties.size() > 0 ) {
        filterCategory = true;
    }

    BoWTokenIterator it(text);
    while (! it.isAtEnd()) {
        const BoWToken& token = *(it.getElement());
        if (filterCategory) {
            set<LinguisticCode>::const_iterator referencePropertyIt =
                referenceProperties.find(propertyAccessor.readValue(token.getCategory()));
            if ( referencePropertyIt != referenceProperties.end() ) {
                lex.add(getStringDecomp(&token),token.getIndexString());
            }
        }
        else {
            lex.add(getStringDecomp(&token),token.getIndexString());
        }
        it++;
    }
}
//==============================================================================
bool SetReflectedPropertyCommand::validateArguments(const ObjectHandle& arguments) const
{
	if ( !arguments.isValid() ) 
	{
		return false;
	}

	auto commandArgs = arguments.getBase< ReflectedPropertyCommandArgument >();
	
	if ( commandArgs == nullptr ) 
	{
			return false;
	}

	auto objManager = definitionManager_.getObjectManager();
	if ( objManager == nullptr ) 
	{
		return false;
	}

	const ObjectHandle & object = objManager->getObject( commandArgs->getContextId() );
	if (!object.isValid())
	{
		return false;
	}

	const IClassDefinition* defn = object.getDefinition( definitionManager_ );
	PropertyAccessor property = defn->bindProperty(commandArgs->getPropertyPath(), object );
	if (property.isValid() == false)
	{
		return false;
	}
	
	const MetaType * dataType = commandArgs->getPropertyValue().type();
	const MetaType * propertyValueType = property.getValue().type();

	if ( !dataType->canConvertTo(propertyValueType) ) 
	{
		return false;
	}

	return true;
}
Example #13
0
	bool createKey( const PropertyAccessor & pa, Key & o_Key )
	{
		const auto & obj = pa.getRootObject();
		if (obj == nullptr)
		{
			return false;
		}

		if (!obj.getId( o_Key.first ))
		{
			auto om = pa.getDefinitionManager()->getObjectManager();
			assert( !om->getObject( obj.data() ).isValid() );
			if (!om->getUnmanagedObjectId( obj.data(), o_Key.first ))
			{
				o_Key.first = om->registerUnmanagedObject( obj );
			}
		}

		o_Key.second = pa.getFullPath();
		return true;
	}
//==============================================================================
void RPURU::resolveProperty(const ObjectHandle& handle, const IClassDefinition& classDef, const char* propertyPath,
                            PropertyAccessor& o_Pa, IDefinitionManager& definitionManager)
{
	o_Pa = handle.getDefinition(definitionManager)->bindProperty(propertyPath, handle);
	if (o_Pa.isValid())
	{
		return;
	}
	const PropertyIteratorRange& props = classDef.allProperties();
	for (PropertyIterator pi = props.begin(); pi != props.end(); ++pi)
	{
		std::string parentPath = pi->getName();
		const PropertyAccessor& prop = classDef.bindProperty(parentPath.c_str(), handle);
		assert(prop.isValid());
		if (prop.getProperty()->isMethod())
		{
			continue;
		}
		const Variant& value = prop.getValue();
		if (value.typeIs<ObjectHandle>())
		{
			ObjectHandle subHandle;
			bool isOk = value.tryCast(subHandle);
			assert(isOk);
			if ((subHandle == nullptr) || (subHandle.getDefinition(definitionManager) == nullptr))
			{
				continue;
			}
			parentPath = parentPath + "." + propertyPath;

			resolveProperty(subHandle, *subHandle.getDefinition(definitionManager), parentPath.c_str(), o_Pa,
			                definitionManager);

			if (o_Pa.isValid())
			{
				return;
			}
		}
	}
}
Example #15
0
TEST_F( TestCommandFixture, executeMacro )
{
	auto & controller = getReflectionController();

	auto objHandle = klass_->createManagedObject();

	PropertyAccessor counter = klass_->bindProperty("counter", objHandle );
	CHECK(counter.isValid());

	const int TEST_VALUE = 57;
	{
		int value = TEST_VALUE;
		controller.setValue( counter, value );
	}

	{
		// TODO: wait on controller
		controller.getValue( counter );
	}

	{
		auto & commandSystemProvider = getCommandSystemProvider();
		commandSystemProvider.undo();
		auto & history = commandSystemProvider.getHistory();
		commandSystemProvider.createMacro( history, "Macro1" );
		CHECK(commandSystemProvider.getMacros().empty() == false );
		auto macroObj = static_cast<CompoundCommand*>( commandSystemProvider.findCommand( "Macro1" ) )->getMacroObject();
		auto instObj = macroObj.getBase<MacroObject>()->executeMacro();
		CommandInstancePtr inst = instObj.getBase<CommandInstance>();
		commandSystemProvider.waitForInstance( inst );
		{
			PropertyAccessor counter = klass_->bindProperty("counter", objHandle );
			int value = 0;
			Variant variant = controller.getValue( counter );
			CHECK(variant.tryCast( value ));
			CHECK_EQUAL(TEST_VALUE, value);
		}
	}
}
Example #16
0
	//--------------------------------------------------------------------------
	ObjectHandle MetaUtilities::findFirstMetaData(
		const TypeId& typeId, const PropertyAccessor& accessor,
		const IDefinitionManager & definitionManager) override
	{
		auto && metaData = accessor.getMetaData();
		auto targetMetaData = findFirstMetaData(typeId, metaData, definitionManager);
		if (targetMetaData != nullptr)
		{
			return targetMetaData;
		}

		return nullptr;
	}
Example #17
0
TEST_F( TestCommandFixture, runSingleCommand )
{
	auto & controller = getReflectionController();

	auto objHandle = klass_->createManagedObject();

	PropertyAccessor counter = klass_->bindProperty("counter", objHandle );
	CHECK(counter.isValid());

	const int TEST_VALUE = 57;
	{
		int value = TEST_VALUE;
		controller.setValue( counter, value );
	}

	{
		int value = 0;
		Variant variant = controller.getValue( counter );
		CHECK(variant.tryCast( value ));
		CHECK_EQUAL(TEST_VALUE, value);
	}

}
Example #18
0
	Variant invoke( const PropertyAccessor & pa, const ReflectedMethodParameters & parameters )
	{
		Key key;
		if (!createKey( pa, key ))
		{
			return pa.invoke( parameters );
		}

		std::unique_ptr<ReflectedMethodCommandParameters> commandParameters( new ReflectedMethodCommandParameters() );
		commandParameters->setId( key.first );
		commandParameters->setPath( key.second.c_str() );
		commandParameters->setParameters( parameters );

		const auto itr = commands_.emplace( std::pair< Key, CommandInstancePtr >( key, commandManager_.queueCommand(
			getClassIdentifier<InvokeReflectedMethodCommand>(), ObjectHandle( std::move( commandParameters ),
			pa.getDefinitionManager()->getDefinition<ReflectedMethodCommandParameters>() ) ) ) );

		commandManager_.waitForInstance( itr->second );
		ObjectHandle returnValueObject = itr->second.get()->getReturnValue();
		commands_.erase( itr );
		Variant* returnValuePointer = returnValueObject.getBase<Variant>();
		assert( returnValuePointer != nullptr );
		return *returnValuePointer;
	}
Example #19
0
Variant c_XMLReader::t___get(Variant name) {
  const xmlChar *retchar = NULL;
  int retint = 0;

  PropertyAccessor *propertyMap = xmlreader_properties_map.get(name);
  if (!propertyMap) {
    raiseUndefProp(name.getStringData());
    return uninit_null();
  }

  if (m_ptr) {
    if (propertyMap->getter_char) {
      retchar = propertyMap->getter_char(m_ptr);
    } else if (propertyMap->getter_int) {
      retint = propertyMap->getter_int(m_ptr);
    }
  }

  switch (propertyMap->return_type) {
    case KindOfString:
      if (retchar) {
        return String((char*)retchar, CopyString);
      } else {
        return String("");
      }
    case KindOfBoolean:
      return (retint ? true : false);

    case KindOfInt64:
      return retint;

    default:
      return uninit_null();
  }
  return uninit_null();
}
Example #20
0
	void erase( const PropertyAccessor & pa, const Variant & eraseKey )
	{
		Key key;
		if (!createKey( pa, key ))
		{
			pa.erase( eraseKey );
			return;
		}

		std::unique_ptr<ReflectedCollectionEraseCommandParameters> commandParameters( new ReflectedCollectionEraseCommandParameters() );
		commandParameters->id_ = key.first;
		commandParameters->path_ = key.second;
		commandParameters->key_ = eraseKey;

		const auto itr = commands_.emplace( std::pair< Key, CommandInstancePtr >( key, commandManager_.queueCommand(
			getClassIdentifier<ReflectedCollectionEraseCommand>(), ObjectHandle( std::move( commandParameters ) ) ) ) );

		commandManager_.waitForInstance( itr->second );
		commands_.erase( itr );
	}
Example #21
0
ReflectedEnumModel::ReflectedEnumModel(const PropertyAccessor& pA, ObjectHandleT<MetaEnumObj> enumObj)
{
	const wchar_t* enumString = enumObj->getEnumString();
	if (enumString != nullptr)
	{
		generateFromString(items_, enumString);
		return;
	}

	Collection collection = enumObj->generateEnum(pA.getObject());
	auto it = collection.begin();
	auto itEnd = collection.end();
	for (; it != itEnd; ++it)
	{
		int index;
		it.key().tryCast(index);
		Variant itValue = it.value();
		std::string text;
		itValue.tryCast(text);
		items_.push_back(new ReflectedEnumItem(index, text));
	}
}
Example #22
0
bool BaseGenericObject::setProperty(const char* name, const Variant& value, bool enableNotification)
{
	// Get existing property
	const IClassDefinition& definition = *this->getDefinition();
	ObjectHandle provider = this->getDerivedType();
	PropertyAccessor accessor = definition.bindProperty(name, provider);

	// do nothing if property does not exist and the value is void
	if (!accessor.isValid() && value.isVoid())
	{
		return false;
	}

	// set value to the property if property exists and the value is not void
	if (accessor.isValid() && !value.isVoid())
	{
		if (enableNotification)
		{
			return accessor.setValue(value);
		}
		else
		{
			return accessor.setValueWithoutNotification(value);
		}
	}

	// Property does not exist
	// Add new property and set it
	auto definitionModifier = definition.getDetails().getDefinitionModifier();
	if (definitionModifier == nullptr)
	{
		return false;
	}

	if (accessor.isValid() && value.isVoid())
	{
		definitionModifier->removeProperty(name);
		return false;
	}

	return addProperty(name, value, nullptr, enableNotification);
}
Example #23
0
//------------------------------------------------------------------------------
void ClassDefinition::bindPropertyImpl(
	const char * name,
	const ObjectHandle & pBase,
	PropertyAccessor & o_PropertyAccessor ) const
{
	if (!*name)
	{
		// empty name causes noop
		return;
	}

	// find property operator
	auto propOperator = name;
	while (true)
	{
		if( !*propOperator ||
			*propOperator == INDEX_OPEN ||
			*propOperator == DOT_OPERATOR )
		{
			break;
		}

		propOperator += 1;
	}

	auto propName = name;
	auto propLength = propOperator - propName;

	auto baseProp = findProperty( propName, propLength );
	if (baseProp == nullptr)
	{
		// error: property `propName` is not found
		o_PropertyAccessor.setBaseProperty( nullptr );
		return;
	}

	o_PropertyAccessor.setObject( pBase );
	o_PropertyAccessor.setBaseProperty( baseProp );

	assert( strncmp( propName, o_PropertyAccessor.getName(), propLength ) == 0 );

	if (!*propOperator)
	{
		// no operator, so that's it
		return;
	}

	Variant propVal = o_PropertyAccessor.getValue();
	if (*propOperator == INDEX_OPEN)
	{
		auto wholeIndex = propOperator;

		// read "multidimensional" indices without recursive bind (optimization)
		while (true)
		{
			Collection collection;
			if (!propVal.tryCast( collection ))
			{
				// error: index operator is applicable to collections only
				o_PropertyAccessor.setBaseProperty( nullptr );
				return;
			}

			// determine key type (heterogeneous keys are not supported yet)
			const auto begin = collection.begin();
			const auto end = collection.end();
			if (begin == end)
			{
				// error: can't index empty collection
				o_PropertyAccessor.setBaseProperty( nullptr );
				return;
			}

			// read key
			Variant key( begin.key().type() );
			{
				propOperator += 1; // skip INDEX_OPEN

				FixedMemoryStream dataStream( propOperator );
				TextStream stream( dataStream );

				stream >> key >> match( INDEX_CLOSE );

				if (stream.fail())
				{
					// error: either key can't be read, or it isn't followed by INDEX_CLOSE
					o_PropertyAccessor.setBaseProperty( nullptr );
					return;
				}

				// skip key and closing bracket
				propOperator += stream.seek( 0, std::ios_base::cur );
			}

			auto it = collection.find( key );

			// If (it == end), still return a valid property accessor to end,
			// rather than an invalid property accessor.
			if (!*propOperator || (it == end))
			{
				// name parsing is completed
				auto baseProp = std::make_shared< CollectionElementHolder >(
					collection,
					it,
					collection.valueType(),
					wholeIndex );
				// o_PropertyAccessor.setObject(); - keep current base
				o_PropertyAccessor.setBaseProperty( baseProp );
				return;
			}

			propVal = it.value();

			if (*propOperator == INDEX_OPEN)
			{
				continue;
			}

			// parse next operator
			break;
		}
	}
Example #24
0
TEST_F( TestCommandFixture, runBatchCommand )
{
	auto & controller = getReflectionController();

	auto objHandle = klass_->createManagedObject();

	const int TEST_VALUE = 57;
	const char * TEST_TEXT = "HelloCommand";

	PropertyAccessor counter = klass_->bindProperty("counter", objHandle );
	CHECK(counter.isValid());
	PropertyAccessor text = klass_->bindProperty( "text", objHandle );
	CHECK(text.isValid());
	PropertyAccessor incrementCounter = klass_->bindProperty("incrementCounter", objHandle );
	CHECK(incrementCounter.isValid());

	{
		int value = 0;
		Variant variantValue = controller.getValue( counter );
		CHECK( variantValue.tryCast( value ) );
		CHECK( TEST_VALUE != value );

		std::string text_value;
		Variant variantText = controller.getValue( text );
		CHECK( variantText.tryCast( text_value ) );
		CHECK( TEST_TEXT != text_value );
	}

	{
		int value = TEST_VALUE;
		auto & commandSystemProvider = getCommandSystemProvider();
		commandSystemProvider.beginBatchCommand();
		controller.setValue( counter, value );
		std::string text_value = TEST_TEXT;
		controller.setValue( text, text_value );
		commandSystemProvider.abortBatchCommand();
	}

	{
		int value = 0;
		Variant variantValue = controller.getValue( counter );
		CHECK(variantValue.tryCast( value ));
		CHECK(TEST_VALUE != value);

		std::string text_value;
		Variant variantText = controller.getValue( text );
		CHECK(variantText.tryCast( text_value ));
		CHECK(TEST_TEXT != text_value);
	}

	{
		int value = TEST_VALUE;
		auto & commandSystemProvider = getCommandSystemProvider();
		commandSystemProvider.beginBatchCommand();
		controller.setValue( counter, value );
		std::string text_value = TEST_TEXT;
		controller.setValue( text, text_value );
		commandSystemProvider.endBatchCommand();
	}

	{
		int value = 0;
		Variant variantValue = controller.getValue( counter );
		CHECK(variantValue.tryCast( value ));
		CHECK_EQUAL(TEST_VALUE, value);

		std::string text_value;
		Variant variantText = controller.getValue( text );
		CHECK(variantText.tryCast( text_value ));
		CHECK_EQUAL(TEST_TEXT, text_value);
	}

	{
		Variant variantValue;
		int value = 0;
		auto & commandSystemProvider = getCommandSystemProvider();
		commandSystemProvider.beginBatchCommand();
		controller.setValue( counter, 0 );
		commandSystemProvider.beginBatchCommand();
		controller.setValue( counter, 1 );
		commandSystemProvider.beginBatchCommand();
		controller.setValue( counter, 2 );
		commandSystemProvider.beginBatchCommand();
		controller.setValue( counter, 3 );
		variantValue = controller.getValue( counter );
		CHECK( variantValue.tryCast( value ) );
		CHECK( value == 3 );
		commandSystemProvider.abortBatchCommand();
		variantValue = controller.getValue( counter );
		CHECK( variantValue.tryCast( value ) );
		CHECK( value == 2 );
		commandSystemProvider.abortBatchCommand();
		variantValue = controller.getValue( counter );
		CHECK( variantValue.tryCast( value ) );
		CHECK( value == 1);
		commandSystemProvider.abortBatchCommand();
		variantValue = controller.getValue( counter );
		CHECK( variantValue.tryCast( value ) );
		CHECK( value == 0);
		commandSystemProvider.endBatchCommand();
		variantValue = controller.getValue( counter );
		CHECK( variantValue.tryCast( value ) );
		CHECK( value == 0);
	}

	{
		int value = 0;
		controller.setValue( counter, value );
		Variant variantValue = controller.getValue( counter );
		CHECK(variantValue.tryCast( value ));
		CHECK_EQUAL(0, value);

		auto & commandSystemProvider = getCommandSystemProvider();
		commandSystemProvider.beginBatchCommand();
		controller.invoke( incrementCounter, ReflectedMethodParameters() );
		controller.invoke( incrementCounter, ReflectedMethodParameters() );
		commandSystemProvider.endBatchCommand();
		variantValue = controller.getValue( counter );
		CHECK(variantValue.tryCast( value ));
		CHECK_EQUAL(2, value);

		commandSystemProvider.beginBatchCommand();
		controller.invoke( incrementCounter, ReflectedMethodParameters() );
		controller.invoke( incrementCounter, ReflectedMethodParameters() );
		commandSystemProvider.abortBatchCommand();
		variantValue = controller.getValue( counter );
		CHECK(variantValue.tryCast( value ));
		CHECK_EQUAL(2, value);
	}
}