All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ocadotechnology.id.IdGenerator Maven / Gradle / Ivy

There is a newer version: 16.6.21
Show newest version
/*
 * Copyright © 2017-2023 Ocado (Ocava)
 *
 * 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.ocadotechnology.id;

import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

import com.google.common.collect.ImmutableMap;

/**
 * Generates per-class-unique type-safe or non-type-safe Ids.
 * This class can be access by multiple threads.
 */
public final class IdGenerator {
    private static final Map, AtomicLong> idCounters = new ConcurrentHashMap<>();

    private IdGenerator() {
    }

    /**
     * Gets a type-safe Id object for convenient. Ids created by calls to this
     * function are not backed by a cache and as such are suitable
     * for use with continually incrementing values.
     * @param classForId class which represents Id
     */
    public static  Id getId(Class classForId) {
        return Id.create(getNextId(classForId));
    }

    /**
     * Gets a cache-backed, type-safe Id object. The backing cache shares
     * objects between classes to avoid unnecessary object instantiation.
     * 

* Classes with a fixed pool of objects are a * good candidate for cached Ids, but continually incrementing ranges * will cause shared objects to be pushed out of * the cache when it fills, rendering the cache useless. * @param classForId class which represents Id */ public static Id getCachedId(Class classForId) { return Id.createCached(getNextId(classForId)); } /** * Returns the non-type-safe, per class unique long id generator. For use with classes that are instantiated in * large numbers, where the overhead of the map lookup and the creation of the typed id object is too slow. * @param classForId class which represents Id */ public static AtomicLong getRawIdGenerator(Class classForId) { AtomicLong counter = idCounters.get(classForId); //computeIfAbsent is slower (in concurrentHashMap) than get and then computeIfAbsent if null return counter != null ? counter : idCounters.computeIfAbsent(classForId, k -> new AtomicLong()); } /** * Allows to reset the counter to selected value * @param classForId class which represents Id * @param initialId new initial Id value */ public static void initialiseIdCounter(Class classForId, long initialId) { getRawIdGenerator(classForId).set(initialId); } /** * Returns a copy of the current state of the id generator */ public static ImmutableMap, Long> snapshot() { return idCounters.entrySet().stream() .collect(ImmutableMap.toImmutableMap(Entry::getKey, e -> e.getValue().get())); } /** * Discouraged use, see notes

* * Sets all cached entries to zero. *

* *

* Note 1: * Should be used only by tests as it does not guarantee atomicity *

*

* Note 2: * This class provides globally available ids, based on classes. Extra care needs to be taken when using the * reset method, so as not to lead to unwanted id collisions. * This is particularly important with test engines, and test suites. *

* Test suites usually are composed by some one-time code (constructors, @BeforeAll/@AfterAll callbacks), * and a test loop(@BeforeEach/@AfterEach callback, test itself). *

* Do not use reset in your tests, if the IdGenerator is used outside of the test loop. * Tests using this class should rather be id-agnostic, and not rely on the generator providing specific ids. *

* */ public static void clear() { idCounters.values().forEach(c -> c.set(0)); } private static long getNextId(Class clazz) { return getRawIdGenerator(clazz).getAndIncrement(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy