OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
177 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.utils.i18n;
15
 
16
import java.util.Collection;
17
import java.util.HashMap;
18
import java.util.Locale;
19
import java.util.Map;
20
import java.util.Objects;
21
import java.util.function.Function;
22
 
23
import net.jcip.annotations.ThreadSafe;
24
 
25
@ThreadSafe
26
public class TranslationPool<T, X extends Exception> {
27
 
28
    static public enum Mode {
29
        /**
30
         * Try to create if needed, but allow <code>null</code>.
31
         */
32
        OPTIONAL_CREATE(true, true),
33
        /**
34
         * Try to create if needed, but disallow <code>null</code>.
35
         */
36
        GET_OR_CREATE(true, false),
37
        /**
38
         * The item must already exist.
39
         */
40
        GET_CREATED(false, false);
41
 
42
        private final boolean allowCreation, allowNull;
43
 
44
        private Mode(boolean allowCreation, boolean allowNull) {
45
            this.allowCreation = allowCreation;
46
            this.allowNull = allowNull;
47
        }
48
    }
49
 
50
    // it's rare to load many Locale
51
    private final Map<Locale, T> byLocale = new HashMap<>(8);
52
    private final Function<Locale, T> createInstance;
53
 
54
    public TranslationPool() {
55
        this(null);
56
    }
57
 
58
    public TranslationPool(final Function<Locale, T> createInstance) {
59
        this.createInstance = createInstance;
60
    }
61
 
62
    protected T createTM(final Locale l) throws X {
63
        return this.createInstance.apply(l);
64
    }
65
 
66
    public final T get(final Locale l) throws X {
67
        return this.get(l, Mode.GET_OR_CREATE);
68
    }
69
 
70
    public final T get(final Locale l, final Mode mode) throws X {
71
        Objects.requireNonNull(l, "Missing locale");
72
        Objects.requireNonNull(mode, "Missing mode");
73
        T res;
74
        synchronized (this) {
75
            res = this.byLocale.get(l);
76
            if (res == null && mode.allowCreation) {
77
                res = this.createTM(l);
78
                if (res != null)
79
                    this.byLocale.put(l, res);
80
            }
81
            if (res == null && !mode.allowNull)
82
                throw new IllegalStateException("Missing instance for " + l);
83
        }
84
        return res;
85
    }
86
 
87
    public final T getCreated(final Locale l) {
88
        // Don't call get(Locale, Mode) since it throws a generic exception that can't be caught
89
        Objects.requireNonNull(l, "Missing locale");
90
        synchronized (this) {
91
            final T res = this.byLocale.get(l);
92
            if (res == null)
93
                throw new IllegalStateException("Missing instance for " + l);
94
            return res;
95
        }
96
    }
97
 
98
    final Collection<T> getCreated() {
99
        assert Thread.holdsLock(this);
100
        return this.byLocale.values();
101
    }
102
}