OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 149 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
73 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;
15
 
180 ilm 16
import org.openconcerto.utils.cc.I2ExnFactory;
17
 
73 ilm 18
import java.util.Map;
180 ilm 19
import java.util.function.Supplier;
73 ilm 20
 
21
/**
22
 * Null can be ambiguous, e.g. {@link Map#get(Object)}. This class allows to avoid the problem.
23
 *
24
 * @author Sylvain
25
 * @param <V> type of value.
26
 */
27
public abstract class Value<V> {
28
 
29
    @SuppressWarnings("rawtypes")
30
    static private final Value NONE = new Value(false) {
31
        @Override
32
        public Object getValue() {
83 ilm 33
            throw new IllegalStateException(this.toString());
73 ilm 34
        }
83 ilm 35
 
36
        @Override
37
        public String toString() {
38
            return "No Value";
39
        }
73 ilm 40
    };
41
 
42
    /**
43
     * I.e. {@link Map#containsKey(Object)} is <code>false</code>.
44
     *
45
     * @return the no value instance, i.e. {@link Value#hasValue()} <code>false</code>.
46
     */
47
    @SuppressWarnings("unchecked")
48
    public static <V> Value<V> getNone() {
49
        return NONE;
50
    }
51
 
144 ilm 52
    @SuppressWarnings("rawtypes")
53
    static private final Value NULL_VALUE = new Value.Some<>(null);
54
 
55
    /**
56
     * Return an instance with a <code>null</code> value.
57
     *
58
     * @return the <code>null</code> {@link #getValue() value} instance, i.e.
59
     *         {@link Value#hasValue()} <code>true</code>.
60
     */
61
    @SuppressWarnings("unchecked")
62
    public static <V> Value<V> getNullValue() {
63
        return NULL_VALUE;
64
    }
65
 
73 ilm 66
    static private final class Some<V> extends Value<V> {
67
 
68
        private final V val;
69
 
70
        public Some(final V val) {
71
            super(true);
72
            this.val = val;
73
        }
74
 
75
        @Override
76
        public V getValue() {
77
            return this.val;
78
        }
83 ilm 79
 
80
        @Override
81
        public String toString() {
82
            return "Value <" + this.getValue() + '>';
83
        }
132 ilm 84
 
85
        @Override
86
        public int hashCode() {
87
            final int prime = 31;
88
            int result = super.hashCode();
89
            result = prime * result + ((this.val == null) ? 0 : this.val.hashCode());
90
            return result;
91
        }
92
 
93
        @Override
94
        public boolean equals(Object obj) {
95
            if (this == obj)
96
                return true;
97
            if (!super.equals(obj))
98
                return false;
99
            final Some<?> other = (Some<?>) obj;
100
            return CompareUtils.equals(this.val, other.val);
101
        }
73 ilm 102
    };
103
 
104
    /**
105
     * I.e. {@link Map#containsKey(Object)} is <code>true</code>.
106
     *
107
     * @param value e.g. the value contained in the Map, possibly <code>null</code>.
108
     * @return a instance with {@link #hasValue()} <code>true</code>.
109
     */
110
    public static <V> Value<V> getSome(final V value) {
144 ilm 111
        // less memory
112
        return value == null ? Value.<V> getNullValue() : new Value.Some<V>(value);
73 ilm 113
    }
114
 
132 ilm 115
    public static final boolean hasValue(final Value<?> v) {
116
        return v != null && v.hasValue();
117
    }
118
 
73 ilm 119
    /**
120
     * Usefull if <code>null</code> value actually means none, i.e. the map cannot contain
121
     * <code>null</code>.
122
     *
123
     * @param value the value.
124
     * @return {@link #getNone()} if <code>value</code> is <code>null</code>,
125
     *         {@link #getSome(Object)} otherwise.
126
     */
127
    public static <V> Value<V> fromNonNull(final V value) {
128
        return value == null ? Value.<V> getNone() : getSome(value);
129
    }
130
 
131
    private final boolean hasValue;
132
 
133
    private Value(boolean hasValue) {
134
        super();
135
        this.hasValue = hasValue;
136
    }
137
 
138
    public final boolean hasValue() {
139
        return this.hasValue;
140
    }
141
 
93 ilm 142
    /**
143
     * Return our value if any.
144
     *
145
     * @return our value if this {@link #hasValue()}, can be <code>null</code>.
146
     * @throws IllegalStateException if not {@link #hasValue()}.
147
     */
148
    public abstract V getValue() throws IllegalStateException;
149
 
150
    /**
149 ilm 151
     * Return the value if {@link #hasValue()}, otherwise the passed one, never throws an exception.
152
     *
153
     * @param def the default value.
154
     * @return either {@link #getValue()} or <code>def</code>.
155
     */
156
    public final V getValue(final V def) {
157
        if (this.hasValue())
158
            return this.getValue();
159
        else
160
            return def;
161
    }
162
 
180 ilm 163
    public final Value<V> asSome(final V def) {
164
        if (this.hasValue())
165
            return this;
166
        else
167
            return getSome(def);
168
    }
169
 
170
    // Same method names as Optional
171
 
172
    public final V orElse(final V def) {
173
        return this.getValue(def);
174
    }
175
 
176
    public final V orGet(final Supplier<? extends V> def) {
177
        if (this.hasValue())
178
            return this.getValue();
179
        else
180
            return def.get();
181
    }
182
 
183
    public final <X extends Exception, X2 extends Exception> V orThrowingGet(final I2ExnFactory<? extends V, X, X2> def) throws X, X2 {
184
        if (this.hasValue())
185
            return this.getValue();
186
        else
187
            return def.createChecked();
188
    }
189
 
149 ilm 190
    /**
93 ilm 191
     * Return <code>null</code> if and only if this has no value.
192
     *
193
     * @return non <code>null</code> {@link #getValue()} if {@link #hasValue()}, otherwise
194
     *         <code>null</code>.
195
     * @throws IllegalStateException if {@link #getValue()} is <code>null</code>.
196
     * @see #fromNonNull(Object)
197
     */
198
    public final V toNonNull() throws IllegalStateException {
199
        if (!this.hasValue())
200
            return null;
201
        final V res = this.getValue();
202
        if (res == null)
203
            throw new IllegalStateException("Null value");
204
        return res;
205
    }
132 ilm 206
 
144 ilm 207
    @SuppressWarnings("unchecked")
208
    public final <T> Value<T> cast(final Class<T> clazz) {
209
        if (this.hasValue())
210
            clazz.cast(this.getValue());
211
        return (Value<T>) this;
212
    }
213
 
132 ilm 214
    @Override
215
    public int hashCode() {
216
        return this.hasValue ? 1231 : 1237;
217
    }
218
 
219
    @Override
220
    public boolean equals(Object obj) {
221
        if (this == obj)
222
            return true;
223
        if (obj == null)
224
            return false;
225
        if (getClass() != obj.getClass())
226
            return false;
227
        return this.hasValue == ((Value<?>) obj).hasValue;
228
    }
73 ilm 229
}