<commit_before>#include <Poco/Exception.h>
#include <Poco/Logger.h>
#include <Poco/Nullable.h>
#include <Poco/Timestamp.h>

#include "di/Injectable.h"
#include "gws/DevicePairHandler.h"
#include "gws/DeviceUnpairHandler.h"
#include "model/Device.h"
#include "model/Gateway.h"
#include "service/DeviceServiceImpl.h"

BEEEON_OBJECT_BEGIN(BeeeOn, DeviceServiceImpl)
BEEEON_OBJECT_CASTABLE(DeviceService)
BEEEON_OBJECT_REF("deviceDao", &DeviceServiceImpl::setDeviceDao)
BEEEON_OBJECT_REF("sensorHistoryDao", &DeviceServiceImpl::setSensorHistoryDao)
BEEEON_OBJECT_REF("devicePropertyDao", &DeviceServiceImpl::setDevicePropertyDao)
BEEEON_OBJECT_REF("gatewayRPC", &DeviceServiceImpl::setGatewayRPC)
BEEEON_OBJECT_REF("accessPolicy", &DeviceServiceImpl::setAccessPolicy)
BEEEON_OBJECT_REF("transactionManager", &DeviceServiceImpl::setTransactionManager)
BEEEON_OBJECT_END(BeeeOn, DeviceServiceImpl)

using namespace std;
using namespace Poco;
using namespace BeeeOn;

DeviceServiceImpl::DeviceServiceImpl()
{
}

void DeviceServiceImpl::setDeviceDao(DeviceDao::Ptr dao)
{
	m_dao = dao;
}

void DeviceServiceImpl::setSensorHistoryDao(SensorHistoryDao::Ptr dao)
{
	m_historyDao = dao;
}

void DeviceServiceImpl::setDevicePropertyDao(DevicePropertyDao::Ptr dao)
{
	m_propertyDao = dao;
}

void DeviceServiceImpl::setGatewayRPC(GatewayRPC::Ptr rpc)
{
	m_gatewayRPC = rpc;
}

void DeviceServiceImpl::setAccessPolicy(DeviceAccessPolicy::Ptr policy)
{
	m_policy = policy;
}

bool DeviceServiceImpl::doFetch(Relation<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.target(), input.base());
	return m_dao->fetch(input.target(), input.base());
}

void DeviceServiceImpl::valuesFor(DeviceWithData &device)
{
	// fetch last value of all device modules
	vector<ModuleInfo> modules;

	for (const auto &info : *device.type())
		modules.emplace_back(info);

	// values of all modules
	vector<ValueAt> values(modules.size());

	// a null result means that there is no data for that module yet
	vector<Nullable<ValueAt>> nullableValues;
	m_historyDao->fetchMany(device, modules, nullableValues);

	size_t i = 0;
	for (const auto &module : modules) {
		const auto &current = nullableValues.at(i++);
		const unsigned int index = module.id();

		if (!current.isNull())
			values[index] = current;

		// else leave the value as invalid
	}

	device.setValues(values);
}

void DeviceServiceImpl::doFetchMany(Single<list<Device>> &input)
{
	m_policy->assureMany(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.target());

	list<Device> &devices = input.target();
	m_dao->fetchMany(devices);
}

void DeviceServiceImpl::doFetchMany(Single<list<DeviceWithData>> &input)
{
	list<Device> devices;
	for (const auto &dev : input.target())
		devices.emplace_back(dev);

	m_dao->fetchMany(devices);

	// convert to list of DeviceWithData
	list<DeviceWithData> result;
	for (const auto &dev : devices) {
		DeviceWithData device = dev;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, device.gateway());
		} catch (const InvalidAccessException &e) {
			continue;
		}

		valuesFor(device);
		result.emplace_back(device);
	}

	input.target() = result;
}

void DeviceServiceImpl::doFetchMany(Relation<list<Device>, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET, input, input.base());

	list<Device> &devices = input.target();

	m_dao->fetchMany(devices);

	list<Device>::iterator it = devices.begin();

	while (it != devices.end()) {
		Device &device = *it;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, input.base());
		} catch (const InvalidAccessException &e) {
			// drop inaccessible devices
			it = devices.erase(it);
			continue;
		}

		++it; // no erase occured, continue
	}
}

/**
 * The method performs 1 + 2 * N Dao requests where N is the number of devices.
 * The first query obtains list of Device instances. Because we need a list
 * of DeviceWithData instances, the loop would convert it. The conversion
 * fetches module data for every single device.
 *
 * The method should be optimized (moved to Dao layer) if needed.
 */
void DeviceServiceImpl::doFetchMany(Relation<list<DeviceWithData>, Gateway> &input)
{
	// fetch list of Devices
	list<Device> devices;
	for (const auto &dev : input.target())
		devices.emplace_back(dev);

	m_policy->assureMany(DeviceAccessPolicy::ACTION_USER_GET, input, devices);

	m_dao->fetchMany(devices);

	// convert to list of DeviceWithData
	list<DeviceWithData> result;
	for (const auto &dev : devices) {
		DeviceWithData device = dev;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, input.base());
		} catch (const InvalidAccessException &e) {
			continue;
		}

		valuesFor(device);
		result.emplace_back(device);
	}

	input.target() = result;
}

void DeviceServiceImpl::doFetchActiveBy(Relation<vector<Device>, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base());
	m_dao->fetchActiveBy(input.target(), input.base());
}

void DeviceServiceImpl::doFetchActiveBy(Relation<vector<DeviceWithData>, Gateway> &input)
{
	// fetch list of Devices
	vector<Device> devices;
	for (const auto &dev : input.target())
		devices.emplace_back(dev);

	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base());
	m_dao->fetchActiveBy(devices, input.base());

	// convert to list of DeviceWithData
	vector<DeviceWithData> result;
	for (const auto &dev : devices) {
		DeviceWithData device = dev;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, input.base());
		} catch (const InvalidAccessException &e) {
			continue;
		}

		valuesFor(device);
		result.emplace_back(device);
	}

	input.target() = result;
}

void DeviceServiceImpl::doFetchInactiveBy(Relation<vector<Device>, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base());
	m_dao->fetchInactiveBy(input.target(), input.base());
}

void DeviceServiceImpl::doFetchInactiveBy(Relation<vector<DeviceWithData>, Gateway> &input)
{
	// fetch list of Devices
	vector<Device> devices;
	for (const auto &dev : input.target())
		devices.emplace_back(dev);

	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base());
	m_dao->fetchInactiveBy(devices, input.base());

	// convert to list of DeviceWithData
	vector<DeviceWithData> result;
	for (const auto &dev : devices) {
		DeviceWithData device = dev;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, input.base());
		} catch (const InvalidAccessException &e) {
			continue;
		}

		valuesFor(device);
		result.emplace_back(device);
	}

	input.target() = result;

}

void DeviceServiceImpl::doUnregister(Relation<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UNREGISTER,
			input, input.target(), input.base());

	Device &device = input.target();

	if (!m_dao->fetch(device, input.base()))
		throw NotFoundException("no such device " + device);

	if (!device.status().active())
		return;

	device.status().setState(DeviceStatus::STATE_INACTIVE_PENDING);
	device.status().setLastChanged({});

	if (!m_dao->update(device, input.base()))
		throw NotFoundException("device " + device + " seems to not exist");

	DeviceUnpairHandler::Ptr handler = new DeviceUnpairHandler(device, m_dao);
	handler->setTransactionManager(transactionManager());

	m_gatewayRPC->unpairDevice(handler, input.base(), device);
}

bool DeviceServiceImpl::doActivate(Relation<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_ACTIVATE,
			input, input.target(), input.base());

	Device &device = input.target();

	if (!m_dao->fetch(device, input.base()))
		return false;

	return tryActivateAndUpdate(device, input.base());
}

bool DeviceServiceImpl::tryActivateAndUpdate(Device &device,
		const Gateway &gateway, bool forceUpdate)
{
	const DeviceStatus &status = device.status();

	if (!status.active()) {
		device.status().setState(DeviceStatus::STATE_ACTIVE_PENDING);
		device.status().setLastChanged({});

		if (!m_dao->update(device, gateway))
			throw NotFoundException("device " + device + " seems to not exist");

		DevicePairHandler::Ptr handler = new DevicePairHandler(device, m_dao);
		handler->setTransactionManager(transactionManager());

		m_gatewayRPC->pairDevice(handler, gateway, device);
		return true;
	}

	return forceUpdate? m_dao->update(device, gateway) : false;
}

bool DeviceServiceImpl::prepareUpdate(RelationWithData<Device, Gateway> &input)
{
	if (!m_dao->fetch(input.target(), input.base()))
		return false;

	input.data().partial(input.target());
	return true;
}

bool DeviceServiceImpl::doUpdate(RelationWithData<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE,
			input, input.target(), input.base());

	if (!prepareUpdate(input))
		return false;

	return m_dao->update(input.target(), input.base());
}

bool DeviceServiceImpl::doUpdateAndActivate(
		RelationWithData<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE_AND_ACTIVATE,
			input, input.target(), input.base());

	if (!prepareUpdate(input))
		return false;

	return tryActivateAndUpdate(input.target(), input.base(), true);
}

bool DeviceServiceImpl::doCreateProperty(RelationWithData<DeviceProperty, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE,
			input, input.base(), gateway);

	input.data().full(input.target());

	return m_propertyDao->insert(input.target(), input.base());
}

bool DeviceServiceImpl::doUpdateProperty(RelationWithData<DeviceProperty, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE,
			input, input.base(), gateway);

	if (!m_propertyDao->fetch(input.target(), input.base()))
		return false;

	input.data().partial(input.target());

	return m_propertyDao->update(input.target(), input.base());
}

bool DeviceServiceImpl::doRemoveProperty(Relation<const DeviceProperty, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE,
			input, input.base(), gateway);

	return m_propertyDao->remove(input.target(), input.base());
}

bool DeviceServiceImpl::doFindProperty(Relation<DeviceProperty, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base(), gateway);

	return m_propertyDao->fetch(input.target(), input.base());
}

void DeviceServiceImpl::doListProperties(Relation<list<DeviceProperty>, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base(), gateway);

	return m_propertyDao->fetchByDevice(input.target(), input.base());
}
<commit_msg>DeviceServiceImpl: do not fail when a device is missing a type<commit_after>#include <Poco/Exception.h>
#include <Poco/Logger.h>
#include <Poco/Nullable.h>
#include <Poco/Timestamp.h>

#include "di/Injectable.h"
#include "gws/DevicePairHandler.h"
#include "gws/DeviceUnpairHandler.h"
#include "model/Device.h"
#include "model/Gateway.h"
#include "service/DeviceServiceImpl.h"

BEEEON_OBJECT_BEGIN(BeeeOn, DeviceServiceImpl)
BEEEON_OBJECT_CASTABLE(DeviceService)
BEEEON_OBJECT_REF("deviceDao", &DeviceServiceImpl::setDeviceDao)
BEEEON_OBJECT_REF("sensorHistoryDao", &DeviceServiceImpl::setSensorHistoryDao)
BEEEON_OBJECT_REF("devicePropertyDao", &DeviceServiceImpl::setDevicePropertyDao)
BEEEON_OBJECT_REF("gatewayRPC", &DeviceServiceImpl::setGatewayRPC)
BEEEON_OBJECT_REF("accessPolicy", &DeviceServiceImpl::setAccessPolicy)
BEEEON_OBJECT_REF("transactionManager", &DeviceServiceImpl::setTransactionManager)
BEEEON_OBJECT_END(BeeeOn, DeviceServiceImpl)

using namespace std;
using namespace Poco;
using namespace BeeeOn;

DeviceServiceImpl::DeviceServiceImpl()
{
}

void DeviceServiceImpl::setDeviceDao(DeviceDao::Ptr dao)
{
	m_dao = dao;
}

void DeviceServiceImpl::setSensorHistoryDao(SensorHistoryDao::Ptr dao)
{
	m_historyDao = dao;
}

void DeviceServiceImpl::setDevicePropertyDao(DevicePropertyDao::Ptr dao)
{
	m_propertyDao = dao;
}

void DeviceServiceImpl::setGatewayRPC(GatewayRPC::Ptr rpc)
{
	m_gatewayRPC = rpc;
}

void DeviceServiceImpl::setAccessPolicy(DeviceAccessPolicy::Ptr policy)
{
	m_policy = policy;
}

bool DeviceServiceImpl::doFetch(Relation<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.target(), input.base());
	return m_dao->fetch(input.target(), input.base());
}

void DeviceServiceImpl::valuesFor(DeviceWithData &device)
{
	// fetch last value of all device modules
	vector<ModuleInfo> modules;

	if (device.type().isNull()) {
		throw IllegalStateException(
			"device " + device + " does not have any known type");
	}

	for (const auto &info : *device.type())
		modules.emplace_back(info);

	// values of all modules
	vector<ValueAt> values(modules.size());

	// a null result means that there is no data for that module yet
	vector<Nullable<ValueAt>> nullableValues;
	m_historyDao->fetchMany(device, modules, nullableValues);

	size_t i = 0;
	for (const auto &module : modules) {
		const auto &current = nullableValues.at(i++);
		const unsigned int index = module.id();

		if (!current.isNull())
			values[index] = current;

		// else leave the value as invalid
	}

	device.setValues(values);
}

void DeviceServiceImpl::doFetchMany(Single<list<Device>> &input)
{
	m_policy->assureMany(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.target());

	list<Device> &devices = input.target();
	m_dao->fetchMany(devices);
}

void DeviceServiceImpl::doFetchMany(Single<list<DeviceWithData>> &input)
{
	list<Device> devices;
	for (const auto &dev : input.target())
		devices.emplace_back(dev);

	m_dao->fetchMany(devices);

	// convert to list of DeviceWithData
	list<DeviceWithData> result;
	for (const auto &dev : devices) {
		DeviceWithData device = dev;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, device.gateway());
		} catch (const InvalidAccessException &e) {
			continue;
		}

		try {
			valuesFor(device);
		}
		catch (const Exception &e) {
			logger().log(e, __FILE__, __LINE__);
			continue; // skip failing devices
		}

		result.emplace_back(device);
	}

	input.target() = result;
}

void DeviceServiceImpl::doFetchMany(Relation<list<Device>, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET, input, input.base());

	list<Device> &devices = input.target();

	m_dao->fetchMany(devices);

	list<Device>::iterator it = devices.begin();

	while (it != devices.end()) {
		Device &device = *it;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, input.base());
		} catch (const InvalidAccessException &e) {
			// drop inaccessible devices
			it = devices.erase(it);
			continue;
		}

		++it; // no erase occured, continue
	}
}

/**
 * The method performs 1 + 2 * N Dao requests where N is the number of devices.
 * The first query obtains list of Device instances. Because we need a list
 * of DeviceWithData instances, the loop would convert it. The conversion
 * fetches module data for every single device.
 *
 * The method should be optimized (moved to Dao layer) if needed.
 */
void DeviceServiceImpl::doFetchMany(Relation<list<DeviceWithData>, Gateway> &input)
{
	// fetch list of Devices
	list<Device> devices;
	for (const auto &dev : input.target())
		devices.emplace_back(dev);

	m_policy->assureMany(DeviceAccessPolicy::ACTION_USER_GET, input, devices);

	m_dao->fetchMany(devices);

	// convert to list of DeviceWithData
	list<DeviceWithData> result;
	for (const auto &dev : devices) {
		DeviceWithData device = dev;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, input.base());
		} catch (const InvalidAccessException &e) {
			continue;
		}

		try {
			valuesFor(device);
		}
		catch (const Exception &e) {
			logger().log(e, __FILE__, __LINE__);
			continue; // skip failing devices
		}

		result.emplace_back(device);
	}

	input.target() = result;
}

void DeviceServiceImpl::doFetchActiveBy(Relation<vector<Device>, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base());
	m_dao->fetchActiveBy(input.target(), input.base());
}

void DeviceServiceImpl::doFetchActiveBy(Relation<vector<DeviceWithData>, Gateway> &input)
{
	// fetch list of Devices
	vector<Device> devices;
	for (const auto &dev : input.target())
		devices.emplace_back(dev);

	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base());
	m_dao->fetchActiveBy(devices, input.base());

	// convert to list of DeviceWithData
	vector<DeviceWithData> result;
	for (const auto &dev : devices) {
		DeviceWithData device = dev;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, input.base());
		} catch (const InvalidAccessException &e) {
			continue;
		}

		try {
			valuesFor(device);
		}
		catch (const Exception &e) {
			logger().log(e, __FILE__, __LINE__);
			continue; // skip failing devices
		}

		result.emplace_back(device);
	}

	input.target() = result;
}

void DeviceServiceImpl::doFetchInactiveBy(Relation<vector<Device>, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base());
	m_dao->fetchInactiveBy(input.target(), input.base());
}

void DeviceServiceImpl::doFetchInactiveBy(Relation<vector<DeviceWithData>, Gateway> &input)
{
	// fetch list of Devices
	vector<Device> devices;
	for (const auto &dev : input.target())
		devices.emplace_back(dev);

	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base());
	m_dao->fetchInactiveBy(devices, input.base());

	// convert to list of DeviceWithData
	vector<DeviceWithData> result;
	for (const auto &dev : devices) {
		DeviceWithData device = dev;

		try {
			m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
					input, device, input.base());
		} catch (const InvalidAccessException &e) {
			continue;
		}

		try {
			valuesFor(device);
		}
		catch (const Exception &e) {
			logger().log(e, __FILE__, __LINE__);
			continue; // skip failing devices
		}

		result.emplace_back(device);
	}

	input.target() = result;

}

void DeviceServiceImpl::doUnregister(Relation<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UNREGISTER,
			input, input.target(), input.base());

	Device &device = input.target();

	if (!m_dao->fetch(device, input.base()))
		throw NotFoundException("no such device " + device);

	if (!device.status().active())
		return;

	device.status().setState(DeviceStatus::STATE_INACTIVE_PENDING);
	device.status().setLastChanged({});

	if (!m_dao->update(device, input.base()))
		throw NotFoundException("device " + device + " seems to not exist");

	DeviceUnpairHandler::Ptr handler = new DeviceUnpairHandler(device, m_dao);
	handler->setTransactionManager(transactionManager());

	m_gatewayRPC->unpairDevice(handler, input.base(), device);
}

bool DeviceServiceImpl::doActivate(Relation<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_ACTIVATE,
			input, input.target(), input.base());

	Device &device = input.target();

	if (!m_dao->fetch(device, input.base()))
		return false;

	return tryActivateAndUpdate(device, input.base());
}

bool DeviceServiceImpl::tryActivateAndUpdate(Device &device,
		const Gateway &gateway, bool forceUpdate)
{
	const DeviceStatus &status = device.status();

	if (!status.active()) {
		device.status().setState(DeviceStatus::STATE_ACTIVE_PENDING);
		device.status().setLastChanged({});

		if (!m_dao->update(device, gateway))
			throw NotFoundException("device " + device + " seems to not exist");

		DevicePairHandler::Ptr handler = new DevicePairHandler(device, m_dao);
		handler->setTransactionManager(transactionManager());

		m_gatewayRPC->pairDevice(handler, gateway, device);
		return true;
	}

	return forceUpdate? m_dao->update(device, gateway) : false;
}

bool DeviceServiceImpl::prepareUpdate(RelationWithData<Device, Gateway> &input)
{
	if (!m_dao->fetch(input.target(), input.base()))
		return false;

	input.data().partial(input.target());
	return true;
}

bool DeviceServiceImpl::doUpdate(RelationWithData<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE,
			input, input.target(), input.base());

	if (!prepareUpdate(input))
		return false;

	return m_dao->update(input.target(), input.base());
}

bool DeviceServiceImpl::doUpdateAndActivate(
		RelationWithData<Device, Gateway> &input)
{
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE_AND_ACTIVATE,
			input, input.target(), input.base());

	if (!prepareUpdate(input))
		return false;

	return tryActivateAndUpdate(input.target(), input.base(), true);
}

bool DeviceServiceImpl::doCreateProperty(RelationWithData<DeviceProperty, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE,
			input, input.base(), gateway);

	input.data().full(input.target());

	return m_propertyDao->insert(input.target(), input.base());
}

bool DeviceServiceImpl::doUpdateProperty(RelationWithData<DeviceProperty, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE,
			input, input.base(), gateway);

	if (!m_propertyDao->fetch(input.target(), input.base()))
		return false;

	input.data().partial(input.target());

	return m_propertyDao->update(input.target(), input.base());
}

bool DeviceServiceImpl::doRemoveProperty(Relation<const DeviceProperty, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_UPDATE,
			input, input.base(), gateway);

	return m_propertyDao->remove(input.target(), input.base());
}

bool DeviceServiceImpl::doFindProperty(Relation<DeviceProperty, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base(), gateway);

	return m_propertyDao->fetch(input.target(), input.base());
}

void DeviceServiceImpl::doListProperties(Relation<list<DeviceProperty>, Device> &input)
{
	const Gateway &gateway = input.base().gateway();
	m_policy->assure(DeviceAccessPolicy::ACTION_USER_GET,
			input, input.base(), gateway);

	return m_propertyDao->fetchByDevice(input.target(), input.base());
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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 <vector>

#include "grpc/support/log.h"

#include <node.h>
#include <nan.h>
#include "grpc/grpc.h"
#include "grpc/grpc_security.h"
#include "call.h"
#include "channel.h"
#include "completion_queue_async_worker.h"
#include "channel_credentials.h"
#include "timeval.h"

namespace grpc {
namespace node {

using Nan::Callback;
using Nan::EscapableHandleScope;
using Nan::HandleScope;
using Nan::Maybe;
using Nan::MaybeLocal;
using Nan::ObjectWrap;
using Nan::Persistent;
using Nan::Utf8String;

using v8::Array;
using v8::Exception;
using v8::Function;
using v8::FunctionTemplate;
using v8::Integer;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

Callback *Channel::constructor;
Persistent<FunctionTemplate> Channel::fun_tpl;

bool ParseChannelArgs(Local<Value> args_val,
                      grpc_channel_args **channel_args_ptr) {
  if (args_val->IsUndefined() || args_val->IsNull()) {
    *channel_args_ptr = NULL;
    return true;
  }
  if (!args_val->IsObject()) {
    *channel_args_ptr = NULL;
    return false;
  }
  grpc_channel_args *channel_args = reinterpret_cast<grpc_channel_args*>(
      malloc(sizeof(channel_args)));
  *channel_args_ptr = channel_args;
  Local<Object> args_hash = Nan::To<Object>(args_val).ToLocalChecked();
  Local<Array> keys = Nan::GetOwnPropertyNames(args_hash).ToLocalChecked();
  channel_args->num_args = keys->Length();
  channel_args->args = reinterpret_cast<grpc_arg *>(
      calloc(channel_args->num_args, sizeof(grpc_arg)));
  for (unsigned int i = 0; i < channel_args->num_args; i++) {
    Local<Value> key = Nan::Get(keys, i).ToLocalChecked();
    Utf8String key_str(key);
    if (*key_str == NULL) {
      // Key string onversion failed
      return false;
    }
    Local<Value> value = Nan::Get(args_hash, key).ToLocalChecked();
    if (value->IsInt32()) {
      channel_args->args[i].type = GRPC_ARG_INTEGER;
      channel_args->args[i].value.integer = Nan::To<int32_t>(value).FromJust();
    } else if (value->IsString()) {
      Utf8String val_str(value);
      channel_args->args[i].type = GRPC_ARG_STRING;
      channel_args->args[i].value.string = reinterpret_cast<char*>(
          calloc(val_str.length() + 1,sizeof(char)));
      memcpy(channel_args->args[i].value.string,
             *val_str, val_str.length() + 1);
    } else {
      // The value does not match either of the accepted types
      return false;
    }
    channel_args->args[i].key = reinterpret_cast<char*>(
        calloc(key_str.length() + 1, sizeof(char)));
    memcpy(channel_args->args[i].key, *key_str, key_str.length() + 1);
  }
  return true;
}

void DeallocateChannelArgs(grpc_channel_args *channel_args) {
  if (channel_args == NULL) {
    return;
  }
  for (size_t i = 0; i < channel_args->num_args; i++) {
    if (channel_args->args[i].key == NULL) {
      /* NULL key implies that this argument and all subsequent arguments failed
       * to parse */
      break;
    }
    free(channel_args->args[i].key);
    if (channel_args->args[i].type == GRPC_ARG_STRING) {
      free(channel_args->args[i].value.string);
    }
  }
  free(channel_args->args);
  free(channel_args);
}

Channel::Channel(grpc_channel *channel) : wrapped_channel(channel) {}

Channel::~Channel() {
  if (wrapped_channel != NULL) {
    grpc_channel_destroy(wrapped_channel);
  }
}

void Channel::Init(Local<Object> exports) {
  Nan::HandleScope scope;
  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("Channel").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  Nan::SetPrototypeMethod(tpl, "close", Close);
  Nan::SetPrototypeMethod(tpl, "getTarget", GetTarget);
  Nan::SetPrototypeMethod(tpl, "getConnectivityState", GetConnectivityState);
  Nan::SetPrototypeMethod(tpl, "watchConnectivityState",
                          WatchConnectivityState);
  fun_tpl.Reset(tpl);
  Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
  Nan::Set(exports, Nan::New("Channel").ToLocalChecked(), ctr);
  constructor = new Callback(ctr);
}

bool Channel::HasInstance(Local<Value> val) {
  HandleScope scope;
  return Nan::New(fun_tpl)->HasInstance(val);
}

grpc_channel *Channel::GetWrappedChannel() { return this->wrapped_channel; }

NAN_METHOD(Channel::New) {
  if (info.IsConstructCall()) {
    if (!info[0]->IsString()) {
      return Nan::ThrowTypeError(
          "Channel expects a string, a credential and an object");
    }
    grpc_channel *wrapped_channel;
    // Owned by the Channel object
    Utf8String host(info[0]);
    grpc_credentials *creds;
    if (!ChannelCredentials::HasInstance(info[1])) {
      return Nan::ThrowTypeError(
          "Channel's second argument must be a ChannelCredentials");
    }
    ChannelCredentials *creds_object = ObjectWrap::Unwrap<ChannelCredentials>(
        Nan::To<Object>(info[1]).ToLocalChecked());
    creds = creds_object->GetWrappedCredentials();
    grpc_channel_args *channel_args_ptr = NULL;
    if (!ParseChannelArgs(info[2], &channel_args_ptr)) {
      DeallocateChannelArgs(channel_args_ptr);
      return Nan::ThrowTypeError("Channel options must be an object with "
                                 "string keys and integer or string values");
    }
    if (creds == NULL) {
      wrapped_channel = grpc_insecure_channel_create(*host, channel_args_ptr,
                                                     NULL);
    } else {
      wrapped_channel =
          grpc_secure_channel_create(creds, *host, channel_args_ptr, NULL);
    }
    DeallocateChannelArgs(channel_args_ptr);
    Channel *channel = new Channel(wrapped_channel);
    channel->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
    return;
  } else {
    const int argc = 3;
    Local<Value> argv[argc] = {info[0], info[1], info[2]};
    MaybeLocal<Object> maybe_instance = constructor->GetFunction()->NewInstance(
        argc, argv);
    if (maybe_instance.IsEmpty()) {
      // There's probably a pending exception
      return;
    } else {
      info.GetReturnValue().Set(maybe_instance.ToLocalChecked());
    }
  }
}

NAN_METHOD(Channel::Close) {
  if (!HasInstance(info.This())) {
    return Nan::ThrowTypeError("close can only be called on Channel objects");
  }
  Channel *channel = ObjectWrap::Unwrap<Channel>(info.This());
  if (channel->wrapped_channel != NULL) {
    grpc_channel_destroy(channel->wrapped_channel);
    channel->wrapped_channel = NULL;
  }
}

NAN_METHOD(Channel::GetTarget) {
  if (!HasInstance(info.This())) {
    return Nan::ThrowTypeError("getTarget can only be called on Channel objects");
  }
  Channel *channel = ObjectWrap::Unwrap<Channel>(info.This());
  info.GetReturnValue().Set(Nan::New(
      grpc_channel_get_target(channel->wrapped_channel)).ToLocalChecked());
}

NAN_METHOD(Channel::GetConnectivityState) {
  if (!HasInstance(info.This())) {
    return Nan::ThrowTypeError(
        "getConnectivityState can only be called on Channel objects");
  }
  Channel *channel = ObjectWrap::Unwrap<Channel>(info.This());
  int try_to_connect = (int)info[0]->Equals(Nan::True());
  info.GetReturnValue().Set(
      grpc_channel_check_connectivity_state(channel->wrapped_channel,
                                            try_to_connect));
}

NAN_METHOD(Channel::WatchConnectivityState) {
  if (!HasInstance(info.This())) {
    return Nan::ThrowTypeError(
        "watchConnectivityState can only be called on Channel objects");
  }
  if (!info[0]->IsUint32()) {
    return Nan::ThrowTypeError(
        "watchConnectivityState's first argument must be a channel state");
  }
  if (!(info[1]->IsNumber() || info[1]->IsDate())) {
    return Nan::ThrowTypeError(
        "watchConnectivityState's second argument must be a date or a number");
  }
  if (!info[2]->IsFunction()) {
    return Nan::ThrowTypeError(
        "watchConnectivityState's third argument must be a callback");
  }
  grpc_connectivity_state last_state =
      static_cast<grpc_connectivity_state>(
          Nan::To<uint32_t>(info[0]).FromJust());
  double deadline = Nan::To<double>(info[1]).FromJust();
  Local<Function> callback_func = info[2].As<Function>();
  Nan::Callback *callback = new Callback(callback_func);
  Channel *channel = ObjectWrap::Unwrap<Channel>(info.This());
  unique_ptr<OpVec> ops(new OpVec());
  grpc_channel_watch_connectivity_state(
      channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline),
      CompletionQueueAsyncWorker::GetQueue(),
      new struct tag(callback,
                     ops.release(),
                     shared_ptr<Resources>(nullptr)));
  CompletionQueueAsyncWorker::Next();
}

}  // namespace node
}  // namespace grpc
<commit_msg>Fixed incorrect type in a malloc in Node extension<commit_after>/*
 *
 * Copyright 2015, 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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 <vector>

#include "grpc/support/log.h"

#include <node.h>
#include <nan.h>
#include "grpc/grpc.h"
#include "grpc/grpc_security.h"
#include "call.h"
#include "channel.h"
#include "completion_queue_async_worker.h"
#include "channel_credentials.h"
#include "timeval.h"

namespace grpc {
namespace node {

using Nan::Callback;
using Nan::EscapableHandleScope;
using Nan::HandleScope;
using Nan::Maybe;
using Nan::MaybeLocal;
using Nan::ObjectWrap;
using Nan::Persistent;
using Nan::Utf8String;

using v8::Array;
using v8::Exception;
using v8::Function;
using v8::FunctionTemplate;
using v8::Integer;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;

Callback *Channel::constructor;
Persistent<FunctionTemplate> Channel::fun_tpl;

bool ParseChannelArgs(Local<Value> args_val,
                      grpc_channel_args **channel_args_ptr) {
  if (args_val->IsUndefined() || args_val->IsNull()) {
    *channel_args_ptr = NULL;
    return true;
  }
  if (!args_val->IsObject()) {
    *channel_args_ptr = NULL;
    return false;
  }
  grpc_channel_args *channel_args = reinterpret_cast<grpc_channel_args*>(
      malloc(sizeof(grpc_channel_args)));
  *channel_args_ptr = channel_args;
  Local<Object> args_hash = Nan::To<Object>(args_val).ToLocalChecked();
  Local<Array> keys = Nan::GetOwnPropertyNames(args_hash).ToLocalChecked();
  channel_args->num_args = keys->Length();
  channel_args->args = reinterpret_cast<grpc_arg *>(
      calloc(channel_args->num_args, sizeof(grpc_arg)));
  for (unsigned int i = 0; i < channel_args->num_args; i++) {
    Local<Value> key = Nan::Get(keys, i).ToLocalChecked();
    Utf8String key_str(key);
    if (*key_str == NULL) {
      // Key string onversion failed
      return false;
    }
    Local<Value> value = Nan::Get(args_hash, key).ToLocalChecked();
    if (value->IsInt32()) {
      channel_args->args[i].type = GRPC_ARG_INTEGER;
      channel_args->args[i].value.integer = Nan::To<int32_t>(value).FromJust();
    } else if (value->IsString()) {
      Utf8String val_str(value);
      channel_args->args[i].type = GRPC_ARG_STRING;
      channel_args->args[i].value.string = reinterpret_cast<char*>(
          calloc(val_str.length() + 1,sizeof(char)));
      memcpy(channel_args->args[i].value.string,
             *val_str, val_str.length() + 1);
    } else {
      // The value does not match either of the accepted types
      return false;
    }
    channel_args->args[i].key = reinterpret_cast<char*>(
        calloc(key_str.length() + 1, sizeof(char)));
    memcpy(channel_args->args[i].key, *key_str, key_str.length() + 1);
  }
  return true;
}

void DeallocateChannelArgs(grpc_channel_args *channel_args) {
  if (channel_args == NULL) {
    return;
  }
  for (size_t i = 0; i < channel_args->num_args; i++) {
    if (channel_args->args[i].key == NULL) {
      /* NULL key implies that this argument and all subsequent arguments failed
       * to parse */
      break;
    }
    free(channel_args->args[i].key);
    if (channel_args->args[i].type == GRPC_ARG_STRING) {
      free(channel_args->args[i].value.string);
    }
  }
  free(channel_args->args);
  free(channel_args);
}

Channel::Channel(grpc_channel *channel) : wrapped_channel(channel) {}

Channel::~Channel() {
  if (wrapped_channel != NULL) {
    grpc_channel_destroy(wrapped_channel);
  }
}

void Channel::Init(Local<Object> exports) {
  Nan::HandleScope scope;
  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("Channel").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  Nan::SetPrototypeMethod(tpl, "close", Close);
  Nan::SetPrototypeMethod(tpl, "getTarget", GetTarget);
  Nan::SetPrototypeMethod(tpl, "getConnectivityState", GetConnectivityState);
  Nan::SetPrototypeMethod(tpl, "watchConnectivityState",
                          WatchConnectivityState);
  fun_tpl.Reset(tpl);
  Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
  Nan::Set(exports, Nan::New("Channel").ToLocalChecked(), ctr);
  constructor = new Callback(ctr);
}

bool Channel::HasInstance(Local<Value> val) {
  HandleScope scope;
  return Nan::New(fun_tpl)->HasInstance(val);
}

grpc_channel *Channel::GetWrappedChannel() { return this->wrapped_channel; }

NAN_METHOD(Channel::New) {
  if (info.IsConstructCall()) {
    if (!info[0]->IsString()) {
      return Nan::ThrowTypeError(
          "Channel expects a string, a credential and an object");
    }
    grpc_channel *wrapped_channel;
    // Owned by the Channel object
    Utf8String host(info[0]);
    grpc_credentials *creds;
    if (!ChannelCredentials::HasInstance(info[1])) {
      return Nan::ThrowTypeError(
          "Channel's second argument must be a ChannelCredentials");
    }
    ChannelCredentials *creds_object = ObjectWrap::Unwrap<ChannelCredentials>(
        Nan::To<Object>(info[1]).ToLocalChecked());
    creds = creds_object->GetWrappedCredentials();
    grpc_channel_args *channel_args_ptr = NULL;
    if (!ParseChannelArgs(info[2], &channel_args_ptr)) {
      DeallocateChannelArgs(channel_args_ptr);
      return Nan::ThrowTypeError("Channel options must be an object with "
                                 "string keys and integer or string values");
    }
    if (creds == NULL) {
      wrapped_channel = grpc_insecure_channel_create(*host, channel_args_ptr,
                                                     NULL);
    } else {
      wrapped_channel =
          grpc_secure_channel_create(creds, *host, channel_args_ptr, NULL);
    }
    DeallocateChannelArgs(channel_args_ptr);
    Channel *channel = new Channel(wrapped_channel);
    channel->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
    return;
  } else {
    const int argc = 3;
    Local<Value> argv[argc] = {info[0], info[1], info[2]};
    MaybeLocal<Object> maybe_instance = constructor->GetFunction()->NewInstance(
        argc, argv);
    if (maybe_instance.IsEmpty()) {
      // There's probably a pending exception
      return;
    } else {
      info.GetReturnValue().Set(maybe_instance.ToLocalChecked());
    }
  }
}

NAN_METHOD(Channel::Close) {
  if (!HasInstance(info.This())) {
    return Nan::ThrowTypeError("close can only be called on Channel objects");
  }
  Channel *channel = ObjectWrap::Unwrap<Channel>(info.This());
  if (channel->wrapped_channel != NULL) {
    grpc_channel_destroy(channel->wrapped_channel);
    channel->wrapped_channel = NULL;
  }
}

NAN_METHOD(Channel::GetTarget) {
  if (!HasInstance(info.This())) {
    return Nan::ThrowTypeError("getTarget can only be called on Channel objects");
  }
  Channel *channel = ObjectWrap::Unwrap<Channel>(info.This());
  info.GetReturnValue().Set(Nan::New(
      grpc_channel_get_target(channel->wrapped_channel)).ToLocalChecked());
}

NAN_METHOD(Channel::GetConnectivityState) {
  if (!HasInstance(info.This())) {
    return Nan::ThrowTypeError(
        "getConnectivityState can only be called on Channel objects");
  }
  Channel *channel = ObjectWrap::Unwrap<Channel>(info.This());
  int try_to_connect = (int)info[0]->Equals(Nan::True());
  info.GetReturnValue().Set(
      grpc_channel_check_connectivity_state(channel->wrapped_channel,
                                            try_to_connect));
}

NAN_METHOD(Channel::WatchConnectivityState) {
  if (!HasInstance(info.This())) {
    return Nan::ThrowTypeError(
        "watchConnectivityState can only be called on Channel objects");
  }
  if (!info[0]->IsUint32()) {
    return Nan::ThrowTypeError(
        "watchConnectivityState's first argument must be a channel state");
  }
  if (!(info[1]->IsNumber() || info[1]->IsDate())) {
    return Nan::ThrowTypeError(
        "watchConnectivityState's second argument must be a date or a number");
  }
  if (!info[2]->IsFunction()) {
    return Nan::ThrowTypeError(
        "watchConnectivityState's third argument must be a callback");
  }
  grpc_connectivity_state last_state =
      static_cast<grpc_connectivity_state>(
          Nan::To<uint32_t>(info[0]).FromJust());
  double deadline = Nan::To<double>(info[1]).FromJust();
  Local<Function> callback_func = info[2].As<Function>();
  Nan::Callback *callback = new Callback(callback_func);
  Channel *channel = ObjectWrap::Unwrap<Channel>(info.This());
  unique_ptr<OpVec> ops(new OpVec());
  grpc_channel_watch_connectivity_state(
      channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline),
      CompletionQueueAsyncWorker::GetQueue(),
      new struct tag(callback,
                     ops.release(),
                     shared_ptr<Resources>(nullptr)));
  CompletionQueueAsyncWorker::Next();
}

}  // namespace node
}  // namespace grpc
<|endoftext|>


<commit_before>#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/PassRegistry.h"
#include "ExpertSystem/KnowledgeConstructionEngine.h"
#include "pipeline/clips/CLIPSPassGenerator.h"
#include "pipeline/clips/CLIPSPass.h"
#include "pipeline/clips/CLIPSPassHeader.h"
#include "rampancy/Cortex.h"
#include "rampancy/CompilerManager.h"
#include "rampancy/CompilerRegistry.h"
#include "indirect/Indirector.h"
#include "llvm/Support/raw_ostream.h"

extern "C" {
#include "clips.h"
}

using namespace llvm;
using namespace indirect;
extern "C" void CLIPSOptimizeCode(void* theEnv);
extern "C" void CLIPSRegisterPass(void* theEnv);
extern "C" void CLIPSUnregisterPass(void* theEnv);
extern "C" void* CLIPSPassRegistered(void* theEnv);
#define pass_registered (char*)"pass-registered"
#define optimize (char*)"optimize"
#define unregister_pass (char*)"unregister-pass"
#define register_pass (char*)"register-pass"
#define werror (char*)"werror"
#define msg(x) (char*) x
#define copy(from, to) \
	to = CharBuffer(strlen(from)); \
sprintf(to, "%s", from)
#define BoolCast(str, tgt) tgt = (strcmp(str, "TRUE") == 0) ? TRUE : FALSE

extern "C" void RegisterCLIPSPipelineFunctions(void* theEnv) {
	EnvDefineFunction(theEnv, optimize, 'v',
			PTIEF CLIPSOptimizeCode, "CLIPSOptimizeCode");
	EnvDefineFunction(theEnv, register_pass, 'v',
			PTIEF CLIPSRegisterPass, "CLIPSRegisterPass");
	EnvDefineFunction(theEnv, unregister_pass, 'v',
			PTIEF CLIPSUnregisterPass, "CLIPSUnregisterPass");
	EnvDefineFunction2(theEnv, pass_registered, 'w',
			PTIEF CLIPSPassRegistered, "CLIPSPassRegistered",
			"11k");
}

void CLIPSOptimizeCode(void* theEnv) {

}

void CLIPSRegisterPass(void* theEnv) {
	/* register-pass has the following arguments
	 * 1) name (PassArg)
	 * 2) description (PassName)
	 * 3) type (string)
	 * 4) IsAnalysis (bool)
	 * 5) isCFGPass (bool)
	 * 6) needRegions (bool)
	 * 7) needLoops (bool)
	 * 8) passes (multifield)
	 * 9) required (multifield)
	 * 10) required-transitive (multifield)
	 * 11) Preserved (multifield)
	 * 12) preservesAll (bool)
	 * 13) preservesCFG (bool);
	 */

	void* passes;
	void* required;
	void* requiredTransitive;
	void* preserved;
	DATA_OBJECT arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
					arg10, arg11, arg12;
	char *tmp0, *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6, *tmp7, *tmp8, *tmp9,
		  *tmp10;
	char* pArg;
	char* pName;
	bool isAnalysis, isCFG,
		  needRegions, needLoops,
		  preservesAll, preservesCFG;
	char* type;
	long long l0, l1, l2, l3;
	std::string tmp;
	raw_string_ostream stream(tmp);
	pipeline::clips::CLIPSPassHeader* header = new pipeline::clips::CLIPSPassHeader();
	header->setTemplateSet("clips");
	if(EnvArgCountCheck(theEnv, register_pass, EXACTLY, 13) == -1) {
		return;
	}

	if(EnvArgTypeCheck(theEnv, register_pass, 1, SYMBOL_OR_STRING, &arg0) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 2, SYMBOL_OR_STRING, &arg1) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 3, SYMBOL_OR_STRING, &arg2) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 4, SYMBOL, &arg3) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 5, SYMBOL, &arg4) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 6, SYMBOL, &arg5) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 7, SYMBOL, &arg6) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 8, MULTIFIELD, &arg7) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 9, MULTIFIELD, &arg8) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 10, MULTIFIELD, &arg9) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 11, MULTIFIELD, &arg10) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 12, SYMBOL, &arg11) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 13, SYMBOL, &arg12) == FALSE) {
		return;
	}
	tmp0 = DOToString(arg0);
	copy(tmp0, pArg);
	header->setPassName((const char*)pArg);
	tmp1 = DOToString(arg1);
	copy(tmp1, pName);
	header->setPassDescription((const char*)pName);
	tmp2 = DOToString(arg2);
	copy(tmp2, type);
	header->setPassType(type);
	tmp3 = DOToString(arg3);
	BoolCast(tmp3, isAnalysis);
	header->setIsAnalysis(isAnalysis);
	tmp4 = DOToString(arg4);
	BoolCast(tmp4, isCFG);
	header->setIsCFGOnlyPass(isCFG);
	tmp5 = DOToString(arg5);
	BoolCast(tmp5, needRegions);
	header->setNeedsRegions(needRegions);
	tmp6 = DOToString(arg6);
	BoolCast(tmp6, needLoops);
	header->setNeedsLoops(needLoops);
	//l0 = (long long)GetDOLength(arg7);
	//l1 = (long long)GetDOLength(arg8);
	//aUsage = GetValue(arg7);

   IndirectPassRegistry& indirectRegistry = *IndirectPassRegistry::getIndirectPassRegistry();
	indirectRegistry.registerIndirectPassHeader(header);
	free(pArg);
	free(pName);
	free(type);

}

void CLIPSUnregisterPass(void* theEnv) {

}

void* CLIPSPassRegistered(void* theEnv) {
	DATA_OBJECT arg0;
	char* a;
	char* b;
	if(EnvArgCountCheck(theEnv, pass_registered, EXACTLY, 1) == -1) {
		return FalseSymbol();
	}

	if(EnvArgTypeCheck(theEnv, pass_registered, 1, SYMBOL_OR_STRING, &arg0) == FALSE) {
		return FalseSymbol();
	}
	a = DOToString(arg0);
	copy(a, b);

	llvm::PassRegistry* registry = llvm::PassRegistry::getPassRegistry();
	const llvm::PassInfo* pi = registry->getPassInfo(llvm::StringRef(b));
	free(b);
	if(pi) {
		return TrueSymbol();
	} else {
		return FalseSymbol();
	}
}
/*
	llvm::PassManager tmpPassManager;
	llvm::PassManagerBuilder builder;
//taken from opt
llvm::TargetLibraryInfo *tli =
new llvm::TargetLibraryInfo(llvm::Triple(module->getTargetTriple()));
tmpPassManager.add(tli);
llvm::TargetData *td = 0;
const std::string &moduleDataLayout = module->getDataLayout();
if(!moduleDataLayout.empty())
td = new llvm::TargetData(moduleDataLayout);
if(td)
tmpPassManager.add(td);
llvm::PassManager& PM = tmpPassManager;
//add em all!
builder.OptLevel = 2;
builder.DisableSimplifyLibCalls = false;
builder.populateModulePassManager(PM);
//let's see if this fixes the issue
llvm::PassRegistry* registry = llvm::PassRegistry::getPassRegistry();
const llvm::PassInfo* ci = registry->getPassInfo(
llvm::StringRef("function-to-knowledge"));
const llvm::PassInfo* ls = registry->getPassInfo(
llvm::StringRef("loop-simplify"));
const llvm::PassInfo* bce = registry->getPassInfo(
llvm::StringRef("break-crit-edges"));
ExpertSystem::FunctionKnowledgeConversionPass* copy =
(ExpertSystem::FunctionKnowledgeConversionPass*)ci->createPass();
copy->setEnvironment(tEnv);
tmpPassManager.add(ls->createPass());
tmpPassManager.add(bce->createPass());
tmpPassManager.add(copy);
tmpPassManager.add(llvm::createVerifierPass());
tmpPassManager.run(*module);

*/
namespace pipeline {
	namespace clips {
		void initializeCLIPSIndirector() {
			IndirectPassRegistry& indirectRegistry = *IndirectPassRegistry::getIndirectPassRegistry();
			indirectRegistry.registerPassGenerator<CLIPSPassGenerator>("clips");
		}
	}
}
#undef pass_registered
#undef optimize
#undef unregister_pass
#undef register_pass
#undef werror
#undef msg
#undef copy
#undef BoolCast
<commit_msg>Added a translation function for char* => IndirectPassType<commit_after>#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/PassRegistry.h"
#include "ExpertSystem/KnowledgeConstructionEngine.h"
#include "pipeline/clips/CLIPSPassGenerator.h"
#include "pipeline/clips/CLIPSPass.h"
#include "pipeline/clips/CLIPSPassHeader.h"
#include "rampancy/Cortex.h"
#include "rampancy/CompilerManager.h"
#include "rampancy/CompilerRegistry.h"
#include "indirect/Indirector.h"
#include "llvm/Support/raw_ostream.h"

extern "C" {
#include "clips.h"
}

using namespace llvm;
using namespace indirect;
extern "C" indirect::IndirectPassHeader::IndirectPassType TranslateInput(char* input);
extern "C" void CLIPSOptimizeCode(void* theEnv);
extern "C" void CLIPSRegisterPass(void* theEnv);
extern "C" void CLIPSUnregisterPass(void* theEnv);
extern "C" void* CLIPSPassRegistered(void* theEnv);
#define pass_registered (char*)"pass-registered"
#define optimize (char*)"optimize"
#define unregister_pass (char*)"unregister-pass"
#define register_pass (char*)"register-pass"
#define werror (char*)"werror"
#define msg(x) (char*) x
#define copy(from, to) \
	to = CharBuffer(strlen(from)); \
sprintf(to, "%s", from)
#define BoolCast(str, tgt) tgt = (strcmp(str, "TRUE") == 0) ? TRUE : FALSE

extern "C" void RegisterCLIPSPipelineFunctions(void* theEnv) {
	EnvDefineFunction(theEnv, optimize, 'v',
			PTIEF CLIPSOptimizeCode, "CLIPSOptimizeCode");
	EnvDefineFunction(theEnv, register_pass, 'v',
			PTIEF CLIPSRegisterPass, "CLIPSRegisterPass");
	EnvDefineFunction(theEnv, unregister_pass, 'v',
			PTIEF CLIPSUnregisterPass, "CLIPSUnregisterPass");
	EnvDefineFunction2(theEnv, pass_registered, 'w',
			PTIEF CLIPSPassRegistered, "CLIPSPassRegistered",
			"11k");
}

void CLIPSOptimizeCode(void* theEnv) {

}

void CLIPSRegisterPass(void* theEnv) {
	/* register-pass has the following arguments
	 * 1) name (PassArg)
	 * 2) description (PassName)
	 * 3) type (string)
	 * 4) IsAnalysis (bool)
	 * 5) isCFGPass (bool)
	 * 6) needRegions (bool)
	 * 7) needLoops (bool)
	 * 8) passes (multifield)
	 * 9) required (multifield)
	 * 10) required-transitive (multifield)
	 * 11) Preserved (multifield)
	 * 12) preservesAll (bool)
	 * 13) preservesCFG (bool);
	 */

	void* passes;
	void* required;
	void* requiredTransitive;
	void* preserved;
	DATA_OBJECT arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
					arg10, arg11, arg12;
	char *tmp0, *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6, *tmp7, *tmp8, *tmp9,
		  *tmp10;
	char* pArg;
	char* pName;
	bool isAnalysis, isCFG,
		  needRegions, needLoops,
		  preservesAll, preservesCFG;
	char* type;
	long long l0, l1, l2, l3;
	std::string tmp;
	raw_string_ostream stream(tmp);
	pipeline::clips::CLIPSPassHeader* header = new pipeline::clips::CLIPSPassHeader();
	header->setTemplateSet("clips");
	if(EnvArgCountCheck(theEnv, register_pass, EXACTLY, 13) == -1) {
		return;
	}

	if(EnvArgTypeCheck(theEnv, register_pass, 1, SYMBOL_OR_STRING, &arg0) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 2, SYMBOL_OR_STRING, &arg1) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 3, SYMBOL_OR_STRING, &arg2) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 4, SYMBOL, &arg3) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 5, SYMBOL, &arg4) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 6, SYMBOL, &arg5) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 7, SYMBOL, &arg6) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 8, MULTIFIELD, &arg7) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 9, MULTIFIELD, &arg8) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 10, MULTIFIELD, &arg9) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 11, MULTIFIELD, &arg10) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 12, SYMBOL, &arg11) == FALSE) {
		return;
	}
	if(EnvArgTypeCheck(theEnv, register_pass, 13, SYMBOL, &arg12) == FALSE) {
		return;
	}
	tmp0 = DOToString(arg0);
	copy(tmp0, pArg);
	header->setPassName((const char*)pArg);
	tmp1 = DOToString(arg1);
	copy(tmp1, pName);
	header->setPassDescription((const char*)pName);
	tmp2 = DOToString(arg2);
	copy(tmp2, type);
	header->setPassType(TranslateInput(type));
	tmp3 = DOToString(arg3);
	BoolCast(tmp3, isAnalysis);
	header->setIsAnalysis(isAnalysis);
	tmp4 = DOToString(arg4);
	BoolCast(tmp4, isCFG);
	header->setIsCFGOnlyPass(isCFG);
	tmp5 = DOToString(arg5);
	BoolCast(tmp5, needRegions);
	header->setNeedsRegions(needRegions);
	tmp6 = DOToString(arg6);
	BoolCast(tmp6, needLoops);
	header->setNeedsLoops(needLoops);
	//l0 = (long long)GetDOLength(arg7);
	//l1 = (long long)GetDOLength(arg8);
	//aUsage = GetValue(arg7);

   IndirectPassRegistry& indirectRegistry = *IndirectPassRegistry::getIndirectPassRegistry();
	indirectRegistry.registerIndirectPassHeader(header);
	free(pArg);
	free(pName);
	free(type);

}

void CLIPSUnregisterPass(void* theEnv) {

}

void* CLIPSPassRegistered(void* theEnv) {
	DATA_OBJECT arg0;
	char* a;
	char* b;
	if(EnvArgCountCheck(theEnv, pass_registered, EXACTLY, 1) == -1) {
		return FalseSymbol();
	}

	if(EnvArgTypeCheck(theEnv, pass_registered, 1, SYMBOL_OR_STRING, &arg0) == FALSE) {
		return FalseSymbol();
	}
	a = DOToString(arg0);
	copy(a, b);

	llvm::PassRegistry* registry = llvm::PassRegistry::getPassRegistry();
	const llvm::PassInfo* pi = registry->getPassInfo(llvm::StringRef(b));
	free(b);
	if(pi) {
		return TrueSymbol();
	} else {
		return FalseSymbol();
	}
}
IndirectPassHeader::IndirectPassType TranslateInput(char* input) {
	if(strcmp(input, "Module") == 0) {
		return IndirectPassHeader::Module;
	} else if(strcmp(input, "Function") == 0) {
		return IndirectPassHeader::Function;
	} else if(strcmp(input, "BasicBlock") == 0) {
		return IndirectPassHeader::BasicBlock;
	} else if(strcmp(input, "Loop") == 0) {
		return IndirectPassHeader::Loop;
	} else if(strcmp(input, "Region") == 0) {
		return IndirectPassHeader::Region;
	} else if(strcmp(input, "MachineFunction") == 0) {
		return IndirectPassHeader::MachineFunction;
	} else if(strcmp(input, "CallGraphSCC") == 0) {
		return IndirectPassHeader::CallGraphSCC;
	} else {
		return IndirectPassHeader::Unknown;
	}
}
/*
	llvm::PassManager tmpPassManager;
	llvm::PassManagerBuilder builder;
//taken from opt
llvm::TargetLibraryInfo *tli =
new llvm::TargetLibraryInfo(llvm::Triple(module->getTargetTriple()));
tmpPassManager.add(tli);
llvm::TargetData *td = 0;
const std::string &moduleDataLayout = module->getDataLayout();
if(!moduleDataLayout.empty())
td = new llvm::TargetData(moduleDataLayout);
if(td)
tmpPassManager.add(td);
llvm::PassManager& PM = tmpPassManager;
//add em all!
builder.OptLevel = 2;
builder.DisableSimplifyLibCalls = false;
builder.populateModulePassManager(PM);
//let's see if this fixes the issue
llvm::PassRegistry* registry = llvm::PassRegistry::getPassRegistry();
const llvm::PassInfo* ci = registry->getPassInfo(
llvm::StringRef("function-to-knowledge"));
const llvm::PassInfo* ls = registry->getPassInfo(
llvm::StringRef("loop-simplify"));
const llvm::PassInfo* bce = registry->getPassInfo(
llvm::StringRef("break-crit-edges"));
ExpertSystem::FunctionKnowledgeConversionPass* copy =
(ExpertSystem::FunctionKnowledgeConversionPass*)ci->createPass();
copy->setEnvironment(tEnv);
tmpPassManager.add(ls->createPass());
tmpPassManager.add(bce->createPass());
tmpPassManager.add(copy);
tmpPassManager.add(llvm::createVerifierPass());
tmpPassManager.run(*module);

*/
namespace pipeline {
	namespace clips {
		void initializeCLIPSIndirector() {
			IndirectPassRegistry& indirectRegistry = *IndirectPassRegistry::getIndirectPassRegistry();
			indirectRegistry.registerPassGenerator<CLIPSPassGenerator>("clips");
		}
	}
}
#undef pass_registered
#undef optimize
#undef unregister_pass
#undef register_pass
#undef werror
#undef msg
#undef copy
#undef BoolCast
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: DiagramHelper.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef CHART2_DIAGRAMHELPER_HXX
#define CHART2_DIAGRAMHELPER_HXX

#include "StackMode.hxx"
#include <com/sun/star/chart2/XAxis.hpp>
#include <com/sun/star/chart2/XDiagram.hpp>
#include <com/sun/star/chart2/XChartTypeTemplate.hpp>
#include <com/sun/star/chart2/XCoordinateSystem.hpp>
#include <com/sun/star/chart2/InterpretedData.hpp>
#include <com/sun/star/chart2/StackingDirection.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>

#include <utility>
#include <vector>

namespace chart
{

class DiagramHelper
{
public:
    typedef ::std::pair<
            ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartTypeTemplate >,
            ::rtl::OUString >
        tTemplateWithServiceName;

    /** tries to find a template in the chart-type manager that matches the
        given diagram.

        @param rPreferredTemplateName
            Check this template first.  This may speed up searching, if the
            caller assumes a certain template as most likely to be the one that
            matches.

        @return
            A pair containing a template with the correct properties set as
            first entry and the service name of the templateas second entry.  If
            no template was found both elements are empty.
     */
    static tTemplateWithServiceName
        getTemplateForDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::lang::XMultiServiceFactory > & xChartTypeManager,
            const ::rtl::OUString & rPreferredTemplateName = ::rtl::OUString());

    /** Sets the "SwapXAndYAxis" property at all coordinate systems found in the
        given diagram.

        "vertical==true" for bar charts, "vertical==false" for column charts
     */
    static void setVertical( const ::com::sun::star::uno::Reference<
                                 ::com::sun::star::chart2::XDiagram > & xDiagram,
                             bool bVertical = true );

    /** Gets the "SwapXAndYAxis" property at all coordinate systems found in the
        given diagram.

        "vertical==true" for bar charts, "vertical==false" for column charts
    */
    static bool getVertical( const ::com::sun::star::uno::Reference<
                                 ::com::sun::star::chart2::XDiagram > & xDiagram,
                             bool& rbOutFoundResult, bool& rbOutAmbiguousResult );

    static StackMode getStackMode(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        bool& rbFound, bool& rbAmbiguous
        );

    /** @param bOnlyAtFirstChartType
            If </TRUE>, the stacking mode is only set at the series found inside
            the first chart type.  This is the standard for all current
            templates (the only template that has more than one chart-type and
            allows stacking is bar/line combi, and for this the stacking only
            applies to the first chart type/the bars)
     */
    static void setStackMode(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        StackMode eStackMode,
        bool bOnlyAtFirstChartType = true
        );

    /** Retrieves the stackmode of the first DataSeries or none. If the series have differing stack
        modes, rbAmbiguous is set to true. If no series is there rbFound is set to false.

        @param xCorrespondingCoordinateSystem
            The coordinate system in which the given chart type xChartType is
            located.  (This is needed for determining percent stacking.  If
            omitted, the result will just indicate "not stacked", "stacked" or
            "ambiguous")
     */
    static StackMode getStackModeFromChartType(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XChartType > & xChartType,
        bool& rbFound, bool& rbAmbiguous,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem =
                ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XCoordinateSystem >()
        );

    /** Returns the dimension found for all chart types in the tree.  If the
        dimension is not unique, 0 is returned.
     */
    static sal_Int32 getDimension(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram );

    /** Sets the dimension of the diagram given.

        1. Sets the dimension of all used ChartTypes
        2. Adapts the DataSeriesTree to reflect the new dimension
        3. If new coordinate-systems have to be created, adapts the
           XCoordinateSystemContainer of the diagram.
     */
    static void setDimension(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        sal_Int32 nNewDimensionCount );

    /** Replaces all occurences of xCooSysToReplace in the tree with
        xReplacement in the diagram's tree
     */
    static void replaceCoordinateSystem(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XCoordinateSystem > & xCooSysToReplace,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XCoordinateSystem > & xReplacement );

    static bool isSeriesAttachedToMainAxis(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries >& xDataSeries );

    static bool attachSeriesToAxis( bool bMainAxis,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries >& xSeries,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram >& xDiagram,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::uno::XComponentContext > & xContext );

    static ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XAxis > getAttachedAxis(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries >& xSeries,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram >& xDiagram );

    static ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XChartType >
        getChartTypeOfSeries(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDataSeries >& xSeries );

    static ::com::sun::star::uno::Reference<
    ::com::sun::star::chart2::XCoordinateSystem >
        getCoordinateSystemOfChartType(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType >& xChartType );

    static ::std::vector<
            ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries > >
        getDataSeriesFromDiagram(
            const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram );

    /** return all data series in this diagram grouped by chart-types
     */
    static ::com::sun::star::uno::Sequence<
               ::com::sun::star::uno::Sequence<
                   ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataSeries > > >
        getDataSeriesGroups(
            const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram );

    static bool isCategoryDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram );

    static void setCategoriesToDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::data::XLabeledDataSequence >& xCategories,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram,
            bool bSetAxisType = false, // when this flag is true ...
            bool bCategoryAxis = true);// set the AxisType to CATEGORY or back to REALNUMBER

    static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XLabeledDataSequence >
        getCategoriesFromDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram );

    static ::com::sun::star::uno::Sequence< rtl::OUString >
        generateAutomaticCategories(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartDocument > & xChartDoc );

    static ::com::sun::star::uno::Sequence< rtl::OUString >
        generateAutomaticCategories(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XCoordinateSystem > & xCooSys );

    static void generateAutomaticCategoriesFromChartType(
            ::com::sun::star::uno::Sequence< rtl::OUString >& rRet,
            const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartType );

    static ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XChartType >
        getChartTypeByIndex( const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram >& xDiagram, sal_Int32 nIndex );

    static ::com::sun::star::uno::Sequence<
            ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType > >
        getChartTypesFromDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram );

    static bool areChartTypesCompatible( const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType >& xFirstType,
                const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType >& xSecondType );

    /**
        * Test if a series can be moved.
        *
        * @param xDiagram
        *  Reference to the diagram that contains the series.
        *
        * @param xGivenDataSeries
        *  Reference to the series that should be tested for moving.
        *
        * @param bForward
        *  Direction of the move to be checked.
        *
        * @returns </TRUE> if the series can be moved.
        *
        */
    static bool isSeriesMoveable(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram,
            const ::com::sun::star::uno::Reference<
        ::com::sun::star::chart2::XDataSeries >& xGivenDataSeries,
            bool bForward );

    /**
        * Move a series forward or backward.
        *
        * @param xDiagram
        *  Reference to the diagram that contains the series.
        *
        * @param xGivenDataSeries
        *  Reference to the series that should be moved.
        *
        * @param bForward
        *  Direction in which the series should be moved.
        *
        * @returns </TRUE> if the series was moved successfully.
        *
        */
    static bool moveSeries(
                const ::com::sun::star::uno::Reference<
                  ::com::sun::star::chart2::XDiagram >& xDiagram,
                const ::com::sun::star::uno::Reference<
          ::com::sun::star::chart2::XDataSeries >& xGivenDataSeries,
                bool bForward );

    static sal_Int32 getIndexOfSeriesWithinChartType(
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::chart2::XDataSeries >& xDataSeries,
               const ::com::sun::star::uno::Reference<
                    ::com::sun::star::chart2::XChartType >& xChartType );

    static bool isSupportingFloorAndWall( const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram );

    static bool isPieOrDonutChart( const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram );

    static sal_Int32 getGeometry3D(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        bool& rbFound, bool& rbAmbiguous );

    static void setGeometry3D(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        sal_Int32 nNewGeometry );

private:
    // not implemented
    DiagramHelper();

};

} //  namespace chart

// CHART2_DIAGRAMHELPER_HXX
#endif
<commit_msg>INTEGRATION: CWS chart22 (1.6.26); FILE MERGED 2008/06/10 11:11:50 iha 1.6.26.3: RESYNC: (1.8-1.9); FILE MERGED 2008/04/17 11:30:52 iha 1.6.26.2: RESYNC: (1.6-1.8); FILE MERGED 2008/02/21 16:55:59 iha 1.6.26.1: #i65549# Plotting of missing values<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: DiagramHelper.hxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef CHART2_DIAGRAMHELPER_HXX
#define CHART2_DIAGRAMHELPER_HXX

#include "StackMode.hxx"
#include <com/sun/star/chart2/XAxis.hpp>
#include <com/sun/star/chart2/XDiagram.hpp>
#include <com/sun/star/chart2/XChartTypeTemplate.hpp>
#include <com/sun/star/chart2/XCoordinateSystem.hpp>
#include <com/sun/star/chart2/InterpretedData.hpp>
#include <com/sun/star/chart2/StackingDirection.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>

#include <utility>
#include <vector>

namespace chart
{

class DiagramHelper
{
public:
    typedef ::std::pair<
            ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartTypeTemplate >,
            ::rtl::OUString >
        tTemplateWithServiceName;

    /** tries to find a template in the chart-type manager that matches the
        given diagram.

        @param rPreferredTemplateName
            Check this template first.  This may speed up searching, if the
            caller assumes a certain template as most likely to be the one that
            matches.

        @return
            A pair containing a template with the correct properties set as
            first entry and the service name of the templateas second entry.  If
            no template was found both elements are empty.
     */
    static tTemplateWithServiceName
        getTemplateForDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::lang::XMultiServiceFactory > & xChartTypeManager,
            const ::rtl::OUString & rPreferredTemplateName = ::rtl::OUString());

    /** Sets the "SwapXAndYAxis" property at all coordinate systems found in the
        given diagram.

        "vertical==true" for bar charts, "vertical==false" for column charts
     */
    static void setVertical( const ::com::sun::star::uno::Reference<
                                 ::com::sun::star::chart2::XDiagram > & xDiagram,
                             bool bVertical = true );

    /** Gets the "SwapXAndYAxis" property at all coordinate systems found in the
        given diagram.

        "vertical==true" for bar charts, "vertical==false" for column charts
    */
    static bool getVertical( const ::com::sun::star::uno::Reference<
                                 ::com::sun::star::chart2::XDiagram > & xDiagram,
                             bool& rbOutFoundResult, bool& rbOutAmbiguousResult );

    static StackMode getStackMode(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        bool& rbFound, bool& rbAmbiguous
        );

    /** @param bOnlyAtFirstChartType
            If </TRUE>, the stacking mode is only set at the series found inside
            the first chart type.  This is the standard for all current
            templates (the only template that has more than one chart-type and
            allows stacking is bar/line combi, and for this the stacking only
            applies to the first chart type/the bars)
     */
    static void setStackMode(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        StackMode eStackMode,
        bool bOnlyAtFirstChartType = true
        );

    /** Retrieves the stackmode of the first DataSeries or none. If the series have differing stack
        modes, rbAmbiguous is set to true. If no series is there rbFound is set to false.

        @param xCorrespondingCoordinateSystem
            The coordinate system in which the given chart type xChartType is
            located.  (This is needed for determining percent stacking.  If
            omitted, the result will just indicate "not stacked", "stacked" or
            "ambiguous")
     */
    static StackMode getStackModeFromChartType(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XChartType > & xChartType,
        bool& rbFound, bool& rbAmbiguous,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem =
                ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XCoordinateSystem >()
        );

    /** Returns the dimension found for all chart types in the tree.  If the
        dimension is not unique, 0 is returned.
     */
    static sal_Int32 getDimension(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram );

    /** Sets the dimension of the diagram given.

        1. Sets the dimension of all used ChartTypes
        2. Adapts the DataSeriesTree to reflect the new dimension
        3. If new coordinate-systems have to be created, adapts the
           XCoordinateSystemContainer of the diagram.
     */
    static void setDimension(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        sal_Int32 nNewDimensionCount );

    /** Replaces all occurences of xCooSysToReplace in the tree with
        xReplacement in the diagram's tree
     */
    static void replaceCoordinateSystem(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XCoordinateSystem > & xCooSysToReplace,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XCoordinateSystem > & xReplacement );

    static bool isSeriesAttachedToMainAxis(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries >& xDataSeries );

    static bool attachSeriesToAxis( bool bMainAxis,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries >& xSeries,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram >& xDiagram,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::uno::XComponentContext > & xContext );

    static ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XAxis > getAttachedAxis(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries >& xSeries,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram >& xDiagram );

    static ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XChartType >
        getChartTypeOfSeries(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDataSeries >& xSeries );

    static ::com::sun::star::uno::Reference<
    ::com::sun::star::chart2::XCoordinateSystem >
        getCoordinateSystemOfChartType(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType >& xChartType );

    static ::std::vector<
            ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDataSeries > >
        getDataSeriesFromDiagram(
            const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram );

    /** return all data series in this diagram grouped by chart-types
     */
    static ::com::sun::star::uno::Sequence<
               ::com::sun::star::uno::Sequence<
                   ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataSeries > > >
        getDataSeriesGroups(
            const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram );

    static bool isCategoryDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram );

    static void setCategoriesToDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::data::XLabeledDataSequence >& xCategories,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram,
            bool bSetAxisType = false, // when this flag is true ...
            bool bCategoryAxis = true);// set the AxisType to CATEGORY or back to REALNUMBER

    static ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XLabeledDataSequence >
        getCategoriesFromDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram );

    static ::com::sun::star::uno::Sequence< rtl::OUString >
        generateAutomaticCategories(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartDocument > & xChartDoc );

    static ::com::sun::star::uno::Sequence< rtl::OUString >
        generateAutomaticCategories(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XCoordinateSystem > & xCooSys );

    static void generateAutomaticCategoriesFromChartType(
            ::com::sun::star::uno::Sequence< rtl::OUString >& rRet,
            const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartType );

    static ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XChartType >
        getChartTypeByIndex( const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram >& xDiagram, sal_Int32 nIndex );

    static ::com::sun::star::uno::Sequence<
            ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType > >
        getChartTypesFromDiagram(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram );

    static bool areChartTypesCompatible( const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType >& xFirstType,
                const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType >& xSecondType );

    /**
        * Test if a series can be moved.
        *
        * @param xDiagram
        *  Reference to the diagram that contains the series.
        *
        * @param xGivenDataSeries
        *  Reference to the series that should be tested for moving.
        *
        * @param bForward
        *  Direction of the move to be checked.
        *
        * @returns </TRUE> if the series can be moved.
        *
        */
    static bool isSeriesMoveable(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram,
            const ::com::sun::star::uno::Reference<
        ::com::sun::star::chart2::XDataSeries >& xGivenDataSeries,
            bool bForward );

    /**
        * Move a series forward or backward.
        *
        * @param xDiagram
        *  Reference to the diagram that contains the series.
        *
        * @param xGivenDataSeries
        *  Reference to the series that should be moved.
        *
        * @param bForward
        *  Direction in which the series should be moved.
        *
        * @returns </TRUE> if the series was moved successfully.
        *
        */
    static bool moveSeries(
                const ::com::sun::star::uno::Reference<
                  ::com::sun::star::chart2::XDiagram >& xDiagram,
                const ::com::sun::star::uno::Reference<
          ::com::sun::star::chart2::XDataSeries >& xGivenDataSeries,
                bool bForward );

    static sal_Int32 getIndexOfSeriesWithinChartType(
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::chart2::XDataSeries >& xDataSeries,
               const ::com::sun::star::uno::Reference<
                    ::com::sun::star::chart2::XChartType >& xChartType );

    static bool isSupportingFloorAndWall( const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram );

    static bool isPieOrDonutChart( const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram >& xDiagram );

    static sal_Int32 getGeometry3D(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        bool& rbFound, bool& rbAmbiguous );

    static void setGeometry3D(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::chart2::XDiagram > & xDiagram,
        sal_Int32 nNewGeometry );

    //returns integer from constant group ::com::sun::star::chart::MissingValueTreatment
    static sal_Int32 getCorrectedMissingValueTreatment(
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XDiagram > & xDiagram,
            const ::com::sun::star::uno::Reference<
                ::com::sun::star::chart2::XChartType >& xChartType );

private:
    // not implemented
    DiagramHelper();

};

} //  namespace chart

// CHART2_DIAGRAMHELPER_HXX
#endif
<|endoftext|>


<commit_before>#include <tinyxml2.h>
#include <list>
#include "mud.h"
#include "conf.h"
#include "baseObject.h"
#include "objectContainer.h"
#include "entity.h"
#include "serializationHelpers.h"

std::list<Entity*>* ObjectContainer::GetContents()
{
    return &_contents;
}

bool ObjectContainer::CanReceive(Entity* obj) const
{
    return true;
}
void ObjectContainer::ObjectLeave(Entity* obj)
{
    std::list<Entity*>::iterator it, itEnd;

    itEnd = _contents.end();
    for (it = _contents.begin(); it != itEnd; ++it)
        {
            if ((*it) == obj)
                {
                    it = _contents.erase(it);
                    break;
                }
        }
}
void ObjectContainer::ObjectEnter(Entity* obj)
{
    _contents.push_back(obj);
}

void ObjectContainer::Serialize(tinyxml2::XMLElement* root)
{
    tinyxml2::XMLDocument* doc = root->GetDocument();
    tinyxml2::XMLElement* ent = doc->NewElement("objc");
    BaseObject::Serialize(ent);

    SerializeList<Entity, std::list<Entity*>>("contents", root, _contents);
    root->InsertEndChild(ent);
}
void ObjectContainer::Deserialize(tinyxml2::XMLElement* root)
{
    DeserializeList<Entity, std::list<Entity*>>(root, "contents", _contents);
    for (auto it: _contents)
        {
            it->SetLocation(this);
        }

    BaseObject::Deserialize(root->FirstChildElement("BaseObject"));
}
<commit_msg>Updated serialization paths.<commit_after>#include <tinyxml2.h>
#include <list>
#include "mud.h"
#include "conf.h"
#include "baseObject.h"
#include "objectContainer.h"
#include "entity.h"
#include "serializationHelpers.h"

std::list<Entity*>* ObjectContainer::GetContents()
{
    return &_contents;
}

bool ObjectContainer::CanReceive(Entity* obj) const
{
    return true;
}
void ObjectContainer::ObjectLeave(Entity* obj)
{
    std::list<Entity*>::iterator it, itEnd;

    itEnd = _contents.end();
    for (it = _contents.begin(); it != itEnd; ++it)
        {
            if ((*it) == obj)
                {
                    it = _contents.erase(it);
                    break;
                }
        }
}
void ObjectContainer::ObjectEnter(Entity* obj)
{
    _contents.push_back(obj);
}

void ObjectContainer::Serialize(tinyxml2::XMLElement* root)
{
    tinyxml2::XMLDocument* doc = root->GetDocument();
    tinyxml2::XMLElement* ent = doc->NewElement("objc");
    BaseObject::Serialize(ent);

    SerializeList<Entity, std::list<Entity*>>("contents", ent, _contents);
    root->InsertEndChild(ent);
}
void ObjectContainer::Deserialize(tinyxml2::XMLElement* root)
{
    DeserializeList<Entity, std::list<Entity*>>(root, "contents", _contents);
    for (auto it: _contents)
        {
            it->SetLocation(this);
        }

    BaseObject::Deserialize(root->FirstChildElement("BaseObject"));
}
<|endoftext|>