package org.apereo.cas.ticket.registry;

import org.apereo.cas.ticket.Ticket;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.infinispan.Cache;

import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

/**
 * This is {@link InfinispanTicketRegistry}. Infinispan is a distributed in-memory
 * key/value data store with optional schema.
 * It offers advanced functionality such as transactions, events, querying and distributed processing.
 * See <a href="http://infinispan.org/features/">http://infinispan.org/features/</a> for more info.
 *
 * @author Misagh Moayyed
 * @since 4.2.0
 */
@Slf4j
@RequiredArgsConstructor
public class InfinispanTicketRegistry extends AbstractTicketRegistry {
    private final Cache<String, Ticket> cache;

    @Override
    public Ticket updateTicket(final Ticket ticket) {
        val encodedTicket = encodeTicket(ticket);
        this.cache.put(encodedTicket.getId(), encodedTicket);
        return ticket;
    }

    @Override
    public void addTicket(final Ticket ticketToAdd) {
        val ticket = encodeTicket(ticketToAdd);
        val expirationPolicy = ticketToAdd.getExpirationPolicy();
        val idleTime = expirationPolicy.getTimeToIdle() <= 0
            ? expirationPolicy.getTimeToLive()
            : expirationPolicy.getTimeToIdle();

        LOGGER.debug("Adding ticket [{}] to cache store to live [{}] seconds and stay idle for [{}]",
            ticketToAdd.getId(), getTimeToLive(expirationPolicy), idleTime);

        this.cache.put(ticket.getId(), ticket,
            expirationPolicy.getTimeToLive(), TimeUnit.SECONDS,
            idleTime, TimeUnit.SECONDS);
    }

    @Override
    public Ticket getTicket(final String ticketId, final Predicate<Ticket> predicate) {
        val encTicketId = encodeTicketId(ticketId);
        if (ticketId == null) {
            return null;
        }
        val result = decodeTicket(Ticket.class.cast(cache.get(encTicketId)));
        if (predicate.test(result)) {
            return result;
        }
        return null;
    }

    @Override
    public boolean deleteSingleTicket(final String ticketId) {
        this.cache.remove(encodeTicketId(ticketId));
        return true;
    }

    @Override
    public long deleteAll() {
        val size = this.cache.size();
        this.cache.clear();
        return size;
    }

    /**
     * Retrieve all tickets from the registry.
     *
     * @return collection of tickets currently stored in the registry. Tickets
     * might or might not be valid i.e. expired.
     */
    @Override
    public Collection<? extends Ticket> getTickets() {
        return decodeTickets(this.cache.values());
    }
    
    private Long getTimeToLive(ExpirationPolicy expirationPolicy) {
        val timeToLive = expirationPolicy.getTimeToLive();
        return Long.MAX_VALUE == timeToLive ? Long.valueOf(Integer.MAX_VALUE) : timeToLive;
    }
}

@@ -34,16 +34,63 @@
 istry;%0A%0A
+import org.apereo.cas.ticket.ExpirationPolicy;%0A
 import o
@@ -118,16 +118,16 @@
 Ticket;%0A
-
 %0Aimport 
@@ -1427,24 +1427,75 @@
 eToIdle();%0A%0A
+        val ttl = getTimeToLive(expirationPolicy);%0A
         LOGG
@@ -1583,28 +1583,16 @@
 r %5B%7B%7D%5D%22,
-%0A           
  ticketT
@@ -1609,39 +1609,11 @@
 (), 
-getTimeToLive(expirationPolicy)
+ttl
 , id
@@ -1621,17 +1621,16 @@
 eTime);%0A
-%0A
         
@@ -1671,53 +1671,12 @@
 ket,
-%0A            expirationPolicy.getTimeToLive()
+ ttl
 , Ti
@@ -1690,28 +1690,16 @@
 SECONDS,
-%0A           
  idleTim
@@ -2428,206 +2428,12 @@
   %7D%0A
-%0A
     
-/**%0A     * Retrieve all tickets from the registry.%0A     *%0A     * @return collection of tickets currently stored in the registry. Tickets%0A     * might or might not be valid i.e. expired.%0A     */
 %0A   
@@ -2551,28 +2551,24 @@
 s());%0A    %7D%0A
-    
 %0A    private
@@ -2568,16 +2568,23 @@
 private 
+static 
 Long get
@@ -2594,16 +2594,22 @@
 eToLive(
+final 
 Expirati

fix failure