class InvalidateMultiCacheAdvice extends CacheAdvice {

    @Around("invalidateMulti()")
    public Object cacheInvalidateMulti(final ProceedingJoinPoint pjp) throws Throwable {
        if (isDisabled()) {
            getLogger().info("Cache disabled");
            return pjp.proceed();
        }

        // This is injected caching. If anything goes wrong in the caching, LOG
        // the crap outta it, but do not let it surface up past the AOP injection itself.
        Collection<String> cacheKeys = null;
        final AnnotationData data;
        final Method methodToCache;
        try {
            methodToCache = getCacheBase().getMethodToCache(pjp, InvalidateMultiCache.class);
            final InvalidateMultiCache annotation = methodToCache.getAnnotation(InvalidateMultiCache.class);
            data = AnnotationDataBuilder.buildAnnotationData(annotation, InvalidateMultiCache.class, methodToCache);
            if (!data.isReturnKeyIndex()) {
                cacheKeys = getCacheBase().getCacheKeyBuilder().getCacheKeys(data, pjp.getArgs(), methodToCache.toString());
            }
        } catch (Exception ex) {
            warn(ex, "Caching on method %s aborted due to an error.", pjp.toShortString());
            return pjp.proceed();
        }

        final Object result = pjp.proceed();

        // This is injected caching. If anything goes wrong in the caching, LOG
        // the crap outta it, but do not let it surface up past the AOP injection itself.
        try {
            // If we have a -1 key index, then build the cacheKeys now.
            if (data.isReturnKeyIndex()) {
                if (!getCacheBase().verifyTypeIsList(result.getClass())) {
                    throw new InvalidAnnotationException(String.format("The return type is not a [%s]. "
                            + "The method [%s] does not fulfill the requirements.", List.class.getName(), methodToCache.toString()));
                }

                @SuppressWarnings("unchecked")
                final List<Object> keyObjects = (List<Object>) result;
                cacheKeys = getCacheBase().getCacheKeyBuilder().getCacheKeys(keyObjects, data.getNamespace());
            }
            getCacheBase().getCache(data).delete(cacheKeys);
        } catch (Exception ex) {
            warn(ex, "Caching on method %s aborted due to an error.", pjp.toShortString());
        }
        return result;

    }

}