001/*
002 * (C) Copyright 2018 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.core.uidgen;
020
021import org.nuxeo.ecm.core.api.NuxeoException;
022import org.nuxeo.runtime.api.Framework;
023import org.nuxeo.runtime.kv.KeyValueService;
024import org.nuxeo.runtime.kv.KeyValueStore;
025import org.nuxeo.runtime.services.config.ConfigurationService;
026
027import java.util.ArrayList;
028import java.util.List;
029
030/**
031 * UID Sequencer based on a key/value store. The store is the same for all sequencers, but they are using different
032 * keys, prefixed by the sequencer name.
033 *
034 * @since 10.2
035 */
036public class KeyValueStoreUIDSequencer extends AbstractUIDSequencer {
037
038    /**
039     * Configuration property to specify the key/value store name. If none is specified, {@code sequence} is used.
040     */
041    public static final String STORE_NAME_PROPERTY = "nuxeo.uidseq.keyvaluestore.name";
042
043    public static final String DEFAULT_STORE_NAME = "sequence";
044
045    public static final String SEP = ".";
046
047    protected String storeName;
048
049    @Override
050    public void init() {
051        storeName = Framework.getService(ConfigurationService.class).getString(STORE_NAME_PROPERTY, DEFAULT_STORE_NAME);
052    }
053
054    @Override
055    public void dispose() {
056        // nothing to do
057    }
058
059    protected KeyValueStore getStore() {
060        KeyValueStore store = Framework.getService(KeyValueService.class).getKeyValueStore(storeName);
061        if (store == null) {
062            throw new NuxeoException("Unknown key/value store: " + storeName);
063        }
064        return store;
065    }
066
067    protected String getKey(String key) {
068        return getName() + SEP + key;
069    }
070
071    @Override
072    public void initSequence(String key, long id) {
073        getStore().put(getKey(key), Long.valueOf(id));
074    }
075
076    @Override
077    public long getNextLong(String key) {
078        return getStore().addAndGet(getKey(key), 1);
079    }
080
081    @Override
082    public List<Long> getNextBlock(String key, int blockSize) {
083        List<Long> ret = new ArrayList<>(blockSize);
084        long last = getStore().addAndGet(getKey(key), blockSize);
085        for (int i = blockSize - 1; i >= 0; i--) {
086            ret.add(last - i);
087        }
088        return ret;
089    }
090}