com.jkoolcloud.tnt4j.streams.utils.StreamsCache.java Source code

Java tutorial

Introduction

Here is the source code for com.jkoolcloud.tnt4j.streams.utils.StreamsCache.java

Source

/*
 * Copyright 2014-2017 JKOOL, LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jkoolcloud.tnt4j.streams.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.jkoolcloud.tnt4j.streams.fields.ActivityInfo;

/**
 * Utility class to support TNT4J-Streams streamed data values caching.
 * <p>
 * Cache entries are defined using static or dynamic (e.g., patterns having field name variable to fill in data from
 * activity entity) values.
 *
 * @version $Revision: 2 $
 */
public class StreamsCache {
    private static final long DEFAULT_CACHE_MAX_SIZE = 100;
    private static final long DEFAULT_CACHE_EXPIRE_IN_MINUTES = 10;

    private static final String PARSER_NAME_VAR = "${ParserName}"; // NON-NLS

    private static Cache<String, Object> valuesCache;
    private static Map<String, CacheEntry> cacheEntries = new HashMap<>();

    private static Cache<String, Object> buildCache(long cSize, long duration) {
        return CacheBuilder.newBuilder().maximumSize(cSize).expireAfterAccess(duration, TimeUnit.MINUTES).build();
    }

    /**
     * Initializes cache setting maximum cache size and cache entries expiration duration.
     *
     * @param cSize
     *            maximum cache size
     * @param duration
     *            cache entries expiration duration
     */
    public static void initCache(Integer cSize, Integer duration) {
        valuesCache = buildCache(cSize == null ? DEFAULT_CACHE_MAX_SIZE : cSize,
                duration == null ? DEFAULT_CACHE_EXPIRE_IN_MINUTES : duration);
    }

    /**
     * Fills in cache entries patterns with activity entity fields values and puts filled in entries to cache.
     *
     * @param ai
     *            activity entity to be used to fill in patterns data
     * @param parserName
     *            parser name
     */
    public static void cacheValues(ActivityInfo ai, String parserName) {
        if (valuesCache == null) {
            valuesCache = buildCache(DEFAULT_CACHE_MAX_SIZE, DEFAULT_CACHE_EXPIRE_IN_MINUTES);
        }

        for (CacheEntry cacheEntry : cacheEntries.values()) {
            String resolvedFieldKey = fillInKeyPattern(cacheEntry.getKey(), ai, parserName);
            Object resolvedFieldValue = fillInValuePattern(cacheEntry.getValue(), ai, parserName);

            if (resolvedFieldKey != null && resolvedFieldValue != null) {
                valuesCache.put(resolvedFieldKey, resolvedFieldValue);
            }
        }
    }

    /**
     * Fills in some key pattern string with activity entity fields values.
     * 
     * @param pattern
     *            pattern string to fill
     * @param ai
     *            activity entity data
     * @param parserName
     *            parser name
     * @return pattern string filled in with data values
     */
    public static String fillInKeyPattern(String pattern, ActivityInfo ai, String parserName) {
        List<String> vars = new ArrayList<>();
        Utils.resolveCfgVariables(vars, pattern);

        return fillInPattern(pattern, vars, ai, parserName);
    }

    private static Object fillInValuePattern(String pattern, ActivityInfo ai, String parserName) {
        List<String> vars = new ArrayList<>();
        Utils.resolveCfgVariables(vars, pattern);

        return vars.size() == 1 ? getActivityValue(vars.get(0), ai) : fillInPattern(pattern, vars, ai, parserName);
    }

    private static String fillInPattern(String pattern, List<String> vars, ActivityInfo ai, String parserName) {
        String filledInValue = pattern;

        for (String var : vars) {
            Object fieldValue;
            if (var.equals(PARSER_NAME_VAR)) {
                fieldValue = parserName;
            } else {
                fieldValue = getActivityValue(var, ai);
            }

            if (fieldValue != null) {
                filledInValue = filledInValue.replace(var, Utils.toString(fieldValue));
            }
        }

        return filledInValue;
    }

    private static Object getActivityValue(String var, ActivityInfo ai) {
        if (ai == null) {
            return null;
        }

        String varKey = var.substring(2, var.length() - 1);
        return ai.getFieldValue(varKey);
    }

    /**
     * Resolves cache stored value identified by cache entry id.
     *
     * @param ai
     *            activity entity to be used to fill in patterns data
     * @param entryIdStr
     *            cache entity pattern identifier string
     * @param parserName
     *            parser name
     * @return resolved cached value or {@code null} if there is no such entry or data in cache
     */
    public static Object getValue(ActivityInfo ai, String entryIdStr, String parserName) {
        CacheEntry cacheEntry = cacheEntries.get(entryIdStr);
        if (cacheEntry != null) {
            String cacheKey = fillInKeyPattern(cacheEntry.getKey(), ai, parserName);
            if (cacheKey != null) {
                return valuesCache == null ? null : valuesCache.getIfPresent(cacheKey);
            }
        }

        return null;
    }

    /**
     * Cleans cache contents.
     */
    public static void cleanup() {
        if (valuesCache != null) {
            valuesCache.cleanUp();
        }
        if (cacheEntries != null) {
            cacheEntries.clear();
        }
    }

    /**
     * Adds cache entry pattern definition to cache entry patterns map.
     *
     * @param entryId
     *            entry identifier
     * @param key
     *            entry key pattern
     * @param value
     *            entry value pattern
     * @return previous cache entry instance stored
     */
    public static CacheEntry addEntry(String entryId, String key, String value) {
        return cacheEntries.put(entryId, new CacheEntry(entryId, key, value));
    }

    /**
     * Defines cache entry pattern.
     */
    public static class CacheEntry {
        private String id;
        private String key;
        private String value;

        /**
         * Constructs new CacheEntry.
         *
         * @param id
         *            cache entry identifier
         * @param key
         *            cache entry key pattern
         * @param value
         *            cache entry value pattern
         */
        private CacheEntry(String id, String key, String value) {
            this.id = id;
            this.key = key;
            this.value = value;
        }

        /**
         * Returns cache entry identifier.
         *
         * @return entry identifier
         */
        public String getId() {
            return id;
        }

        /**
         * Returns cache entry key pattern.
         *
         * @return cache entry key pattern
         */
        public String getKey() {
            return key;
        }

        /**
         * Returns cache entry value pattern.
         *
         * @return cache entry value pattern
         */
        public String getValue() {
            return value;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("CacheEntry{"); // NON-NLS
            sb.append("id=").append(Utils.quote(id)); // NON-NLS
            sb.append(", key=").append(Utils.quote(key)); // NON-NLS
            sb.append(", value=").append(Utils.quote(value)); // NON-NLS
            sb.append('}'); // NON-NLS
            return sb.toString();
        }
    }
}