void connect()
  {
    if (standAlone())
    {
      _session->listenStandalone(_listenUrls);
      return;
    }

    // listen + connect
    _session->connect(_url);
    if (!listenAddresses().empty())
    {
      for (const qi::Url& listenUrl : _listenUrls)
        _session->listen(listenUrl);
    }
  }
  ApplicationSessionPrivate(const ApplicationSession::Config& config)
    : _session(new qi::Session)
    , _init(false)
  {
    if (!(config.option() & qi::ApplicationSession::Option_NoAutoExit))
    {
      _session->disconnected.connect(&::onDisconnected);
    }

    bool& standalone = standAlone();
    std::string& addr = address();
    if (standalone && !addr.empty())
      throw std::runtime_error("You cannot be standAlone if you specified --qi-url to connect");

    standalone = standalone ? standalone : config.defaultStandAlone();
    if(!addr.empty())
      standalone = false;

    qiLogDebug() << "Connect url specified was: " << addr << ", now defaulting missing url parts from "
                 << config.defaultUrl().str();
    _url = specifyUrl(Url(addr), config.defaultUrl());
    qiLogDebug() << "Connect url is now: " << _url.str();


    std::vector<std::string> listenUrls;
    boost::split(listenUrls, listenAddresses(), boost::is_any_of(";"));
    for (const std::string& url : listenUrls)
      _listenUrls.push_back(specifyUrl(Url(url), config.defaultListenUrl()));

    if (!_listenUrls.empty())
    {
      qiLogDebug() << "Listen url specified: "
                   << boost::algorithm::join(listenUrls, ", ")
                   << ", now defaulting missing url parts with "
                   << config.defaultListenUrl().str();


      std::ostringstream ssListenUrl;
      for (const auto& url : _listenUrls)
        ssListenUrl << " " << url.str();
      qiLogDebug() << "Listen url are now:" << ssListenUrl.str();
    }
  }
static void parseAddress()
{
  namespace po = boost::program_options;
  po::options_description desc("ApplicationSession options");

  static const std::string qiListenUrlsOption = ""
      "Set URL to listen to.\n"
      "Can be more than one URL to listen semicolon-separated list.\n"

      " tcp://127.0.0.1:9555;tcp://:9999;127.0.0.1\n"
      "Missing information from incomplete URLs will be defaulted by defaultListenUrl.\n"
      "If the default URL is tcps://0.0.0.0:9559 the previous list will become:\n"
      " tcp://127.0.0.1:9555;tcp://0.0.0.0:9999;tcps://127.0.0.1:9559";

  desc.add_options()
      ("qi-url", po::value<std::string>(&address()), "The address of the service directory")
      ("qi-listen-url", po::value<std::string>(&listenAddresses()), qiListenUrlsOption.c_str())
      ("qi-standalone", "create a standalone session (this will use qi-listen-url if provided");

  po::variables_map vm;
  po::parsed_options parsed =
      po::command_line_parser(qi::Application::arguments()).options(desc).allow_unregistered().run();
  po::store(parsed, vm);
  po::notify(vm);

  qi::Application::setArguments(po::collect_unrecognized(parsed.options, po::include_positional));
  standAlone() = vm.count("qi-standalone") ? true : false;

  {
    po::options_description descTmp;
    descTmp.add_options()
        ("help,h", "");

    po::variables_map vmTmp;
    po::store(po::command_line_parser(qi::Application::arguments()).options(descTmp).allow_unregistered().run(),
              vmTmp);

    if (vmTmp.count("help"))
      std::cout << desc << std::endl;
  }
}
//----------------------------------------------------------------------------------------
// Do
//----------------------------------------------------------------------------------------
ErrorCode
CZPAMUISaveAlertService::Do(
	IManageableAsset * pAsset)
{
	LogFunctionEnterExit;

	InterfacePtr<IAMServiceData> iamdata(this, UseDefaultIID());
	ASSERT(iamdata);
	
	const enAMUIServiceType serviceType = this->GetServiceType();

	bool canCheckIn = this->CallVerifyService( pAsset, IAMServiceProvider::enCheckIn );

	PMString name;
	iamdata->Get(IAMUIService::enDocumentName, name);
	
	const IStringData *	dbAsset = nil;
	if( serviceType == eAMUIServiceType_LinkedStory )
		dbAsset = this->GetDBAsset_FromIDStory( pAsset );
	else if( serviceType == eAMUIServiceType_Document )
		dbAsset = this->GetDBAsset_FromDoc( pAsset );
	else
		dbAsset = nil;

	if( name.IsEmpty() && dbAsset )
	{
		InterfacePtr<const IStringData> dbAssetName( dbAsset, IID_IZPDATANAME );
		if( dbAssetName )
			name = dbAssetName->Get();
	}

	PMString message(kIZPSaveAlertKey);
	message.Translate();
	
	StringUtils::ReplaceStringParameters(&message, name);
	
	IDataBase * db = ::GetDataBase( pAsset );
	bool isInCopy = Utils<IZPInDnUtils>()->IsHostAppInCopy();

	bool isStandaloneDoc = false;
	if (db)
	{
		InterfacePtr<IDocument> doc(db, db->GetRootUID(), UseDefaultIID());
		InterfacePtr<IStandAloneDoc> standAlone(doc, IID_ISTANDALONEDOC);
		if (standAlone )
			isStandaloneDoc = standAlone->IsStandAloneDoc();
	}

	int16 result = 0;
	//result = CAlert::ModalAlert(message, kSaveButtonString, kDontSaveButtonString, kCancelString, 1, CAlert::eWarningIcon);
	//int16 result = CAlert::ModalAlert(message, kSaveButtonString, kDontSaveButtonString, kIZPSaveVersionBtnKey, 1, CAlert::eWarningIcon);
#if 0
	if( canCheckIn )
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kSaveButtonString, kIZPSaveVersionBtnKey, kDontSaveButtonString, kCancelString );
	else if( !isInCopy && db->IsModified() )	//On InCopy if we cannot check-in then don't save it.
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kSaveButtonString, kNullString, kDontSaveButtonString, kCancelString );
#else	//#1935, force check-in, don't allow

#if 0
	if( canCheckIn )
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kNullString, kIZPSaveVersionBtnKey, kNullString, kCancelString );
	else if( !isInCopy && db->IsModified() )	//On InCopy if we cannot check-in then don't save it.
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kSaveButtonString, kNullString, kNullString, kCancelString );
#else
	//Patch: #1948, fix crash when select checkin after selecting No in IC Document
	if (dbAsset == nil && canCheckIn == false)
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kSaveButtonString, kNullString, kDontSaveButtonString, kCancelString ); //Save new doc
	else if (isInCopy && canCheckIn == false && db == nil)
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kSaveButtonString, kNullString, kNullString, kCancelString ); //Save new IC doc
	else if (isInCopy && canCheckIn && db && db->IsModified() && isStandaloneDoc == false)
		result = 4; // Checkin IC doc
	else if (isInCopy && canCheckIn == false && db && db->IsModified() && isStandaloneDoc == false)
		result = 4; // Cancel Assignment
	else if (isInCopy && canCheckIn && db && db->IsModified() && isStandaloneDoc)
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kNullString, kIZPSaveVersionBtnKey, kNullString, kCancelString ); // Checkin template
	else if (isInCopy == false && canCheckIn == false && db && db->IsModified())
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kSaveButtonString, kNullString, kNullString, kCancelString ); //Save new ID doc
	else if (isInCopy == false && canCheckIn && db && db->IsModified())
		result = Utils<IZPUIDialogFacade>()->ShowAlertDialog( message, kNullString, kIZPSaveVersionBtnKey, kNullString, kCancelString ); //Checkin
#endif
#endif
	else
		result = 3;
	
	switch (result){
		case 1:
			iamdata->Set(IAMUIService::enFollowupAction, IAMUIService::enSave);
			break;
		case 2:
			iamdata->Set(IAMUIService::enFollowupAction, IAMUIService::enSaveVersion);
			break;
		case 3:
			iamdata->Set(IAMUIService::enFollowupAction, IAMUIService::enDontSave);
			break;
		case 4:
			iamdata->Set(IAMUIService::enFollowupAction, IAMUIService::enCancel);
			break;
	}
	
	return (kSuccess);
}