/** {@inheritDoc} */
  @Transactional(readOnly = true)
  @Timed(name = "GET_TICKET_TIMER")
  @Metered(name = "GET_TICKET_METER")
  @Counted(name = "GET_TICKET_COUNTER", monotonic = true)
  @Override
  public <T extends Ticket> T getTicket(final String ticketId, final Class<? extends Ticket> clazz)
      throws InvalidTicketException {
    Assert.notNull(ticketId, "ticketId cannot be null");
    final Ticket ticket = this.ticketRegistry.getTicket(ticketId, clazz);

    if (ticket == null) {
      logger.debug(
          "Ticket [{}] by type [{}] cannot be found in the ticket registry.",
          ticketId,
          clazz.getSimpleName());
      throw new InvalidTicketException(ticketId);
    }

    if (ticket instanceof TicketGrantingTicket) {
      synchronized (ticket) {
        if (ticket.isExpired()) {
          this.ticketRegistry.deleteTicket(ticketId);
          logger.debug(
              "Ticket [{}] has expired and is now deleted from the ticket registry.", ticketId);
          throw new InvalidTicketException(ticketId);
        }
      }
    }
    return (T) ticket;
  }
  /** @throws IllegalArgumentException if the Ticket is null. */
  public void addTicket(final Ticket ticket) {
    Assert.notNull(ticket, "ticket cannot be null");

    if (log.isDebugEnabled()) {
      log.debug("Added ticket [" + ticket.getId() + "] to registry.");
    }
    this.cache.put(ticket.getId(), ticket);
  }
 @Override
 public void addTicket(final Ticket ticketToAdd) {
   final Ticket ticket = encodeTicket(ticketToAdd);
   logger.debug("Adding ticket {}", ticket);
   try {
     if (!this.client.add(ticket.getId(), getTimeout(ticket), ticket).get()) {
       logger.error("Failed adding {}", ticket);
     }
   } catch (final InterruptedException e) {
     logger.warn(
         "Interrupted while waiting for response to async add operation for ticket {}."
             + "Cannot determine whether add was successful.",
         ticket);
   } catch (final Exception e) {
     logger.error("Failed adding {}", ticket, e);
   }
 }
 @Override
 protected void updateTicket(final Ticket ticketToUpdate) {
   final Ticket ticket = encodeTicket(ticketToUpdate);
   logger.debug("Updating ticket {}", ticket);
   try {
     if (!this.client.replace(ticket.getId(), getTimeout(ticket), ticket).get()) {
       logger.error("Failed updating {}", ticket);
     }
   } catch (final InterruptedException e) {
     logger.warn(
         "Interrupted while waiting for response to async replace operation for ticket {}. "
             + "Cannot determine whether update was successful.",
         ticket);
   } catch (final Exception e) {
     logger.error("Failed updating {}", ticket, e);
   }
 }
 @Override
 public void addTicket(final Ticket ticket) {
   final Element element = new Element(ticket.getId(), ticket);
   if (ticket instanceof ServiceTicket) {
     logger.debug(
         "Adding service ticket {} to the cache {}",
         ticket.getId(),
         this.serviceTicketsCache.getName());
     this.serviceTicketsCache.put(element);
   } else if (ticket instanceof TicketGrantingTicket) {
     logger.debug(
         "Adding ticket granting ticket {} to the cache {}",
         ticket.getId(),
         this.ticketGrantingTicketsCache.getName());
     this.ticketGrantingTicketsCache.put(element);
   } else {
     throw new IllegalArgumentException("Invalid ticket type " + ticket);
   }
 }
  /**
   * {@inheritDoc} Either the element is removed from the cache or it's not found in the cache and
   * is already removed. Thus the result of this op would always be true.
   */
  @Override
  public boolean deleteSingleTicket(final String ticketId) {

    final Ticket ticket = getTicket(ticketId);
    if (ticket == null) {
      logger.debug("Ticket {} cannot be retrieved from the cache", ticketId);
      return true;
    }

    if (ticket instanceof ServiceTicket) {
      if (this.serviceTicketsCache.remove(ticket.getId())) {
        logger.debug("Service ticket {} is removed", ticket.getId());
      }
    } else {
      if (this.ticketGrantingTicketsCache.remove(ticket.getId())) {
        logger.debug("Ticket-granting ticket {} is removed", ticket.getId());
      }
    }
    return true;
  }