@SuppressWarnings({ "MethodLength", "DuplicatedCode" })
    public String build()
    {
        sb.setLength(0);

        if (null != prefix && !prefix.isEmpty())
        {
            sb.append(prefix).append(':');
        }

        sb.append(ChannelUri.AERON_SCHEME).append(':').append(media).append('?');

        appendParameter(sb, TAGS_PARAM_NAME, tags);
        appendParameter(sb, ENDPOINT_PARAM_NAME, endpoint);
        appendParameter(sb, INTERFACE_PARAM_NAME, networkInterface);
        appendParameter(sb, MDC_CONTROL_PARAM_NAME, controlEndpoint);
        appendParameter(sb, MDC_CONTROL_MODE_PARAM_NAME, controlMode);
        appendParameter(sb, MTU_LENGTH_PARAM_NAME, mtu);
        appendParameter(sb, TERM_LENGTH_PARAM_NAME, termLength);
        appendParameter(sb, INITIAL_TERM_ID_PARAM_NAME, initialTermId);
        appendParameter(sb, TERM_ID_PARAM_NAME, termId);
        appendParameter(sb, TERM_OFFSET_PARAM_NAME, termOffset);

        if (null != sessionId)
        {
            appendParameter(sb, SESSION_ID_PARAM_NAME, prefixTag(isSessionIdTagged, sessionId));
        }

        appendParameter(sb, TTL_PARAM_NAME, ttl);
        appendParameter(sb, RELIABLE_STREAM_PARAM_NAME, reliable);
        appendParameter(sb, LINGER_PARAM_NAME, linger);
        appendParameter(sb, ALIAS_PARAM_NAME, alias);
        appendParameter(sb, CONGESTION_CONTROL_PARAM_NAME, cc);
        appendParameter(sb, FLOW_CONTROL_PARAM_NAME, fc);
        appendParameter(sb, GROUP_TAG_PARAM_NAME, groupTag);
        appendParameter(sb, SPARSE_PARAM_NAME, sparse);
        appendParameter(sb, EOS_PARAM_NAME, eos);
        appendParameter(sb, TETHER_PARAM_NAME, tether);
        appendParameter(sb, GROUP_PARAM_NAME, group);
        appendParameter(sb, REJOIN_PARAM_NAME, rejoin);
        appendParameter(sb, SPIES_SIMULATE_CONNECTION_PARAM_NAME, ssc);
        appendParameter(sb, SOCKET_SNDBUF_PARAM_NAME, socketSndbufLength);
        appendParameter(sb, SOCKET_RCVBUF_PARAM_NAME, socketRcvbufLength);
        appendParameter(sb, RECEIVER_WINDOW_LENGTH_PARAM_NAME, receiverWindowLength);
        appendParameter(sb, MEDIA_RCV_TIMESTAMP_OFFSET_PARAM_NAME, mediaReceiveTimestampOffset);
        appendParameter(sb, CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME, channelReceiveTimestampOffset);
        appendParameter(sb, CHANNEL_SEND_TIMESTAMP_OFFSET_PARAM_NAME, channelSendTimestampOffset);
        appendParameter(sb, RESPONSE_ENDPOINT_PARAM_NAME, responseEndpoint);
        appendParameter(sb, RESPONSE_CORRELATION_ID_PARAM_NAME, responseCorrelationId);
        appendParameter(sb, NAK_DELAY_PARAM_NAME, nakDelay);
        appendParameter(sb, UNTETHERED_WINDOW_LIMIT_TIMEOUT_PARAM_NAME, untetheredWindowLimitTimeoutNs);
        appendParameter(sb, UNTETHERED_RESTING_TIMEOUT_PARAM_NAME, untetheredRestingTimeoutNs);
        appendParameter(sb, MAX_RESEND_PARAM_NAME, maxResend);

        final char lastChar = sb.charAt(sb.length() - 1);
        if (lastChar == '|' || lastChar == '?')
        {
            sb.setLength(sb.length() - 1);
        }

        return sb.toString();
    }
@Test
    void shouldBuildChannelBuilderUsingExistingStringWithAllTheFields()
    {
        final String uri = "aeron-spy:aeron:udp?endpoint=127.0.0.1:0|interface=127.0.0.1|control=127.0.0.2:0|" +
            "control-mode=manual|tags=2,4|alias=foo|cc=cubic|fc=min|reliable=false|ttl=16|mtu=8992|" +
            "term-length=1048576|init-term-id=5|term-offset=64|term-id=4353|session-id=2314234|gtag=3|" +
            "linger=100000055000001|sparse=true|eos=true|tether=false|group=false|ssc=true|so-sndbuf=8388608|" +
            "so-rcvbuf=2097152|rcv-wnd=1048576|media-rcv-ts-offset=reserved|channel-rcv-ts-offset=0|" +
            "channel-snd-ts-offset=8|response-endpoint=127.0.0.3:0|response-correlation-id=12345|nak-delay=100000|" +
            "untethered-window-limit-timeout=1000|untethered-resting-timeout=5000";

        final ChannelUri fromString = ChannelUri.parse(uri);
        final ChannelUri fromBuilder = ChannelUri.parse(new ChannelUriStringBuilder(uri).build());

        assertEquals(Collections.emptyMap(), fromString.diff(fromBuilder));
    }