1 /*
2 Copyright 2007 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.model.container;
17
18 import fulmine.IType;
19 import fulmine.context.IFrameworkContext;
20 import fulmine.event.IEvent;
21 import fulmine.event.IEventFrame;
22 import fulmine.event.listener.IEventListener;
23 import fulmine.model.component.IComponent;
24 import fulmine.model.container.IContainerFactory.IContainerBuilder;
25 import fulmine.model.container.subscription.remote.IRemoteSubscribable;
26 import fulmine.model.field.BooleanField;
27 import fulmine.model.field.DoubleField;
28 import fulmine.model.field.FloatField;
29 import fulmine.model.field.IField;
30 import fulmine.model.field.IntegerField;
31 import fulmine.model.field.LongField;
32 import fulmine.model.field.StringField;
33 import fulmine.model.field.containerdefinition.IContainerDefinitionField;
34
35 /**
36 * A container represents an entity with multiple properties. The properties
37 * make up the state of the entity. The properties are represented by
38 * {@link IField} objects. The {@link IField} implementations are for scalar
39 * primitive types only. Each property is addressed by its identity (a string).
40 * Non-scalar properties can be simulated by using identities with suitable
41 * namespacing.
42 * <p>
43 * As each field changes, it notifies its container with the {@link IEvent} that
44 * encapsulates the change. These events are marshaled into an event frame by
45 * the container.
46 * <p>
47 * A container may be static or dynamic; static container types have an
48 * immutable {@link IField} population. The definition of the fields is held in
49 * a {@link IContainerDefinitionField} that will be keyed against the
50 * container's type. If the field definition changes for the container type, it
51 * must be changed in <b>all</b> contexts. If not, then the container type will
52 * not be read correctly by receiving contexts that have an incorrect static
53 * definition for the type.
54 * <p>
55 * Dynamic containers have a variable (mutable) population with no constraints
56 * of the container's type.
57 *
58 * @see IComponent
59 * @see IContainerDefinitionField
60 * @see IContainerBuilder
61 * @author Ramon Servadei
62 *
63 */
64 public interface IContainer extends IComponent, IEventFrame,
65 IRemoteSubscribable
66 {
67 /**
68 * The enumeration of data states for an {@link IContainer}.
69 * <p>
70 * There are 2 data states
71 * <ul>
72 * <li>LIVE - in this state, the data of the container is being updated (in
73 * real-time) and can be considered trustworthy.
74 * <li>STALE - in this state, the data of the container is not being updated
75 * and should be considered untrustable.
76 * </ul>
77 * A container is automatically 'live' when it is created and automatically
78 * 'stale' when it is destroyed. Application logic may also change the data
79 * state.
80 * <p>
81 * The data state is orthogonal to the life-cycle state of the container.
82 *
83 * @author Ramon Servadei
84 */
85 public enum DataState
86 {
87 /**
88 * Enumerates the live data state. The data in the container is
89 * up-to-date and trustworthy.
90 *
91 * @see IContainer#getDataState
92 */
93 LIVE,
94
95 /**
96 * Enumerates the stale data state. The data in the container is not
97 * being updated and is not trustworthy.
98 *
99 * @see IContainer#getDataState
100 */
101 STALE, ;
102
103 /**
104 * Find the enum from its ordinal
105 *
106 * @param ordinal
107 * the ordinal
108 * @return the enum for the ordinal
109 * @throws IllegalArgumentException
110 * if the ordinal does not match
111 */
112 public static DataState fromOrdinal(int ordinal)
113 {
114 final DataState[] values = values();
115 for (DataState dataState : values)
116 {
117 if (dataState.ordinal() == ordinal)
118 {
119 return dataState;
120 }
121 }
122 throw new IllegalArgumentException("Unknown ordinal: " + ordinal);
123 }
124 }
125
126 /**
127 * Add the field to this container. Any {@link IEvent} events raised by the
128 * field will reach this container via its {@link IEventFrame} interface.
129 *
130 * @param field
131 * the field to add to this container.
132 */
133 void add(IField field);
134
135 /**
136 * Remove the field from this container. Any events raised by the field will
137 * no longer reach this container.
138 *
139 * @param field
140 * the field to remove from this container.
141 * @return the removed field
142 */
143 <T extends IField> T remove(T field);
144
145 /**
146 * Find the field in the container with the identity equal to the string
147 * argument.
148 *
149 * @param identity
150 * the string identity of the field to find
151 * @return the field in the container with the same identity or
152 * <code>null</code> if not found.
153 */
154 <T extends IField> T get(String identity);
155
156 /**
157 * Get all the identities of the fields in this container.
158 *
159 * @return an array of the string identities of all the {@link IField}
160 * objects in this container.
161 */
162 String[] getComponentIdentities();
163
164 /**
165 * A life-cycle method of a container to initialise all resources. Failure
166 * to call this method results in a container with an unusable state.
167 * Implementations may throw a {@link RuntimeException} if a container is
168 * accessed without being initialised.
169 * <p>
170 * The proper way to retrieve a container is via the
171 * {@link ContainerFactory#createContainer(String, int)}. This will
172 * automatically invoke this method.
173 * <p>
174 * Idempotent operation.
175 *
176 * @see #destroy()
177 */
178 void start();
179
180 /**
181 * This is a life-cycle method of a container to release all resources and
182 * perform cleaning up prior to being made redundant.
183 * <p>
184 * Idempotent operation.
185 *
186 * @see #start()
187 */
188 void destroy();
189
190 /**
191 * Set the container state. The state is a logical business state and is not
192 * connected to the object lifecycle state. The business state indicates if
193 * the data is trustworthy.
194 *
195 * @param dataState
196 * the new business state.
197 * @see DataState for a description of the states.
198 */
199 void setState(DataState dataState);
200
201 /**
202 * Determine the number of {@link IField} instances held in this container
203 *
204 * @return the number of {@link IField} instances held in this container
205 */
206 int size();
207
208 /**
209 * Get the container's data state. This represents the if the data is being
210 * updated and is trustworthy.
211 *
212 * @return the current data state
213 * @see DataState DataState for a description of the states.
214 */
215 DataState getDataState();
216
217 /**
218 * Get the type of the container. A container type represents a family of
219 * related container instances. This is synonymous with a class in an object
220 * oriented language.
221 *
222 * @return a byte describing the type of container.
223 */
224 IType getType();
225
226 /**
227 * Determines if this container empty.
228 *
229 * @return <code>true</code> if there are no fields in this container.
230 */
231 boolean isEmpty();
232
233 /**
234 * Determines if there is an {@link IField} instance with an identity equal
235 * to the key argument.
236 *
237 * @param key
238 * the identity of a field to find in this container.
239 * @return <code>true</code> if there is an {@link IField} with this
240 * identity held in this.
241 */
242 boolean contains(String key);
243
244 /**
245 * Identify if the container is dynamic or static. Static container types
246 * have an immutable {@link IField} population. Dynamic containers have a
247 * variable (mutable) population.
248 *
249 * @return <code>true</code> if the definition is dynamic
250 */
251 boolean isDynamic();
252
253 /**
254 * Is the container local to the host context returned by
255 * {@link #getContext()}
256 *
257 * @return <code>true</code> if the container is local
258 */
259 boolean isLocal();
260
261 /**
262 * Get the host context for the container instance. This may not be the
263 * native context for the container.
264 *
265 * @see #isLocal()
266 * @see #getNativeContextIdentity()
267 * @return the {@link IFrameworkContext} hosting this instance
268 */
269 IFrameworkContext getContext();
270
271 /**
272 * Get the {@link BooleanField} identified by the identity
273 *
274 * @param identity
275 * the identity of the field to get
276 * @return the {@link BooleanField} for the identity, <code>null</code> if
277 * not found
278 * @throws ClassCastException
279 * if the field is not of this type
280 */
281 public BooleanField getBooleanField(String identity);
282
283 /**
284 * Get the {@link StringField} identified by the identity
285 *
286 * @param identity
287 * the identity of the field to get
288 * @return the {@link StringField} for the identity, <code>null</code> if
289 * not found
290 * @throws ClassCastException
291 * if the field is not of this type
292 */
293 public StringField getStringField(String identity);
294
295 /**
296 * Get the {@link IntegerField} identified by the identity
297 *
298 * @param identity
299 * the identity of the field to get
300 * @return the {@link IntegerField} for the identity, <code>null</code> if
301 * not found
302 * @throws ClassCastException
303 * if the field is not of this type
304 */
305 public IntegerField getIntegerField(String identity);
306
307 /**
308 * Get the {@link LongField} identified by the identity
309 *
310 * @param identity
311 * the identity of the field to get
312 * @return the {@link LongField} for the identity, <code>null</code> if not
313 * found
314 * @throws ClassCastException
315 * if the field is not of this type
316 */
317 public LongField getLongField(String identity);
318
319 /**
320 * Get the {@link FloatField} identified by the identity
321 *
322 * @param identity
323 * the identity of the field to get
324 * @return the {@link FloatField} for the identity, <code>null</code> if not
325 * found
326 * @throws ClassCastException
327 * if the field is not of this type
328 */
329 public FloatField getFloatField(String identity);
330
331 /**
332 * Get the {@link DoubleField} identified by the identity
333 *
334 * @param identity
335 * the identity of the field to get
336 * @return the {@link DoubleField} for the identity, <code>null</code> if
337 * not found
338 * @throws ClassCastException
339 * if the field is not of this type
340 */
341 public DoubleField getDoubleField(String identity);
342
343 /**
344 * Get the identity of the context this container is native to; this is its
345 * local context identity. If this container is local to the host context,
346 * this is the same as the identity of {@link #getContext()}. If this
347 * container is a remote container, this will return the remote context
348 * identity.
349 * <p>
350 * Note: this is more for informational purposes, the true mechanism for
351 * determining whether a container is local to the host context or not is by
352 * checking {@link #isLocal()}.
353 *
354 * @see #isLocal()
355 * @see #getContext()
356 * @return the identity of this container's local context
357 */
358 String getNativeContextIdentity();
359
360 /**
361 * Determine if this instance is the original or a clone. Any
362 * {@link IEventListener} instances processing {@link IContainer} instances
363 * as {@link IEvent} instances will receive the container instance as a
364 * <b>clone</b>. In this way, the container changes are broadcast as a
365 * logically immutable instance.
366 *
367 * @return <code>true</code> if this is a clone of the original
368 */
369 boolean isClone();
370 }