Commit | Line | Data |
---|---|---|
a52fde77 | 1 | /******************************************************************************* |
60ae41e1 | 2 | * Copyright (c) 2012, 2014 Ericsson |
a52fde77 AM |
3 | * Copyright (c) 2010, 2011 École Polytechnique de Montréal |
4 | * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> | |
5df842b3 | 5 | * |
a52fde77 AM |
6 | * All rights reserved. This program and the accompanying materials are |
7 | * made available under the terms of the Eclipse Public License v1.0 which | |
8 | * accompanies this distribution, and is available at | |
9 | * http://www.eclipse.org/legal/epl-v10.html | |
5df842b3 | 10 | * |
a52fde77 AM |
11 | ******************************************************************************/ |
12 | ||
bcec0116 | 13 | package org.eclipse.linuxtools.statesystem.core.statevalue; |
a52fde77 | 14 | |
77c2c2c9 | 15 | import org.eclipse.jdt.annotation.Nullable; |
3cf9b392 | 16 | import org.eclipse.linuxtools.internal.statesystem.core.Activator; |
bcec0116 | 17 | import org.eclipse.linuxtools.statesystem.core.exceptions.StateValueTypeException; |
6d08acca | 18 | |
a52fde77 AM |
19 | /** |
20 | * This is the wrapper class that exposes the different types of 'state values' | |
21 | * available to use in the State System. | |
5df842b3 | 22 | * |
a52fde77 AM |
23 | * This also defines how these values are to be stored in the History Tree. For |
24 | * example, we can save numerical values as integers instead of arrays of | |
25 | * 1-digit characters. | |
5df842b3 | 26 | * |
ec5fec10 | 27 | * The available types are Int, Long, Double and String. |
5df842b3 | 28 | * |
2cb26548 | 29 | * @author Alexandre Montplaisir |
bcec0116 | 30 | * @since 3.0 |
a52fde77 AM |
31 | */ |
32 | public abstract class TmfStateValue implements ITmfStateValue { | |
44b69c99 EB |
33 | |
34 | // ------------------------------------------------------------------------ | |
35 | // State value caches (sizes must be powers of 2) | |
36 | // ------------------------------------------------------------------------ | |
37 | ||
38 | private static final int INT_CACHE_SIZE = 128; | |
39 | private static final int LONG_CACHE_SIZE = 128; | |
40 | private static final int DOUBLE_CACHE_SIZE = 128; | |
41 | ||
42 | private static final IntegerStateValue intCache[] = new IntegerStateValue[INT_CACHE_SIZE]; | |
43 | private static final LongStateValue longCache[] = new LongStateValue[LONG_CACHE_SIZE]; | |
44 | private static final DoubleStateValue doubleCache[] = new DoubleStateValue[DOUBLE_CACHE_SIZE]; | |
45 | ||
a9cdbafc AM |
46 | // ------------------------------------------------------------------------ |
47 | // Factory methods to instantiate new state values | |
48 | // ------------------------------------------------------------------------ | |
49 | ||
a52fde77 AM |
50 | /* |
51 | * Since all "null state values" are the same, we only need one copy in | |
52 | * memory. | |
53 | */ | |
54 | private static TmfStateValue nullValue = new NullStateValue(); | |
55 | ||
56 | /** | |
57 | * Return an instance of a "null" value. Only one copy exists in memory. | |
5df842b3 | 58 | * |
a52fde77 AM |
59 | * @return A null value |
60 | */ | |
cb42195c | 61 | public static final TmfStateValue nullValue() { |
a52fde77 AM |
62 | return nullValue; |
63 | } | |
64 | ||
65 | /** | |
66 | * Factory constructor for Integer state values | |
5df842b3 | 67 | * |
a9cdbafc AM |
68 | * @param intValue |
69 | * The integer value to contain | |
a52fde77 AM |
70 | * @return The newly-created TmfStateValue object |
71 | */ | |
72 | public static TmfStateValue newValueInt(int intValue) { | |
44b69c99 EB |
73 | /* Lookup in cache for the existence of the same value. */ |
74 | int offset = intValue & (INT_CACHE_SIZE - 1); | |
75 | IntegerStateValue cached = intCache[offset]; | |
76 | if (cached != null && cached.unboxInt() == intValue) { | |
77 | return cached; | |
78 | } | |
79 | ||
80 | /* Not in cache, create a new value and cache it. */ | |
81 | IntegerStateValue newValue = new IntegerStateValue(intValue); | |
82 | intCache[offset] = newValue; | |
83 | return newValue; | |
a52fde77 AM |
84 | } |
85 | ||
86 | /** | |
a9cdbafc | 87 | * Factory constructor for Long state values |
5df842b3 | 88 | * |
a9cdbafc AM |
89 | * @param longValue |
90 | * The long value to contain | |
91 | * @return The newly-created TmfStateValue object | |
92 | * @since 2.0 | |
a52fde77 | 93 | */ |
a9cdbafc | 94 | public static TmfStateValue newValueLong(long longValue) { |
44b69c99 EB |
95 | /* Lookup in cache for the existence of the same value. */ |
96 | int offset = (int) longValue & (LONG_CACHE_SIZE - 1); | |
97 | LongStateValue cached = longCache[offset]; | |
98 | if (cached != null && cached.unboxLong() == longValue) { | |
99 | return cached; | |
100 | } | |
101 | ||
102 | /* Not in cache, create a new value and cache it. */ | |
103 | LongStateValue newValue = new LongStateValue(longValue); | |
104 | longCache[offset] = newValue; | |
105 | return newValue; | |
a52fde77 AM |
106 | } |
107 | ||
a3c22e8e AM |
108 | /** |
109 | * Factory constructor for Double state values | |
110 | * | |
111 | * @param value | |
112 | * The double value to contain | |
113 | * @return The newly-created TmfStateValue object | |
c4767854 | 114 | * @since 3.0 |
a3c22e8e AM |
115 | */ |
116 | public static TmfStateValue newValueDouble(double value) { | |
44b69c99 EB |
117 | /* Lookup in cache for the existence of the same value. */ |
118 | int offset = (int) Double.doubleToLongBits(value) & (DOUBLE_CACHE_SIZE - 1); | |
119 | DoubleStateValue cached = doubleCache[offset]; | |
120 | ||
121 | /* | |
122 | * We're using Double.compare() instead of .equals(), because .compare() | |
123 | * works when both values are Double.NaN. | |
124 | */ | |
125 | if (cached != null && Double.compare(cached.unboxDouble(), value) == 0) { | |
126 | return cached; | |
127 | } | |
128 | ||
129 | /* Not in cache, create a new value and cache it. */ | |
130 | DoubleStateValue newValue = new DoubleStateValue(value); | |
131 | doubleCache[offset] = newValue; | |
132 | return newValue; | |
a3c22e8e AM |
133 | } |
134 | ||
1cbf1a19 | 135 | /** |
a9cdbafc | 136 | * Factory constructor for String state values |
1cbf1a19 | 137 | * |
a9cdbafc AM |
138 | * @param strValue |
139 | * The string value to contain | |
140 | * @return The newly-created TmfStateValue object | |
1cbf1a19 | 141 | */ |
77c2c2c9 | 142 | public static TmfStateValue newValueString(@Nullable String strValue) { |
a9cdbafc | 143 | if (strValue == null) { |
1cbf1a19 FR |
144 | return nullValue(); |
145 | } | |
3cf9b392 AM |
146 | /* |
147 | * Make sure the String does not contain "weird" things, like ISO | |
148 | * control characters. | |
149 | */ | |
150 | for (char c : strValue.toCharArray()) { | |
151 | if (Character.isISOControl(c)) { | |
152 | Activator.getDefault().logError("Trying to use invalid string: " + strValue); //$NON-NLS-1$ | |
153 | throw new IllegalArgumentException(); | |
154 | } | |
155 | } | |
a9cdbafc | 156 | return new StringStateValue(strValue); |
1cbf1a19 FR |
157 | } |
158 | ||
a9cdbafc AM |
159 | // ------------------------------------------------------------------------ |
160 | // Default unboxing methods. | |
161 | // Subclasses can override those for the types they support. | |
162 | // ------------------------------------------------------------------------ | |
a52fde77 | 163 | |
a9cdbafc AM |
164 | private String unboxErrMsg(String targetType) { |
165 | return "Type " + getClass().getSimpleName() + //$NON-NLS-1$ | |
ec5fec10 | 166 | " cannot be unboxed into a " + targetType + " value."; //$NON-NLS-1$ //$NON-NLS-2$ |
a52fde77 AM |
167 | } |
168 | ||
169 | @Override | |
6dd46830 | 170 | public int unboxInt() { |
a9cdbafc | 171 | throw new StateValueTypeException(unboxErrMsg("Int")); //$NON-NLS-1$ |
a52fde77 | 172 | } |
1cbf1a19 | 173 | |
1cbf1a19 | 174 | @Override |
6dd46830 | 175 | public long unboxLong() { |
a9cdbafc AM |
176 | throw new StateValueTypeException(unboxErrMsg("Long")); //$NON-NLS-1$ |
177 | } | |
1cbf1a19 | 178 | |
c4767854 AM |
179 | /** |
180 | * @since 3.0 | |
181 | */ | |
a3c22e8e | 182 | @Override |
6dd46830 | 183 | public double unboxDouble() { |
a3c22e8e AM |
184 | throw new StateValueTypeException(unboxErrMsg("Double")); //$NON-NLS-1$ |
185 | } | |
186 | ||
a9cdbafc | 187 | @Override |
6dd46830 | 188 | public String unboxStr() { |
a9cdbafc | 189 | throw new StateValueTypeException(unboxErrMsg("String")); //$NON-NLS-1$ |
1cbf1a19 | 190 | } |
a52fde77 | 191 | } |