KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > util > Index


1 /*
2  * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
3  * Copyright (C) 2005 - Javolution (http://javolution.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package javolution.util;
10
11 import j2me.io.ObjectStreamException;
12 import j2me.io.Serializable;
13 import j2mex.realtime.MemoryArea;
14 import javolution.lang.Immutable;
15 import javolution.util.FastCollection.Record;
16 import javolution.xml.XMLFormat;
17 import javolution.xml.stream.XMLStreamException;
18
19 /**
20  * This class represents a unique index object. Instances of this class
21  * are immutable and can be used for direct iteration over random access
22  * collections (e.g. {@link FastTable}) or for specialized <code>int</code>
23  * to <code>Object</code> mapping. For example:[code]
24  * class SparseVector<F> {
25  * FastMap<Index, F> _elements = new FastMap<Index, F>();
26  * ...
27  * }
28  * [/code]
29  * Direct object equality can be used (<code>==</code>) to compare indexes.
30  * Indexes have no adverse effect on the garbage collectors but should only
31  * be used for reasonably small <code>int</code> values.
32  *
33  * <p><b>RTSJ:</b> Instance of this classes are always allocated in
34  * <code>ImmortalMemory</code>.</p>
35  *
36  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
37  * @version 4.2, December 18, 2006
38  */

39 public final class Index implements Record, Immutable, Serializable {
40
41     /**
42      * Holds the index zero (value <code>0</code>).
43      */

44     public static final Index ZERO = new Index(0);
45
46     /**
47      * Holds positive indexes (immortal memory).
48      */

49     private static final FastTable POSITIVE = new FastTable();
50     static {
51         POSITIVE.add(ZERO);
52     }
53
54     /**
55      * Holds negative indexes (immortal memory).
56      */

57     private static final FastTable NEGATIVE = new FastTable();
58     static {
59         NEGATIVE.add(ZERO);
60     }
61
62     /**
63      * Holds the default XML representation for indexes.
64      * This presentation consists of a <code>"value"</code> attribute
65      * holding the index <code>int</code> value.
66      */

67     protected static final XMLFormat/*<Index>*/XML = new XMLFormat(new Index(0)
68             .getClass()) {
69
70         public boolean isReferenceable() {
71             return false; // Always by value (immutable).
72
}
73
74         public Object JavaDoc newInstance(Class JavaDoc cls, InputElement xml)
75                 throws XMLStreamException {
76             return Index.valueOf(xml.getAttribute("value", 0));
77         }
78
79         public void read(InputElement xml, Object JavaDoc obj)
80                 throws XMLStreamException {
81             // Do nothing.
82
}
83
84         public void write(Object JavaDoc obj, OutputElement xml)
85                 throws XMLStreamException {
86             xml.setAttribute("value", ((Index) obj).intValue());
87         }
88     };
89
90     /**
91      * Holds the index position.
92      */

93     private final int _value;
94
95     /**
96      * Holds the next index.
97      */

98     private transient Index _next;
99
100     /**
101      * Holds the previous node.
102      */

103     private transient Index _previous;
104
105     /**
106      * Creates an index at the specified position.
107      *
108      * @param i the index position.
109      */

110     private Index(int i) {
111         _value = i;
112     }
113
114     /**
115      * Returns the unique index for the specified <code>int</code> value
116      * (creating it as well as the indices toward {@link #ZERO zero}
117      * if they do not exist).
118      *
119      * @param i the index value.
120      * @return the corresponding unique index.
121      */

122     public static Index valueOf(int i) {
123         return ((i >= 0) && (i < POSITIVE.size())) ? (Index) POSITIVE.get(i)
124                 : ((i < 0) && (-i < NEGATIVE.size())) ? (Index) NEGATIVE
125                         .get(-i) : createInstance(i);
126     }
127
128     private static synchronized Index createInstance(int value) {
129         if (value >= 0) {
130             while (value >= POSITIVE.size()) {
131                 MemoryArea.getMemoryArea(POSITIVE).executeInArea(
132                         AUGMENT_POSITIVE);
133             }
134             return (Index) POSITIVE.get(value);
135         } else {
136             while (-value >= NEGATIVE.size()) {
137                 MemoryArea.getMemoryArea(NEGATIVE).executeInArea(
138                         AUGMENT_NEGATIVE);
139             }
140             return (Index) NEGATIVE.get(-value);
141         }
142     }
143
144     private static Runnable JavaDoc AUGMENT_POSITIVE = new Runnable JavaDoc() {
145         public void run() {
146             Index prev = (Index) POSITIVE.getLast();
147             for (int i = 0; i < 16; i++) { // 16 at a time.
148
Index index = new Index(prev._value + 1);
149                 index._previous = prev;
150                 prev._next = index;
151                 POSITIVE.add(index);
152                 prev = index;
153             }
154         }
155     };
156
157     private static Runnable JavaDoc AUGMENT_NEGATIVE = new Runnable JavaDoc() {
158         public void run() {
159             Index next = (Index) NEGATIVE.getLast();
160             for (int i = 0; i < 16; i++) { // 16 at a time.
161
Index index = new Index(next._value - 1);
162                 index._next = next;
163                 next._previous = index;
164                 NEGATIVE.add(index);
165                 next = index;
166             }
167         }
168     };
169
170     /**
171      * Returns the index value.
172      *
173      * @return the index value.
174      */

175     public final int intValue() {
176         return _value;
177     }
178
179     /**
180      * Returns the <code>String</code> representation of this index.
181      *
182      * @return this index value formatted as a string.
183      */

184     public final String JavaDoc toString() {
185         return String.valueOf(_value);
186     }
187
188     /**
189      * Indicates if this index is equals to the one specified (unicity
190      * ensures that this method is equivalent to <code>==</code>).
191      *
192      * @return <code>this == obj</code>
193      */

194     public final boolean equals(Object JavaDoc obj) {
195         return this == obj;
196     }
197
198     /**
199      * Returns the hash code for this index.
200      *
201      * @return the index value.
202      */

203     public final int hashCode() {
204         return _value;
205     }
206
207     /**
208      * Ensures index unicity during deserialization.
209      *
210      * @return the unique instance for this deserialized index.
211      */

212     protected final Object JavaDoc readResolve() throws ObjectStreamException {
213         return valueOf(_value);
214     }
215
216     // Implements Record interface.
217
public final Record getNext() {
218         return _next;
219     }
220
221     // Implements Record interface.
222
public final Record getPrevious() {
223         return _previous;
224     }
225
226     private static final long serialVersionUID = 1L;
227 }
Popular Tags