Example usage for org.apache.commons.lang3.tuple Triple getLeft

List of usage examples for org.apache.commons.lang3.tuple Triple getLeft

Introduction

In this page you can find the example usage for org.apache.commons.lang3.tuple Triple getLeft.

Prototype

public abstract L getLeft();

Source Link

Document

Gets the left element from this triple.

Usage

From source file:alfio.manager.AdminReservationManagerIntegrationTest.java

@Test
public void testConfirmReservation() throws Exception {
    List<TicketCategoryModification> categories = Collections.singletonList(new TicketCategoryModification(null,
            "default", 1, new DateTimeModification(LocalDate.now(), LocalTime.now()),
            new DateTimeModification(LocalDate.now(), LocalTime.now()), DESCRIPTION, BigDecimal.TEN, false, "",
            true, null, null, null, null, null));
    Triple<Event, String, TicketReservation> testResult = performExistingCategoryTest(categories, true,
            Collections.singletonList(2), false, true, 0, AVAILABLE_SEATS);
    assertNotNull(testResult);//from w w  w  .  ja v a  2s  .  c o m
    Result<Triple<TicketReservation, List<Ticket>, Event>> result = adminReservationManager.confirmReservation(
            testResult.getLeft().getShortName(), testResult.getRight().getId(), testResult.getMiddle());
    assertTrue(result.isSuccess());
    Triple<TicketReservation, List<Ticket>, Event> triple = result.getData();
    assertEquals(TicketReservation.TicketReservationStatus.COMPLETE, triple.getLeft().getStatus());
    triple.getMiddle().forEach(t -> assertEquals(Ticket.TicketStatus.ACQUIRED, t.getStatus()));
    assertTrue(emailMessageRepository.findByEventId(triple.getRight().getId(), 0, 50, null).isEmpty());
    ticketCategoryRepository.findByEventId(triple.getRight().getId())
            .forEach(tc -> assertTrue(specialPriceRepository.findAllByCategoryId(tc.getId()).stream()
                    .allMatch(sp -> sp.getStatus() == SpecialPrice.Status.TAKEN)));
    assertFalse(ticketRepository.findAllReservationsConfirmedButNotAssigned(triple.getRight().getId())
            .contains(triple.getLeft().getId()));
}

From source file:alfio.manager.WaitingQueueManagerIntegrationTest.java

@Test
public void testAssignTicketToWaitingQueueUnboundedCategorySelected() {
    LocalDateTime start = LocalDateTime.now().minusHours(1);
    LocalDateTime end = LocalDateTime.now().plusHours(1);

    List<TicketCategoryModification> categories = Arrays.asList(
            new TicketCategoryModification(null, "default", AVAILABLE_SEATS,
                    new DateTimeModification(start.toLocalDate(), start.toLocalTime()),
                    new DateTimeModification(end.toLocalDate(), end.toLocalTime()), DESCRIPTION, BigDecimal.TEN,
                    false, "", false, null, null, null, null, null),
            new TicketCategoryModification(null, "default2", AVAILABLE_SEATS,
                    new DateTimeModification(start.toLocalDate(), start.toLocalTime()),
                    new DateTimeModification(end.toLocalDate(), end.toLocalTime()), DESCRIPTION, BigDecimal.TEN,
                    false, "", false, null, null, null, null, null));

    configurationManager.saveSystemConfiguration(ConfigurationKeys.ENABLE_WAITING_QUEUE, "true");

    Event event = initEvent(categories, organizationRepository, userManager, eventManager, eventRepository)
            .getKey();/*from  w  w w . j  a  v  a2s .c o m*/

    List<TicketCategory> ticketCategories = ticketCategoryRepository.findByEventId(event.getId());
    TicketCategory first = ticketCategories.get(0);
    TicketCategory second = ticketCategories.get(1);

    TicketReservationModification tr2 = new TicketReservationModification();
    tr2.setAmount(1);
    tr2.setTicketCategoryId(second.getId());

    TicketReservationModification tr3 = new TicketReservationModification();
    tr3.setAmount(1);
    tr3.setTicketCategoryId(first.getId());

    reserveTickets(event, first, AVAILABLE_SEATS - 2);

    String reservationIdSingleFirst = reserveTickets(event, second, 1);
    String reservationIdSingleSecond = reserveTickets(event, second, 1);

    assertEquals(0, eventRepository.findStatisticsFor(event.getId()).getDynamicAllocation());

    assertTrue(waitingQueueManager.subscribe(event, customerJohnDoe(event), "john@doe.com", first.getId(),
            Locale.ENGLISH));
    assertTrue(waitingQueueManager.subscribe(event, new CustomerName("John Doe 2", "John", "Doe 2", event),
            "john@doe2.com", second.getId(), Locale.ENGLISH));

    ticketReservationManager.deleteOfflinePayment(event, reservationIdSingleFirst, false);
    ticketReservationManager.deleteOfflinePayment(event, reservationIdSingleSecond, false);

    List<Triple<WaitingQueueSubscription, TicketReservationWithOptionalCodeModification, ZonedDateTime>> subscriptions = waitingQueueManager
            .distributeSeats(event).collect(Collectors.toList());
    assertEquals(2, subscriptions.size());
    Triple<WaitingQueueSubscription, TicketReservationWithOptionalCodeModification, ZonedDateTime> subscriptionDetail = subscriptions
            .get(0);
    assertEquals("john@doe.com", subscriptionDetail.getLeft().getEmailAddress());
    TicketReservationWithOptionalCodeModification reservation = subscriptionDetail.getMiddle();
    assertEquals(Integer.valueOf(first.getId()), reservation.getTicketCategoryId());
    assertEquals(Integer.valueOf(1), reservation.getAmount());
    assertTrue(subscriptionDetail.getRight().isAfter(ZonedDateTime.now()));

    subscriptionDetail = subscriptions.get(1);
    assertEquals("john@doe2.com", subscriptionDetail.getLeft().getEmailAddress());
    reservation = subscriptionDetail.getMiddle();
    assertEquals(Integer.valueOf(second.getId()), reservation.getTicketCategoryId());
    assertEquals(Integer.valueOf(1), reservation.getAmount());
    assertTrue(subscriptionDetail.getRight().isAfter(ZonedDateTime.now()));
}

From source file:alfio.manager.WaitingQueueManagerIntegrationTest.java

@Test
public void testAssignTicketToWaitingQueueUnboundedCategory() {
    LocalDateTime start = LocalDateTime.now().minusMinutes(1);
    LocalDateTime end = LocalDateTime.now().plusMinutes(20);
    List<TicketCategoryModification> categories = Collections.singletonList(new TicketCategoryModification(null,
            "default", AVAILABLE_SEATS, new DateTimeModification(start.toLocalDate(), start.toLocalTime()),
            new DateTimeModification(end.toLocalDate(), end.toLocalTime()), DESCRIPTION, BigDecimal.TEN, false,
            "", false, null, null, null, null, null));

    configurationManager.saveSystemConfiguration(ConfigurationKeys.ENABLE_WAITING_QUEUE, "true");

    Event event = initEvent(categories, organizationRepository, userManager, eventManager, eventRepository)
            .getKey();//from w  w w  .j a v a  2s.c om

    TicketCategory unbounded = ticketCategoryRepository.findByEventId(event.getId()).get(0);

    TicketReservationModification tr = new TicketReservationModification();
    tr.setAmount(AVAILABLE_SEATS - 1);
    tr.setTicketCategoryId(unbounded.getId());

    TicketReservationModification tr2 = new TicketReservationModification();
    tr2.setAmount(1);
    tr2.setTicketCategoryId(unbounded.getId());

    TicketReservationWithOptionalCodeModification multi = new TicketReservationWithOptionalCodeModification(tr,
            Optional.empty());
    TicketReservationWithOptionalCodeModification single = new TicketReservationWithOptionalCodeModification(
            tr2, Optional.empty());

    String reservationId = ticketReservationManager.createTicketReservation(event,
            Collections.singletonList(multi), Collections.emptyList(), DateUtils.addDays(new Date(), 1),
            Optional.empty(), Optional.empty(), Locale.ENGLISH, false);
    TotalPrice reservationCost = ticketReservationManager.totalReservationCostWithVAT(reservationId);
    PaymentResult result = ticketReservationManager.confirm("", null, event, reservationId, "test@test.ch",
            new CustomerName("Full Name", "Full", "Name", event), Locale.ENGLISH, "", reservationCost,
            Optional.empty(), Optional.of(PaymentProxy.OFFLINE), false, null, null, null);
    assertTrue(result.isSuccessful());

    String reservationIdSingle = ticketReservationManager.createTicketReservation(event,
            Collections.singletonList(single), Collections.emptyList(), DateUtils.addDays(new Date(), 1),
            Optional.empty(), Optional.empty(), Locale.ENGLISH, false);
    TotalPrice reservationCostSingle = ticketReservationManager
            .totalReservationCostWithVAT(reservationIdSingle);
    PaymentResult resultSingle = ticketReservationManager.confirm("", null, event, reservationIdSingle,
            "test@test.ch", new CustomerName("Full Name", "Full", "Name", event), Locale.ENGLISH, "",
            reservationCostSingle, Optional.empty(), Optional.of(PaymentProxy.OFFLINE), false, null, null,
            null);
    assertTrue(resultSingle.isSuccessful());

    assertEquals(0, eventRepository.findStatisticsFor(event.getId()).getDynamicAllocation());

    assertTrue(
            waitingQueueManager.subscribe(event, customerJohnDoe(event), "john@doe.com", null, Locale.ENGLISH));

    ticketReservationManager.deleteOfflinePayment(event, reservationIdSingle, false);

    List<Triple<WaitingQueueSubscription, TicketReservationWithOptionalCodeModification, ZonedDateTime>> subscriptions = waitingQueueManager
            .distributeSeats(event).collect(Collectors.toList());
    assertEquals(1, subscriptions.size());
    Triple<WaitingQueueSubscription, TicketReservationWithOptionalCodeModification, ZonedDateTime> subscriptionDetail = subscriptions
            .get(0);
    assertEquals("john@doe.com", subscriptionDetail.getLeft().getEmailAddress());
    TicketReservationWithOptionalCodeModification reservation = subscriptionDetail.getMiddle();
    assertEquals(Integer.valueOf(unbounded.getId()), reservation.getTicketCategoryId());
    assertEquals(Integer.valueOf(1), reservation.getAmount());
    assertTrue(subscriptionDetail.getRight().isAfter(ZonedDateTime.now()));
}

From source file:alfio.manager.WaitingQueueManagerIntegrationTest.java

@Test
public void testAssignTicketToWaitingQueueBoundedCategory() {
    LocalDateTime start = LocalDateTime.now().minusMinutes(2);
    LocalDateTime end = LocalDateTime.now().plusMinutes(20);
    List<TicketCategoryModification> categories = Collections.singletonList(new TicketCategoryModification(null,
            "default", AVAILABLE_SEATS, new DateTimeModification(start.toLocalDate(), start.toLocalTime()),
            new DateTimeModification(end.toLocalDate(), end.toLocalTime()), DESCRIPTION, BigDecimal.TEN, false,
            "", true, null, null, null, null, null));

    configurationManager.saveSystemConfiguration(ConfigurationKeys.ENABLE_WAITING_QUEUE, "true");

    Event event = initEvent(categories, organizationRepository, userManager, eventManager, eventRepository)
            .getKey();//from   ww  w .  j  av  a  2s  . c  om

    TicketCategory bounded = ticketCategoryRepository.findByEventId(event.getId()).get(0);

    TicketReservationModification tr = new TicketReservationModification();
    tr.setAmount(AVAILABLE_SEATS - 1);
    tr.setTicketCategoryId(bounded.getId());

    TicketReservationModification tr2 = new TicketReservationModification();
    tr2.setAmount(1);
    tr2.setTicketCategoryId(bounded.getId());

    TicketReservationWithOptionalCodeModification multi = new TicketReservationWithOptionalCodeModification(tr,
            Optional.empty());
    TicketReservationWithOptionalCodeModification single = new TicketReservationWithOptionalCodeModification(
            tr2, Optional.empty());

    String reservationId = ticketReservationManager.createTicketReservation(event,
            Collections.singletonList(multi), Collections.emptyList(), DateUtils.addDays(new Date(), 1),
            Optional.empty(), Optional.empty(), Locale.ENGLISH, false);
    TotalPrice reservationCost = ticketReservationManager.totalReservationCostWithVAT(reservationId);
    PaymentResult result = ticketReservationManager.confirm("", null, event, reservationId, "test@test.ch",
            new CustomerName("Full Name", "Full", "Name", event), Locale.ENGLISH, "", reservationCost,
            Optional.empty(), Optional.of(PaymentProxy.OFFLINE), false, null, null, null);
    assertTrue(result.isSuccessful());

    String reservationIdSingle = ticketReservationManager.createTicketReservation(event,
            Collections.singletonList(single), Collections.emptyList(), DateUtils.addDays(new Date(), 1),
            Optional.empty(), Optional.empty(), Locale.ENGLISH, false);
    TotalPrice reservationCostSingle = ticketReservationManager
            .totalReservationCostWithVAT(reservationIdSingle);
    PaymentResult resultSingle = ticketReservationManager.confirm("", null, event, reservationIdSingle,
            "test@test.ch", new CustomerName("Full Name", "Full", "Name", event), Locale.ENGLISH, "",
            reservationCostSingle, Optional.empty(), Optional.of(PaymentProxy.OFFLINE), false, null, null,
            null);
    assertTrue(resultSingle.isSuccessful());

    assertEquals(0, eventRepository.findStatisticsFor(event.getId()).getDynamicAllocation());

    assertTrue(
            waitingQueueManager.subscribe(event, customerJohnDoe(event), "john@doe.com", null, Locale.ENGLISH));

    ticketReservationManager.deleteOfflinePayment(event, reservationIdSingle, false);

    List<Triple<WaitingQueueSubscription, TicketReservationWithOptionalCodeModification, ZonedDateTime>> subscriptions = waitingQueueManager
            .distributeSeats(event).collect(Collectors.toList());
    assertEquals(1, subscriptions.size());
    Triple<WaitingQueueSubscription, TicketReservationWithOptionalCodeModification, ZonedDateTime> subscriptionDetail = subscriptions
            .get(0);
    assertEquals("john@doe.com", subscriptionDetail.getLeft().getEmailAddress());
    TicketReservationWithOptionalCodeModification reservation = subscriptionDetail.getMiddle();
    assertEquals(Integer.valueOf(bounded.getId()), reservation.getTicketCategoryId());
    assertEquals(Integer.valueOf(1), reservation.getAmount());
    assertTrue(subscriptionDetail.getRight().isAfter(ZonedDateTime.now()));
}

From source file:com.vmware.identity.openidconnect.server.AuthenticationRequestProcessor.java

public Pair<ModelAndView, HttpResponse> process() {
    // parse authn request (and if that fails, see if you can still construct an error response off of the partially parsed request)
    ClientID clientId;//from   ww w  .ja  v a 2  s  .c  o m
    URI redirectUri;
    AuthenticationErrorResponse parseErrorResponse;
    try {
        this.authnRequest = AuthenticationRequest.parse(this.httpRequest);
        clientId = this.authnRequest.getClientID();
        redirectUri = this.authnRequest.getRedirectURI();
        parseErrorResponse = null;
    } catch (AuthenticationRequest.ParseException e) {
        if (e.getClientID() != null && e.getRedirectURI() != null
                && e.createAuthenticationErrorResponse(this.isAjaxRequest) != null) {
            clientId = e.getClientID();
            redirectUri = e.getRedirectURI();
            parseErrorResponse = e.createAuthenticationErrorResponse(this.isAjaxRequest);
        } else {
            LoggerUtils.logFailedRequest(logger, e.getErrorObject(), e);
            return Pair.of((ModelAndView) null, HttpResponse.createErrorResponse(e.getErrorObject()));
        }
    }

    // check that tenant, client, and redirect_uri are registered (if not, return error to browser, not client)
    try {
        if (this.tenant == null) {
            this.tenant = this.tenantInfoRetriever.getDefaultTenantName();
        }
        this.tenantInfo = this.tenantInfoRetriever.retrieveTenantInfo(this.tenant);
        this.clientInfo = this.clientInfoRetriever.retrieveClientInfo(this.tenant, clientId);
        if (!this.clientInfo.getRedirectURIs().contains(redirectUri)) {
            throw new ServerException(ErrorObject.invalidRequest("unregistered redirect_uri"));
        }
    } catch (ServerException e) {
        LoggerUtils.logFailedRequest(logger, e);
        return Pair.of((ModelAndView) null, HttpResponse.createErrorResponse(e.getErrorObject()));
    }

    // if tenant, client, and redirect_uri are registered, we can return authn error response to the client instead of browser
    if (parseErrorResponse != null) {
        LoggerUtils.logFailedRequest(logger, parseErrorResponse.getErrorObject());
        return Pair.of((ModelAndView) null, parseErrorResponse.toHttpResponse());
    }

    // authenticate client
    try {
        authenticateClient();
    } catch (ServerException e) {
        LoggerUtils.logFailedRequest(logger, e);
        return Pair.of((ModelAndView) null, authnErrorResponse(e).toHttpResponse());
    }

    // process login information (username/password or session), if failed, return error message to browser so javascript can consume it
    LoginProcessor p = new LoginProcessor(this.personUserAuthenticator, this.sessionManager, this.messageSource,
            this.locale, this.httpRequest, this.tenant);
    Triple<PersonUser, SessionID, LoginMethod> loginResult;
    try {
        loginResult = p.process();
    } catch (LoginProcessor.LoginException e) {
        LoggerUtils.logFailedRequest(logger, e.getErrorObject(), e);
        return Pair.of((ModelAndView) null, e.toHttpResponse());
    }
    PersonUser personUser = loginResult.getLeft();
    SessionID sessionId = loginResult.getMiddle();
    LoginMethod loginMethod = loginResult.getRight();

    // if no person user, return login form
    if (personUser == null) {
        try {
            return Pair.of(generateLoginForm(), (HttpResponse) null);
        } catch (ServerException e) {
            LoggerUtils.logFailedRequest(logger, e);
            return Pair.of((ModelAndView) null, authnErrorResponse(e).toHttpResponse());
        }
    }

    // we have a person user, process authn request for this person user
    try {
        AuthenticationSuccessResponse authnSuccessResponse = (this.authnRequest.getResponseType()
                .contains(ResponseTypeValue.AUTHORIZATION_CODE))
                        ? processAuthzCodeResponse(personUser, sessionId)
                        : processIDTokenResponse(personUser, sessionId);
        if (loginMethod == null) {
            this.sessionManager.update(sessionId, this.clientInfo);
        } else {
            this.sessionManager.add(sessionId, personUser, loginMethod, this.clientInfo);
        }
        HttpResponse httpResponse = authnSuccessResponse.toHttpResponse();
        httpResponse.addCookie(loggedInSessionCookie(sessionId));
        return Pair.of((ModelAndView) null, httpResponse);
    } catch (ServerException e) {
        LoggerUtils.logFailedRequest(logger, e);
        return Pair.of((ModelAndView) null, authnErrorResponse(e).toHttpResponse());
    }
}

From source file:com.formkiq.core.service.workflow.WorkflowServiceImpl.java

@Transactional
@Override/*from ww  w . j  a v  a 2s . c  o m*/
public Pair<ModelAndView, WebFlow> startSigning(final HttpServletRequest request, final String document,
        final String stoken) throws IOException {

    Triple<DocSignQueueMessage, ArchiveDTO, QueueMessage> p = this.signingService.findAssets(document, stoken);

    DocSignQueueMessage msg = p.getLeft();

    ArchiveDTO dto = p.getMiddle();

    updateSignaturesToRequired(dto.getForms().values());

    List<FlowState> states = new ArrayList<>();
    states.add(new FlowState(START));
    FlowState s1 = new FlowState(DEFAULT, null, "flow/summary");
    s1.setParameter("geoLocation", Boolean.TRUE);
    states.add(s1);
    states.add(new FlowState(END, null, "flow/complete"));

    WebFlow flow = startFlow(request, msg.getFolderid(), null, dto, WorkflowEditorServiceImpl.class, states);
    flow.setParameter("docsignmsg", msg);

    return Pair.of(new ModelAndView("redirect:/flow/workflow?execution=" + flow.getSessionKey()), flow);
}

From source file:com.mirth.connect.client.ui.codetemplate.CodeTemplateLibrariesPanel.java

public void initialize() {
    PlatformUI.MIRTH_FRAME.codeTemplatePanel.doRefreshCodeTemplates(new ActionListener() {
        @Override//from w ww.  j av  a  2 s .  c  o  m
        public void actionPerformed(ActionEvent evt) {
            for (CodeTemplateLibrary library : PlatformUI.MIRTH_FRAME.codeTemplatePanel
                    .getCachedCodeTemplateLibraries().values()) {
                libraryMap.put(library.getId(), new CodeTemplateLibrary(library));
            }
            Map<String, CodeTemplate> codeTemplateMap = PlatformUI.MIRTH_FRAME.codeTemplatePanel
                    .getCachedCodeTemplates();

            DefaultMutableTreeTableNode rootNode = new DefaultMutableTreeTableNode();

            for (CodeTemplateLibrary library : libraryMap.values()) {
                boolean enabled = library.getEnabledChannelIds().contains(channelId)
                        || (library.isIncludeNewChannels()
                                && !library.getDisabledChannelIds().contains(channelId));
                DefaultMutableTreeTableNode libraryNode = new DefaultMutableTreeTableNode(
                        new ImmutableTriple<String, String, Boolean>(library.getId(), library.getName(),
                                enabled));

                for (CodeTemplate codeTemplate : library.getCodeTemplates()) {
                    codeTemplate = codeTemplateMap.get(codeTemplate.getId());
                    if (codeTemplate != null) {
                        libraryNode.add(
                                new DefaultMutableTreeTableNode(new ImmutableTriple<String, String, Boolean>(
                                        codeTemplate.getId(), codeTemplate.getName(), enabled)));
                    }
                }

                rootNode.add(libraryNode);
            }

            ((DefaultTreeTableModel) libraryTreeTable.getTreeTableModel()).setRoot(rootNode);
            libraryTreeTable.expandAll();

            libraryTreeTable.getModel().addTableModelListener(new TableModelListener() {
                @Override
                public void tableChanged(TableModelEvent evt) {
                    for (Enumeration<? extends MutableTreeTableNode> libraryNodes = ((DefaultMutableTreeTableNode) libraryTreeTable
                            .getTreeTableModel().getRoot()).children(); libraryNodes.hasMoreElements();) {
                        Triple<String, String, Boolean> triple = (Triple<String, String, Boolean>) libraryNodes
                                .nextElement().getUserObject();

                        CodeTemplateLibrary library = libraryMap.get(triple.getLeft());
                        if (triple.getRight()) {
                            library.getDisabledChannelIds().remove(channelId);
                            library.getEnabledChannelIds().add(channelId);
                        } else {
                            library.getDisabledChannelIds().add(channelId);
                            library.getEnabledChannelIds().remove(channelId);
                        }
                    }
                }
            });

            parent.codeTemplateLibrariesReady();
        }
    });
}

From source file:at.gridtec.lambda4j.function.tri.to.ThrowableToIntTriFunction.java

/**
 * Applies this function to the given tuple.
 *
 * @param tuple The tuple to be applied to the function
 * @return The return value from the function, which is its result.
 * @throws NullPointerException If given argument is {@code null}
 * @throws X Any throwable from this functions action
 * @see org.apache.commons.lang3.tuple.Triple
 *///from www.  ja va 2 s.c o m
default int applyAsIntThrows(@Nonnull Triple<T, U, V> tuple) throws X {
    Objects.requireNonNull(tuple);
    return applyAsIntThrows(tuple.getLeft(), tuple.getMiddle(), tuple.getRight());
}

From source file:at.gridtec.lambda4j.function.tri.to.ThrowableToByteTriFunction.java

/**
 * Applies this function to the given tuple.
 *
 * @param tuple The tuple to be applied to the function
 * @return The return value from the function, which is its result.
 * @throws NullPointerException If given argument is {@code null}
 * @throws X Any throwable from this functions action
 * @see org.apache.commons.lang3.tuple.Triple
 *///  w w w  . jav  a  2  s. c om
default byte applyAsByteThrows(@Nonnull Triple<T, U, V> tuple) throws X {
    Objects.requireNonNull(tuple);
    return applyAsByteThrows(tuple.getLeft(), tuple.getMiddle(), tuple.getRight());
}

From source file:at.gridtec.lambda4j.function.tri.to.ThrowableToCharTriFunction.java

/**
 * Applies this function to the given tuple.
 *
 * @param tuple The tuple to be applied to the function
 * @return The return value from the function, which is its result.
 * @throws NullPointerException If given argument is {@code null}
 * @throws X Any throwable from this functions action
 * @see org.apache.commons.lang3.tuple.Triple
 *//*from   www. j a  v  a  2s  . com*/
default char applyAsCharThrows(@Nonnull Triple<T, U, V> tuple) throws X {
    Objects.requireNonNull(tuple);
    return applyAsCharThrows(tuple.getLeft(), tuple.getMiddle(), tuple.getRight());
}