1 /*
2 Copyright 2008 Ramon Servadei
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16 package fulmine;
17
18 import static fulmine.util.Utils.string;
19 import fulmine.model.field.containerdefinition.ContainerDefinitionField;
20 import fulmine.util.reference.AutoCreatingStore;
21 import fulmine.util.reference.IAutoCreatingStore;
22 import fulmine.util.reference.IObjectBuilder;
23 import fulmine.util.reference.is;
24
25 /**
26 * A standard {@link IType} implementation backed by an
27 * {@link IAutoCreatingStore} that returns canonical {@link IType} instances.
28 * <p>
29 * The standard types for the framework are defined and accessible as static
30 * member variables (e.g. {@link #LONG_FIELD}).
31 * <p>
32 * Use the {@link Type#get(byte)} factory method to obtain an instance. Any user
33 * defined types must start from {@link #BASE_USER_START}.
34 *
35 * @author Ramon Servadei
36 */
37 public final class Type implements IType
38 {
39 /**
40 * The builder for {@link Type} instances.
41 *
42 * @author Ramon Servadei
43 */
44 private static final class TypeBuilder implements
45 IObjectBuilder<Byte, Type>
46 {
47 public Type create(Byte key)
48 {
49 return new Type(key.byteValue());
50 }
51 }
52
53 /** The store of type instances against type code */
54 private final static IAutoCreatingStore<Byte, Type> store =
55 new AutoCreatingStore<Byte, Type>(new TypeBuilder());
56
57 /**
58 * Factory method to obtain a sharable, immutable {@link Type} instance.
59 *
60 * @param code
61 * the code for the type (a byte)
62 * @param name
63 * the name for the type, <b>optional</b>. This is only set on
64 * the first call for each code. If no name is supplied on the
65 * first call, the type will have no name, irrespective of
66 * subsequent calls.
67 * @return a sharable, immutable {@link IType} instance representing the
68 * code.
69 */
70 public static final IType get(int code, String... name)
71 {
72 final Byte byteCode = Byte.valueOf((byte) code);
73 if (store.containsKey(byteCode))
74 {
75 return store.get(byteCode);
76 }
77 final Type type = store.get(byteCode);
78 if (name.length == 1)
79 {
80 type.setName(name[0]);
81 }
82 return type;
83 }
84
85 /** The code for the type */
86 private final byte code;
87
88 /** The name for the domain */
89 private String name;
90
91 /** Represents an unspecified type */
92 public static final IType UNSPECIFIED_TYPE = get(-2, "Unspecfied");
93
94 /** Represents a 'removed' type */
95 public static final IType REMOVED = get(-1, "Removed");
96
97 /** The type value for a system level component. */
98 public static final IType SYSTEM = get(0, "System");
99
100 /**
101 * The type value for a container definition component. This is also the
102 * wire-code for the {@link ContainerDefinitionField}.
103 */
104 public static final// DO NOT CHANGE THE VALUE OF THIS
105 IType CONTAINER_DEFINITION = get(1, "ContainerDefinition");
106
107 /** The type value for a boolean component. */
108 public static final IType BOOLEAN_FIELD = get(3, "BooleanField");
109
110 /** The type value for an integer component. */
111 public static final IType INTEGER_FIELD = get(4, "IntegerField");
112
113 /** The type value for a long component. */
114 public static final IType LONG_FIELD = get(5, "LongField");
115
116 /** The type value for a float component. */
117 public static final IType FLOAT_FIELD = get(6, "FloatField");
118
119 /** The type value for a double component. */
120 public static final IType DOUBLE_FIELD = get(7, "DoubleField");
121
122 /** The type value for a string component. */
123 public static final IType STRING_FIELD = get(8, "StringField");
124
125 /** The type value for a descriptor component. */
126 public static final IType DESCRIPTOR_FIELD = get(9, "DescriptorField");
127
128 /** The type value for a record component. */
129 public static final IType RECORD = get(10, "Record");
130
131 /** The starting type value for user defined types. */
132 public static final int BASE_USER_START = RECORD.value() + 1;
133
134 private Type(byte code)
135 {
136 this.code = code;
137 }
138
139 public byte value()
140 {
141 return this.code;
142 }
143
144 public String getName()
145 {
146 return this.name;
147 }
148
149 void setName(String name)
150 {
151 this.name = name;
152 }
153
154 @Override
155 public final String toString()
156 {
157 return string(this, this.code + "," + this.name);
158 }
159
160 @Override
161 public int hashCode()
162 {
163 return this.code;
164 }
165
166 @Override
167 public boolean equals(Object obj)
168 {
169 if (is.same(this, obj))
170 {
171 return true;
172 }
173 if (is.differentClass(this, obj))
174 {
175 return false;
176 }
177 final Type other = (Type) obj;
178 return is.eq(this.code, other.code);
179 }
180
181 }