1 /*******************************************************************************
2 * Copyright (c) 2012, 2014 Ericsson
3 * Copyright (c) 2010, 2011 École Polytechnique de Montréal
4 * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
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
11 ******************************************************************************/
13 package org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
;
15 import org
.eclipse
.jdt
.annotation
.Nullable
;
16 import org
.eclipse
.linuxtools
.internal
.statesystem
.core
.Activator
;
17 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.StateValueTypeException
;
20 * This is the wrapper class that exposes the different types of 'state values'
21 * available to use in the State System.
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
27 * The available types are Int, Long, Double and String.
29 * @author Alexandre Montplaisir
32 public abstract class TmfStateValue
implements ITmfStateValue
{
34 // ------------------------------------------------------------------------
35 // State value caches (sizes must be powers of 2)
36 // ------------------------------------------------------------------------
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;
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
];
46 // ------------------------------------------------------------------------
47 // Factory methods to instantiate new state values
48 // ------------------------------------------------------------------------
51 * Since all "null state values" are the same, we only need one copy in
54 private static TmfStateValue nullValue
= new NullStateValue();
57 * Return an instance of a "null" value. Only one copy exists in memory.
59 * @return A null value
61 public static final TmfStateValue
nullValue() {
66 * Factory constructor for Integer state values
69 * The integer value to contain
70 * @return The newly-created TmfStateValue object
72 public static TmfStateValue
newValueInt(int intValue
) {
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
) {
80 /* Not in cache, create a new value and cache it. */
81 IntegerStateValue newValue
= new IntegerStateValue(intValue
);
82 intCache
[offset
] = newValue
;
87 * Factory constructor for Long state values
90 * The long value to contain
91 * @return The newly-created TmfStateValue object
94 public static TmfStateValue
newValueLong(long longValue
) {
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
) {
102 /* Not in cache, create a new value and cache it. */
103 LongStateValue newValue
= new LongStateValue(longValue
);
104 longCache
[offset
] = newValue
;
109 * Factory constructor for Double state values
112 * The double value to contain
113 * @return The newly-created TmfStateValue object
116 public static TmfStateValue
newValueDouble(double value
) {
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
];
122 * We're using Double.compare() instead of .equals(), because .compare()
123 * works when both values are Double.NaN.
125 if (cached
!= null && Double
.compare(cached
.unboxDouble(), value
) == 0) {
129 /* Not in cache, create a new value and cache it. */
130 DoubleStateValue newValue
= new DoubleStateValue(value
);
131 doubleCache
[offset
] = newValue
;
136 * Factory constructor for String state values
139 * The string value to contain
140 * @return The newly-created TmfStateValue object
142 public static TmfStateValue
newValueString(@Nullable String strValue
) {
143 if (strValue
== null) {
147 * Make sure the String does not contain "weird" things, like ISO
148 * control characters.
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();
156 return new StringStateValue(strValue
);
159 // ------------------------------------------------------------------------
160 // Default unboxing methods.
161 // Subclasses can override those for the types they support.
162 // ------------------------------------------------------------------------
164 private String
unboxErrMsg(String targetType
) {
165 return "Type " + getClass().getSimpleName() + //$NON-NLS-1$
166 " cannot be unboxed into a " + targetType
+ " value."; //$NON-NLS-1$ //$NON-NLS-2$
170 public int unboxInt() {
171 throw new StateValueTypeException(unboxErrMsg("Int")); //$NON-NLS-1$
175 public long unboxLong() {
176 throw new StateValueTypeException(unboxErrMsg("Long")); //$NON-NLS-1$
183 public double unboxDouble() {
184 throw new StateValueTypeException(unboxErrMsg("Double")); //$NON-NLS-1$
188 public String
unboxStr() {
189 throw new StateValueTypeException(unboxErrMsg("String")); //$NON-NLS-1$