docs: public Conversation connect(Object endPoint,
                                  ConversationReceiveListener receiveListener,
                                  Conversation.ConversationType conversationType)
                      throws SIResourceException
      {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.entry(this, tc, "connect", new Object[] { endPoint, receiveListener, conversationType });
          CFEndPointDescriptor testEndPoint = new CFEndPointDescriptor(endPoint, conversationType);
          ConnectionDataGroup connGroup;
  
          // Take the monitor of the end point to group map.  This allows us to select or
          // create a new group, safe in the knowledge that no-one else can add a duplicate
          // or remove the group we are interested in.
          synchronized (endPointToGroupMap)
          {
              // See if there is already a connection group for the end point we are interested
              // in, if not create one and add it to the map.
              connGroup = endPointToGroupMap.get(testEndPoint);
  
              // Contemplate issuing a warning if the endpoint is SSL enabled, we are running in
              // the client container, and the SSL properties file is not available.
              framework.warnIfSSLAndPropertiesFileMissing(endPoint);
  
              // Determine the heartbeat interval and timeout from our configuration.
              Map properties = framework.getOutboundConnectionProperties(endPoint);
              int heartbeatInterval = determineHeartbeatInterval(properties);
              int heartbeatTimeout = determineHeartbeatTimeout(properties);
  
              if (connGroup == null)
              {
                  connGroup = new ConnectionDataGroup(this,
                                  testEndPoint,
                                  conversationsPerConnection,
                                  framework,
                                  heartbeatInterval,
                                  heartbeatTimeout);
  
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                      SibTr.debug(this, tc, "created new connection data group: " + connGroup);
                  endPointToGroupMap.put(testEndPoint, connGroup);
              }
  
              // Notify the connection group of our intention to make a connection at some point in
              // the future.  This mechanism is used to prevent an "empty" group from being
              // closed in the interval between us releasing the lock on the endpoint->group map
              // and actually making the connect attempt.  The motivation behind this is to avoid
              // holding the endpoint->group map monitor for the (potentially very long) duration
              // of an connect attempt.
              connGroup.connectionPending();
          }
  
          // Attempt to establish a new conversation.
          Conversation retConversation = connGroup.connect(endPoint,
                                                           receiveListener,
                                                           conversationType);
  
          if (retConversation != null)
              retConversation.setConversationType(conversationType);
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.exit(this, tc, "connect", retConversation);
          return retConversation;
      }