Fix 40 errors from checkstyle plugin run. 139 left))
This commit is contained in:
		@@ -1,26 +1,3 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The MIT License
 | 
			
		||||
 * Copyright © 2014-2021 Ilkka Seppälä
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.caching;
 | 
			
		||||
 | 
			
		||||
import com.iluwatar.caching.database.DbManager;
 | 
			
		||||
@@ -28,33 +5,42 @@ import com.iluwatar.caching.database.DbManagerFactory;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The Caching pattern describes how to avoid expensive re-acquisition of resources by not releasing
 | 
			
		||||
 * the resources immediately after their use. The resources retain their identity, are kept in some
 | 
			
		||||
 * fast-access storage, and are re-used to avoid having to acquire them again. There are four main
 | 
			
		||||
 * caching strategies/techniques in this pattern; each with their own pros and cons. They are;
 | 
			
		||||
 * <code>write-through</code> which writes data to the cache and DB in a single transaction,
 | 
			
		||||
 * <code>write-around</code> which writes data immediately into the DB instead of the cache,
 | 
			
		||||
 * <code>write-behind</code> which writes data into the cache initially whilst the data is only
 | 
			
		||||
 * written into the DB when the cache is full, and <code>cache-aside</code> which pushes the
 | 
			
		||||
 * responsibility of keeping the data synchronized in both data sources to the application itself.
 | 
			
		||||
 * The <code>read-through</code> strategy is also included in the mentioned four strategies --
 | 
			
		||||
 * returns data from the cache to the caller <b>if</b> it exists <b>else</b> queries from DB and
 | 
			
		||||
 * stores it into the cache for future use. These strategies determine when the data in the cache
 | 
			
		||||
 * should be written back to the backing store (i.e. Database) and help keep both data sources
 | 
			
		||||
 * synchronized/up-to-date. This pattern can improve performance and also helps to maintain
 | 
			
		||||
 * consistency between data held in the cache and the data in the underlying data store.
 | 
			
		||||
 * The Caching pattern describes how to avoid expensive re-acquisition of
 | 
			
		||||
 * resources by not releasing the resources immediately after their use.
 | 
			
		||||
 * The resources retain their identity, are kept in some fast-access storage,
 | 
			
		||||
 * and are re-used to avoid having to acquire them again. There are four main
 | 
			
		||||
 * caching strategies/techniques in this pattern; each with their own pros and
 | 
			
		||||
 * cons. They are <code>write-through</code> which writes data to the cache and
 | 
			
		||||
 * DB in a single transaction, <code>write-around</code> which writes data
 | 
			
		||||
 * immediately into the DB instead of the cache, <code>write-behind</code>
 | 
			
		||||
 * which writes data into the cache initially whilst the data is only
 | 
			
		||||
 * written into the DB when the cache is full, and <code>cache-aside</code>
 | 
			
		||||
 * which pushes the responsibility of keeping the data synchronized in both
 | 
			
		||||
 * data sources to the application itself. The <code>read-through</code>
 | 
			
		||||
 * strategy is also included in the mentioned four strategies --
 | 
			
		||||
 * returns data from the cache to the caller <b>if</b> it exists <b>else</b>
 | 
			
		||||
 * queries from DB and stores it into the cache for future use. These strategies
 | 
			
		||||
 * determine when the data in the cache should be written back to the backing
 | 
			
		||||
 * store (i.e. Database) and help keep both data sources
 | 
			
		||||
 * synchronized/up-to-date. This pattern can improve performance and also helps
 | 
			
		||||
 * to maintainconsistency between data held in the cache and the data in
 | 
			
		||||
 * the underlying data store.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>In this example, the user account ({@link UserAccount}) entity is used as the underlying
 | 
			
		||||
 * application data. The cache itself is implemented as an internal (Java) data structure. It adopts
 | 
			
		||||
 * a Least-Recently-Used (LRU) strategy for evicting data from itself when its full. The four
 | 
			
		||||
 * strategies are individually tested. The testing of the cache is restricted towards saving and
 | 
			
		||||
 * querying of user accounts from the underlying data store ( {@link DbManager}). The main class (
 | 
			
		||||
 * {@link App} is not aware of the underlying mechanics of the application (i.e. save and query) and
 | 
			
		||||
 * whether the data is coming from the cache or the DB (i.e. separation of concern). The AppManager
 | 
			
		||||
 * ({@link AppManager}) handles the transaction of data to-and-from the underlying data store
 | 
			
		||||
 * (depending on the preferred caching policy/strategy).
 | 
			
		||||
 * <p>In this example, the user account ({@link UserAccount}) entity is used
 | 
			
		||||
 * as the underlying application data. The cache itself is implemented as an
 | 
			
		||||
 * internal (Java) data structure. It adopts a Least-Recently-Used (LRU)
 | 
			
		||||
 * strategy for evicting data from itself when its full. The four
 | 
			
		||||
 * strategies are individually tested. The testing of the cache is restricted
 | 
			
		||||
 * towards saving and querying of user accounts from the
 | 
			
		||||
 * underlying data store( {@link DbManager}). The main class ( {@link App}
 | 
			
		||||
 * is not aware of the underlying mechanics of the application
 | 
			
		||||
 * (i.e. save and query) and whether the data is coming from the cache or the
 | 
			
		||||
 * DB (i.e. separation of concern). The AppManager ({@link AppManager}) handles
 | 
			
		||||
 * the transaction of data to-and-from the underlying data store (depending on
 | 
			
		||||
 * the preferred caching policy/strategy).
 | 
			
		||||
 * <p>
 | 
			
		||||
 * <i>{@literal App --> AppManager --> CacheStore/LRUCache/CachingPolicy --> DBManager} </i>
 | 
			
		||||
 * <i>{@literal App --> AppManager --> CacheStore/LRUCache/CachingPolicy -->
 | 
			
		||||
 *     DBManager} </i>
 | 
			
		||||
 * </p>
 | 
			
		||||
 *
 | 
			
		||||
 * <p>
 | 
			
		||||
@@ -68,10 +54,20 @@ import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 */
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class App {
 | 
			
		||||
    /**
 | 
			
		||||
     * Constant parameter name to use mongoDB.
 | 
			
		||||
     */
 | 
			
		||||
    private static final String USE_MONGO_DB = "--mongo";
 | 
			
		||||
    private AppManager appManager;
 | 
			
		||||
    /**
 | 
			
		||||
     * Application manager.
 | 
			
		||||
     */
 | 
			
		||||
    private final AppManager appManager;
 | 
			
		||||
 | 
			
		||||
    public App(boolean isMongo) {
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor of current App.
 | 
			
		||||
     * @param isMongo boolean
 | 
			
		||||
     */
 | 
			
		||||
    public App(final boolean isMongo) {
 | 
			
		||||
        DbManager dbManager = DbManagerFactory.initDb(isMongo);
 | 
			
		||||
        appManager = new AppManager(dbManager);
 | 
			
		||||
        appManager.initDb();
 | 
			
		||||
@@ -82,20 +78,20 @@ public class App {
 | 
			
		||||
     *
 | 
			
		||||
     * @param args command line args
 | 
			
		||||
     */
 | 
			
		||||
    public static void main(String[] args) {
 | 
			
		||||
    public static void main(final String[] args) {
 | 
			
		||||
        // VirtualDB (instead of MongoDB) was used in running the JUnit tests
 | 
			
		||||
        // and the App class to avoid Maven compilation errors. Set flag to
 | 
			
		||||
        // true to run the tests with MongoDB (provided that MongoDB is
 | 
			
		||||
        // installed and socket connection is open).
 | 
			
		||||
        App app = new App(isDbMongo(args));
 | 
			
		||||
        app.useReadAndWriteThroughStrategy();
 | 
			
		||||
        System.out.println("=====================================================");
 | 
			
		||||
        System.out.println("==============================================");
 | 
			
		||||
        app.useReadThroughAndWriteAroundStrategy();
 | 
			
		||||
        System.out.println("=====================================================");
 | 
			
		||||
        System.out.println("==============================================");
 | 
			
		||||
        app.useReadThroughAndWriteBehindStrategy();
 | 
			
		||||
        System.out.println("=====================================================");
 | 
			
		||||
        System.out.println("==============================================");
 | 
			
		||||
        app.useCacheAsideStategy();
 | 
			
		||||
        System.out.println("=====================================================");
 | 
			
		||||
        System.out.println("==============================================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -103,7 +99,7 @@ public class App {
 | 
			
		||||
     * @param args input params
 | 
			
		||||
     * @return true if there is "--mongo" parameter in arguments
 | 
			
		||||
     */
 | 
			
		||||
    private static boolean isDbMongo(String[] args) {
 | 
			
		||||
    private static boolean isDbMongo(final String[] args) {
 | 
			
		||||
        for (String arg : args) {
 | 
			
		||||
            if (arg.equals(USE_MONGO_DB)) {
 | 
			
		||||
                return true;
 | 
			
		||||
@@ -156,9 +152,15 @@ public class App {
 | 
			
		||||
        LOGGER.info("# CachingPolicy.BEHIND");
 | 
			
		||||
        appManager.initCachingPolicy(CachingPolicy.BEHIND);
 | 
			
		||||
 | 
			
		||||
        var userAccount3 = new UserAccount("003", "Adam", "He likes food.");
 | 
			
		||||
        var userAccount4 = new UserAccount("004", "Rita", "She hates cats.");
 | 
			
		||||
        var userAccount5 = new UserAccount("005", "Isaac", "He is allergic to mustard.");
 | 
			
		||||
        var userAccount3 = new UserAccount("003",
 | 
			
		||||
                "Adam",
 | 
			
		||||
                "He likes food.");
 | 
			
		||||
        var userAccount4 = new UserAccount("004",
 | 
			
		||||
                "Rita",
 | 
			
		||||
                "She hates cats.");
 | 
			
		||||
        var userAccount5 = new UserAccount("005",
 | 
			
		||||
                "Isaac",
 | 
			
		||||
                "He is allergic to mustard.");
 | 
			
		||||
 | 
			
		||||
        appManager.save(userAccount3);
 | 
			
		||||
        appManager.save(userAccount4);
 | 
			
		||||
@@ -166,7 +168,9 @@ public class App {
 | 
			
		||||
        LOGGER.info(appManager.printCacheContent());
 | 
			
		||||
        appManager.find("003");
 | 
			
		||||
        LOGGER.info(appManager.printCacheContent());
 | 
			
		||||
        UserAccount userAccount6 = new UserAccount("006", "Yasha", "She is an only child.");
 | 
			
		||||
        UserAccount userAccount6 = new UserAccount("006",
 | 
			
		||||
                "Yasha",
 | 
			
		||||
                "She is an only child.");
 | 
			
		||||
        appManager.save(userAccount6);
 | 
			
		||||
        LOGGER.info(appManager.printCacheContent());
 | 
			
		||||
        appManager.find("004");
 | 
			
		||||
@@ -181,9 +185,15 @@ public class App {
 | 
			
		||||
        appManager.initCachingPolicy(CachingPolicy.ASIDE);
 | 
			
		||||
        LOGGER.info(appManager.printCacheContent());
 | 
			
		||||
 | 
			
		||||
        var userAccount3 = new UserAccount("003", "Adam", "He likes food.");
 | 
			
		||||
        var userAccount4 = new UserAccount("004", "Rita", "She hates cats.");
 | 
			
		||||
        var userAccount5 = new UserAccount("005", "Isaac", "He is allergic to mustard.");
 | 
			
		||||
        var userAccount3 = new UserAccount("003",
 | 
			
		||||
                "Adam",
 | 
			
		||||
                "He likes food.");
 | 
			
		||||
        var userAccount4 = new UserAccount("004",
 | 
			
		||||
                "Rita",
 | 
			
		||||
                "She hates cats.");
 | 
			
		||||
        var userAccount5 = new UserAccount("005",
 | 
			
		||||
                "Isaac",
 | 
			
		||||
                "He is allergic to mustard.");
 | 
			
		||||
        appManager.save(userAccount3);
 | 
			
		||||
        appManager.save(userAccount4);
 | 
			
		||||
        appManager.save(userAccount5);
 | 
			
		||||
 
 | 
			
		||||
@@ -29,28 +29,41 @@ import com.iluwatar.caching.database.DbManager;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * AppManager helps to bridge the gap in communication between the main class and the application's
 | 
			
		||||
 * back-end. DB connection is initialized through this class. The chosen caching strategy/policy is
 | 
			
		||||
 * also initialized here. Before the cache can be used, the size of the cache has to be set.
 | 
			
		||||
 * Depending on the chosen caching policy, AppManager will call the appropriate function in the
 | 
			
		||||
 * CacheStore class.
 | 
			
		||||
 * AppManager helps to bridge the gap in communication between the main class
 | 
			
		||||
 * and the application's back-end. DB connection is initialized through this
 | 
			
		||||
 * class. The chosen  caching strategy/policy is also initialized here.
 | 
			
		||||
 * Before the cache can be used, the size of the  cache has to be set.
 | 
			
		||||
 * Depending on the chosen caching policy, AppManager will call the
 | 
			
		||||
 * appropriate function in the CacheStore class.
 | 
			
		||||
 */
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class AppManager {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Caching Policy.
 | 
			
		||||
   */
 | 
			
		||||
  private static CachingPolicy cachingPolicy;
 | 
			
		||||
  /**
 | 
			
		||||
   * Database Manager.
 | 
			
		||||
   */
 | 
			
		||||
  private final DbManager dbManager;
 | 
			
		||||
  /**
 | 
			
		||||
   * Cache Store.
 | 
			
		||||
   */
 | 
			
		||||
  private final CacheStore cacheStore;
 | 
			
		||||
 | 
			
		||||
  public AppManager(DbManager dbManager) {
 | 
			
		||||
    this.dbManager = dbManager;
 | 
			
		||||
    this.cacheStore = new CacheStore(dbManager);
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructor.
 | 
			
		||||
   * @param newDbManager database manager
 | 
			
		||||
   */
 | 
			
		||||
  public AppManager(final DbManager newDbManager) {
 | 
			
		||||
    this.dbManager = newDbManager;
 | 
			
		||||
    this.cacheStore = new CacheStore(newDbManager);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Developer/Tester is able to choose whether the application should use MongoDB as its underlying
 | 
			
		||||
   * data storage or a simple Java data structure to (temporarily) store the data/objects during
 | 
			
		||||
   * runtime.
 | 
			
		||||
   * Developer/Tester is able to choose whether the application should use
 | 
			
		||||
   * MongoDB as its underlying data storage or a simple Java data structure
 | 
			
		||||
   * to (temporarily) store the data/objects during runtime.
 | 
			
		||||
   */
 | 
			
		||||
  public void initDb() {
 | 
			
		||||
     dbManager.connect();
 | 
			
		||||
@@ -58,8 +71,9 @@ public class AppManager {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Initialize caching policy.
 | 
			
		||||
   * @param policy is a {@link CachingPolicy}
 | 
			
		||||
   */
 | 
			
		||||
  public void initCachingPolicy(CachingPolicy policy) {
 | 
			
		||||
  public void initCachingPolicy(final CachingPolicy policy) {
 | 
			
		||||
    cachingPolicy = policy;
 | 
			
		||||
    if (cachingPolicy == CachingPolicy.BEHIND) {
 | 
			
		||||
      Runtime.getRuntime().addShutdownHook(new Thread(cacheStore::flushCache));
 | 
			
		||||
@@ -69,10 +83,13 @@ public class AppManager {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Find user account.
 | 
			
		||||
   * @param userId String
 | 
			
		||||
   * @return {@link UserAccount}
 | 
			
		||||
   */
 | 
			
		||||
  public UserAccount find(String userId) {
 | 
			
		||||
  public UserAccount find(final String userId) {
 | 
			
		||||
    LOGGER.info("Trying to find {} in cache", userId);
 | 
			
		||||
    if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) {
 | 
			
		||||
    if (cachingPolicy == CachingPolicy.THROUGH
 | 
			
		||||
            || cachingPolicy == CachingPolicy.AROUND) {
 | 
			
		||||
      return cacheStore.readThrough(userId);
 | 
			
		||||
    } else if (cachingPolicy == CachingPolicy.BEHIND) {
 | 
			
		||||
      return cacheStore.readThroughWithWriteBackPolicy(userId);
 | 
			
		||||
@@ -84,8 +101,9 @@ public class AppManager {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Save user account.
 | 
			
		||||
   * @param userAccount {@link UserAccount}
 | 
			
		||||
   */
 | 
			
		||||
  public void save(UserAccount userAccount) {
 | 
			
		||||
  public void save(final UserAccount userAccount) {
 | 
			
		||||
    LOGGER.info("Save record!");
 | 
			
		||||
    if (cachingPolicy == CachingPolicy.THROUGH) {
 | 
			
		||||
      cacheStore.writeThrough(userAccount);
 | 
			
		||||
@@ -98,25 +116,33 @@ public class AppManager {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns String.
 | 
			
		||||
   * @return String
 | 
			
		||||
   */
 | 
			
		||||
  public String printCacheContent() {
 | 
			
		||||
    return cacheStore.print();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Cache-Aside save user account helper.
 | 
			
		||||
   * @param userAccount {@link UserAccount}
 | 
			
		||||
   */
 | 
			
		||||
  private void saveAside(UserAccount userAccount) {
 | 
			
		||||
  private void saveAside(final UserAccount userAccount) {
 | 
			
		||||
    dbManager.updateDb(userAccount);
 | 
			
		||||
    cacheStore.invalidate(userAccount.getUserId());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Cache-Aside find user account helper.
 | 
			
		||||
   * @param userId String
 | 
			
		||||
   * @return {@link UserAccount}
 | 
			
		||||
   */
 | 
			
		||||
  private UserAccount findAside(String userId) {
 | 
			
		||||
  private UserAccount findAside(final String userId) {
 | 
			
		||||
    return Optional.ofNullable(cacheStore.get(userId))
 | 
			
		||||
        .or(() -> {
 | 
			
		||||
          Optional<UserAccount> userAccount = Optional.ofNullable(dbManager.readFromDb(userId));
 | 
			
		||||
          Optional<UserAccount> userAccount =
 | 
			
		||||
                  Optional.ofNullable(dbManager.readFromDb(userId));
 | 
			
		||||
          userAccount.ifPresent(account -> cacheStore.set(userId, account));
 | 
			
		||||
          return userAccount;
 | 
			
		||||
        })
 | 
			
		||||
 
 | 
			
		||||
@@ -3,14 +3,38 @@ package com.iluwatar.caching.database;
 | 
			
		||||
import com.iluwatar.caching.UserAccount;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * <p>DBManager handles the communication with the underlying data store i.e. Database. It contains
 | 
			
		||||
 * the implemented methods for querying, inserting, and updating data. MongoDB was used as the
 | 
			
		||||
 * database for the application.</p>
 | 
			
		||||
 * <p>DBManager handles the communication with the underlying data store i.e.
 | 
			
		||||
 * Database. It contains the implemented methods for querying, inserting,
 | 
			
		||||
 * and updating data. MongoDB was used as the database for the application.</p>
 | 
			
		||||
 */
 | 
			
		||||
public interface DbManager {
 | 
			
		||||
    /**
 | 
			
		||||
     * Connect to DB.
 | 
			
		||||
     */
 | 
			
		||||
    void connect();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Read from DB.
 | 
			
		||||
     * @param userId {@link String}
 | 
			
		||||
     * @return {@link UserAccount}
 | 
			
		||||
     */
 | 
			
		||||
    UserAccount readFromDb(String userId);
 | 
			
		||||
    /**
 | 
			
		||||
     * Write to DB.
 | 
			
		||||
     * @param userAccount {@link UserAccount}
 | 
			
		||||
     * @return {@link UserAccount}
 | 
			
		||||
     */
 | 
			
		||||
    UserAccount writeToDb(UserAccount userAccount);
 | 
			
		||||
    /**
 | 
			
		||||
     * Update record.
 | 
			
		||||
     * @param userAccount {@link UserAccount}
 | 
			
		||||
     * @return {@link UserAccount}
 | 
			
		||||
     */
 | 
			
		||||
    UserAccount updateDb(UserAccount userAccount);
 | 
			
		||||
    /**
 | 
			
		||||
     * Update record or Insert if not exists.
 | 
			
		||||
     * @param userAccount {@link UserAccount}
 | 
			
		||||
     * @return {@link UserAccount}
 | 
			
		||||
     */
 | 
			
		||||
    UserAccount upsertDb(UserAccount userAccount);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Database classes
 | 
			
		||||
 */
 | 
			
		||||
package com.iluwatar.caching.database;
 | 
			
		||||
							
								
								
									
										24
									
								
								caching/src/main/java/com/iluwatar/caching/package-info.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								caching/src/main/java/com/iluwatar/caching/package-info.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The MIT License
 | 
			
		||||
 * Copyright © 2014-2021 Ilkka Seppälä
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package com.iluwatar.caching;
 | 
			
		||||
		Reference in New Issue
	
	Block a user