bool
DBusAddressTranslator::translate(const DBusAddress &_key, CommonAPI::Address &_value) {
    bool result(true);
    std::lock_guard<std::mutex> itsLock(mutex_);

    const auto it = backwards_.find(_key);
    if (it != backwards_.end()) {
        _value = it->second;
    } else if (isDefault_) {
        if (isValid(_key.getObjectPath(), '/', true) && isValid(_key.getInterface(), '.')) {
            std::string interfaceName(_key.getInterface());
            std::string instance(_key.getObjectPath().substr(1));
            std::replace(instance.begin(), instance.end(), '/', '.');

            _value.setDomain(defaultDomain_);
            _value.setInterface(interfaceName);
            _value.setInstance(instance);

            std::string service = _key.getService();
            if(isValid(service, '.',
                       (service.length() > 0 && service[0] == ':'),
                       (service.length() > 0 && service[0] == ':'),
                       true)) {
                forwards_.insert({_value, _key});
                backwards_.insert({_key, _value});
            }
        } else {
            result = false;
        }
    } else {
        result = false;
    }

    return result;
}
void
InstanceAvailabilityStatusChangedEvent::onServiceInstanceStatus(
        std::shared_ptr<Proxy> _proxy,
        service_id_t _serviceId,
        instance_id_t _instanceId,
        bool _isAvailable,
        void* _data) {
    (void)_proxy;
    InstanceAvailabilityStatusChangedEvent* itsSelf =
            static_cast<InstanceAvailabilityStatusChangedEvent*>(_data);
    if(_instanceId != vsomeip::ANY_INSTANCE) {
        Address service(_serviceId, _instanceId);
        CommonAPI::Address capiAddressNewService;
        AddressTranslator::get()->translate(service, capiAddressNewService);

        if(capiAddressNewService.getInterface() == itsSelf->observedInterfaceName_) {
            if(_isAvailable) {
                if (itsSelf->addInstance(capiAddressNewService, _instanceId)) {
                    itsSelf->notifyListeners(capiAddressNewService.getAddress(),
                            CommonAPI::AvailabilityStatus::AVAILABLE);
                }
            } else {
                if (itsSelf->removeInstance(capiAddressNewService, _instanceId)) {
                    itsSelf->notifyListeners(capiAddressNewService.getAddress(),
                            CommonAPI::AvailabilityStatus::NOT_AVAILABLE);
               }
            }
        } else {
            COMMONAPI_ERROR(
                    itsSelf->observedInterfaceName_ + " doesn't match "
                            + capiAddressNewService.getInterface());
        }
    }
}
bool
AddressTranslator::translate(const Address &_key, std::string &_value) {
    CommonAPI::Address address;
    bool result = translate(_key, address);
    _value = address.getAddress();
    return result;
}
TEST_F(AddressTranslatorTest, CheckWellKnownNameInsertWorks) {
    std::shared_ptr<CommonAPI::DBus::DBusAddressTranslator> translator = CommonAPI::DBus::DBusAddressTranslator::get();

    std::string commonApiAddressRef = "local:my.well.insert.other.interface:my.well.insert.other.instance";
    CommonAPI::DBus::DBusAddress dbusAddressInsertRef("my.well.known.name", "/my/well/insert/instance", "my.well.insert.interface");

    CommonAPI::DBus::DBusAddress dbusAddressResult;
    CommonAPI::Address commonApiAddressResult;

    translator->insert(commonApiAddressRef,
                dbusAddressInsertRef.getService(),
                dbusAddressInsertRef.getObjectPath(),
                dbusAddressInsertRef.getInterface());

    translator->translate(CommonAPI::DBus::DBusAddress(dbusAddressInsertRef.getService(), dbusAddressInsertRef.getObjectPath(), dbusAddressInsertRef.getInterface()), commonApiAddressResult);
    std::cout << dbusAddressInsertRef.getService() << " " << dbusAddressInsertRef.getObjectPath() << " " << dbusAddressInsertRef.getInterface() << std::endl;
    std::cout << commonApiAddressResult.getDomain() << " " << commonApiAddressResult.getInterface() << " " << commonApiAddressResult.getInstance() << std::endl;
    ASSERT_EQ(commonApiAddressRef, commonApiAddressResult.getAddress());

    translator->translate(commonApiAddressRef, dbusAddressResult);
    std::cout << dbusAddressResult.getService() << " " << dbusAddressResult.getObjectPath() << " " << dbusAddressResult.getInterface() << std::endl;
    ASSERT_EQ(dbusAddressInsertRef.getService(), dbusAddressResult.getService());
    ASSERT_EQ(dbusAddressInsertRef.getObjectPath(), dbusAddressResult.getObjectPath());
    ASSERT_EQ(dbusAddressInsertRef.getInterface(), dbusAddressResult.getInterface());
}
TEST_F(AddressTranslatorTest, ParsesCommonAPIAddresses) {
    std::shared_ptr<CommonAPI::DBus::DBusAddressTranslator> translator = CommonAPI::DBus::DBusAddressTranslator::get();

    for(unsigned int i = 0; i < commonApiAddresses.size(); i++) {
        CommonAPI::Address commonApiAddress;
        translator->translate(CommonAPI::DBus::DBusAddress(dbusAddresses[i].getService(), dbusAddresses[i].getObjectPath(), dbusAddresses[i].getInterface()), commonApiAddress);
        std::cout << dbusAddresses[i].getService() << " " << dbusAddresses[i].getObjectPath() << " " << dbusAddresses[i].getInterface() << std::endl;
        std::cout << commonApiAddress.getDomain() << " " << commonApiAddress.getInterface() << " " << commonApiAddress.getInstance() << std::endl;
        ASSERT_EQ(commonApiAddresses[i], commonApiAddress.getAddress());
    }
}
bool
InstanceAvailabilityStatusChangedEvent::addInstance(
        const CommonAPI::Address &_address,
        const instance_id_t &_instanceId) {
    std::lock_guard<std::mutex> lock(instancesMutex_);
    if (instancesForward_.find(_instanceId) == instancesForward_.end()) {
        instancesForward_[_instanceId] = _address.getInstance();
        instancesBackward_[_address.getInstance()] = _instanceId;
        return true;
    }
    return false;
}
TEST_F(AddressTranslatorTest, InsertAddressPossible) {
    std::shared_ptr<CommonAPI::DBus::DBusAddressTranslator> translator = CommonAPI::DBus::DBusAddressTranslator::get();

    std::string commonApiAddressRef = "local:my.service:my.instance";

    CommonAPI::DBus::DBusAddress dbusAddressInsertRef("my.new.service_my.new.instance", "/my/new/instance", "my.new.service");
    CommonAPI::DBus::DBusAddress dbusAddressSecondInsertRef("my.new.second.service_my.new.second.instance", "/my/new/second/instance", "my.new.second.service");
    std::string commonApiSecondInsertAddressRef = "local:my.new.second.service:my.new.second.instance";

    CommonAPI::DBus::DBusAddress dbusAddressResult;
    CommonAPI::Address commonApiAddressResult;

    // insert new address
    translator->insert(commonApiAddressRef,
            dbusAddressInsertRef.getService(),
            dbusAddressInsertRef.getObjectPath(),
            dbusAddressInsertRef.getInterface());

    //check inserted address
    translator->translate(commonApiAddressRef, dbusAddressResult);
    std::cout << dbusAddressResult.getService() << " " << dbusAddressResult.getObjectPath() << " " << dbusAddressResult.getInterface() << std::endl;
    ASSERT_EQ(dbusAddressInsertRef.getService(), dbusAddressResult.getService());
    ASSERT_EQ(dbusAddressInsertRef.getObjectPath(), dbusAddressResult.getObjectPath());
    ASSERT_EQ(dbusAddressInsertRef.getInterface(), dbusAddressResult.getInterface());

    translator->translate(CommonAPI::DBus::DBusAddress(dbusAddressInsertRef.getService(), dbusAddressInsertRef.getObjectPath(), dbusAddressInsertRef.getInterface()), commonApiAddressResult);
    std::cout << dbusAddressInsertRef.getService() << " " << dbusAddressInsertRef.getObjectPath() << " " << dbusAddressInsertRef.getInterface() << std::endl;
    std::cout << commonApiAddressResult.getDomain() << " " << commonApiAddressResult.getInterface() << " " << commonApiAddressResult.getInstance() << std::endl;
    ASSERT_EQ(commonApiAddressRef, commonApiAddressResult.getAddress());

    // try overwriting address
    translator->insert(commonApiAddressRef,
            dbusAddressSecondInsertRef.getService(),
            dbusAddressSecondInsertRef.getObjectPath(),
            dbusAddressSecondInsertRef.getInterface());

    //check overwritten not possible
    translator->translate(commonApiAddressRef, dbusAddressResult);
    std::cout << dbusAddressResult.getService() << " " << dbusAddressResult.getObjectPath() << " " << dbusAddressResult.getInterface() << std::endl;
    ASSERT_EQ(dbusAddressInsertRef.getService(), dbusAddressResult.getService());
    ASSERT_EQ(dbusAddressInsertRef.getObjectPath(), dbusAddressResult.getObjectPath());
    ASSERT_EQ(dbusAddressInsertRef.getInterface(), dbusAddressResult.getInterface());

    translator->translate(CommonAPI::DBus::DBusAddress(dbusAddressSecondInsertRef.getService(), dbusAddressSecondInsertRef.getObjectPath(), dbusAddressSecondInsertRef.getInterface()), commonApiAddressResult);
    std::cout << dbusAddressSecondInsertRef.getService() << " " << dbusAddressSecondInsertRef.getObjectPath() << " " << dbusAddressSecondInsertRef.getInterface() << std::endl;
    std::cout << commonApiAddressResult.getDomain() << " " << commonApiAddressResult.getInterface() << " " << commonApiAddressResult.getInstance() << std::endl;
    ASSERT_EQ(commonApiSecondInsertAddressRef, commonApiAddressResult.getAddress());

    translator->translate(CommonAPI::DBus::DBusAddress(dbusAddressInsertRef.getService(), dbusAddressInsertRef.getObjectPath(), dbusAddressInsertRef.getInterface()), commonApiAddressResult);
    std::cout << dbusAddressInsertRef.getService() << " " << dbusAddressInsertRef.getObjectPath() << " " << dbusAddressInsertRef.getInterface() << std::endl;
    std::cout << commonApiAddressResult.getDomain() << " " << commonApiAddressResult.getInterface() << " " << commonApiAddressResult.getInstance() << std::endl;
    ASSERT_EQ(commonApiAddressRef, commonApiAddressResult.getAddress());
}
TEST_F(AddressTranslatorTest, InsertAddressNotPossibleConflictTranslate) {
    std::shared_ptr<CommonAPI::DBus::DBusAddressTranslator> translator = CommonAPI::DBus::DBusAddressTranslator::get();

    CommonAPI::DBus::DBusAddress dbusAddressRef("my.service.translate_my.instance.translate", "/my/instance/translate", "my.service.translate");
    std::string commonApiAddressRef = "local:my.service.translate:my.instance.translate";

    CommonAPI::DBus::DBusAddress dbusAddressInsertRef("my.new.service.translate_my.new.instance.translate", "/my/new/instance/translate", "my.new.service.translate");
    std::string commonApiAddressInsertRef = "local:my.new.service.translate:my.new.instance.translate";

    CommonAPI::DBus::DBusAddress dbusAddressResult;
    CommonAPI::Address commonApiAddressResult;

    // insertion via translate
    translator->translate(commonApiAddressRef, dbusAddressResult);
    std::cout << dbusAddressResult.getService() << " " << dbusAddressResult.getObjectPath() << " " << dbusAddressResult.getInterface() << std::endl;
    ASSERT_EQ(dbusAddressRef.getService(), dbusAddressResult.getService());
    ASSERT_EQ(dbusAddressRef.getObjectPath(), dbusAddressResult.getObjectPath());
    ASSERT_EQ(dbusAddressRef.getInterface(), dbusAddressResult.getInterface());

    translator->translate(CommonAPI::DBus::DBusAddress(dbusAddressRef.getService(), dbusAddressRef.getObjectPath(), dbusAddressRef.getInterface()), commonApiAddressResult);
    std::cout << dbusAddressRef.getService() << " " << dbusAddressRef.getObjectPath() << " " << dbusAddressRef.getInterface() << std::endl;
    std::cout << commonApiAddressResult.getDomain() << " " << commonApiAddressResult.getInterface() << " " << commonApiAddressResult.getInstance() << std::endl;
    ASSERT_EQ(commonApiAddressRef, commonApiAddressResult.getAddress());

    // try to overwrite address
    translator->insert(commonApiAddressRef,
            dbusAddressInsertRef.getService(),
            dbusAddressInsertRef.getObjectPath(),
            dbusAddressInsertRef.getInterface());

    //check that inserting was not possible
    translator->translate(commonApiAddressRef, dbusAddressResult);
    std::cout << dbusAddressResult.getService() << " " << dbusAddressResult.getObjectPath() << " " << dbusAddressResult.getInterface() << std::endl;
    ASSERT_EQ(dbusAddressRef.getService(), dbusAddressResult.getService());
    ASSERT_EQ(dbusAddressRef.getObjectPath(), dbusAddressResult.getObjectPath());
    ASSERT_EQ(dbusAddressRef.getInterface(), dbusAddressResult.getInterface());

    translator->translate(CommonAPI::DBus::DBusAddress(dbusAddressInsertRef.getService(), dbusAddressInsertRef.getObjectPath(), dbusAddressInsertRef.getInterface()), commonApiAddressResult);
    std::cout << dbusAddressInsertRef.getService() << " " << dbusAddressInsertRef.getObjectPath() << " " << dbusAddressInsertRef.getInterface() << std::endl;
    std::cout << commonApiAddressResult.getDomain() << " " << commonApiAddressResult.getInterface() << " " << commonApiAddressResult.getInstance() << std::endl;
    ASSERT_EQ(commonApiAddressInsertRef, commonApiAddressResult.getAddress());

    translator->translate(CommonAPI::DBus::DBusAddress(dbusAddressRef.getService(), dbusAddressRef.getObjectPath(), dbusAddressRef.getInterface()), commonApiAddressResult);
    std::cout << dbusAddressRef.getService() << " " << dbusAddressRef.getObjectPath() << " " << dbusAddressRef.getInterface() << std::endl;
    std::cout << commonApiAddressResult.getDomain() << " " << commonApiAddressResult.getInterface() << " " << commonApiAddressResult.getInstance() << std::endl;
    ASSERT_EQ(commonApiAddressRef, commonApiAddressResult.getAddress());

}
TEST_F(AddressTranslatorTest, UniqueAddressHandlingTranslateWorks) {
    std::shared_ptr<CommonAPI::DBus::DBusAddressTranslator> translator = CommonAPI::DBus::DBusAddressTranslator::get();

    std::string commonApiAddressRef = "local:my.unique.translate.interface:my.unique.translate.instance";
    CommonAPI::DBus::DBusAddress dbusAddressInsertRef(":1.6", "/my/unique/translate/instance", "my.unique.translate.interface");

    CommonAPI::DBus::DBusAddress dbusAddressResult;
    CommonAPI::Address commonApiAddressResult;

    translator->translate(CommonAPI::DBus::DBusAddress(dbusAddressInsertRef.getService(), dbusAddressInsertRef.getObjectPath(), dbusAddressInsertRef.getInterface()), commonApiAddressResult);
    std::cout << dbusAddressInsertRef.getService() << " " << dbusAddressInsertRef.getObjectPath() << " " << dbusAddressInsertRef.getInterface() << std::endl;
    std::cout << commonApiAddressResult.getDomain() << " " << commonApiAddressResult.getInterface() << " " << commonApiAddressResult.getInstance() << std::endl;
    ASSERT_EQ(commonApiAddressRef, commonApiAddressResult.getAddress());

    translator->translate(commonApiAddressRef, dbusAddressResult);
    std::cout << dbusAddressResult.getService() << " " << dbusAddressResult.getObjectPath() << " " << dbusAddressResult.getInterface() << std::endl;
    ASSERT_EQ(dbusAddressInsertRef.getService(), dbusAddressResult.getService());
    ASSERT_EQ(dbusAddressInsertRef.getObjectPath(), dbusAddressResult.getObjectPath());
    ASSERT_EQ(dbusAddressInsertRef.getInterface(), dbusAddressResult.getInterface());
}