1   /*
2    *  SimpleSortedSet.java
3    *
4    *  Copyright (c) 2001, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  D.Ognyanoff, 15/Nov/2001
12   *
13   */
14  package gate.util;
15  import java.io.*;
16  import java.util.*;
17  
18  /**
19   * The purpose of this Map is to combine the functionality found in
20   * TreeSet, especially first() and tailSet() with the hashcode driven map
21   * using native long as key to hold the annotations orederd by their offset.
22   * It is used in the SinglePhaseTransducer.transduce()
23   */
24  public class SimpleSortedSet {
25  
26  /**
27   * the Map contianing Lists with the annotations by offset as key
28   */
29      HashMapLong m = new HashMapLong();
30  
31  /**
32   * the initial dimension of the offsets array
33   */
34      static final int INCREMENT = 4;
35  /**
36   * the array containing the distinct offsets in the map
37   * It should be sorted before usinf the first and tailSet methods
38   */
39      long[] theArray = new long[INCREMENT];
40  /**
41   * tailSet generated index - this is the index found to be les or equl to the
42   * argument provided when tailSet() methos was invoked
43   */
44      int tsindex = 0;
45  /**
46   * size of the offset's array
47   */
48      int size = 0;
49  
50  /**
51   * the Contructor. fills the allocated offset's array with the large possible
52   * valuse so any valis value will be placed on front of them.
53   */
54      public SimpleSortedSet()
55      {
56          java.util.Arrays.fill(theArray, Long.MAX_VALUE);
57      }
58  /**
59   * the get method retrive the List element by offset key given as argument
60   * @param the offset to which the list should be retrived.
61   * @returns the list with annotations by this offset or null if there is no
62   * such offset placed in the map
63   */
64      public Object get(long elValue)
65      {
66          return m.get(elValue);
67      }
68  /**
69   * add the new annotation to the annotation list for the given offset
70   * Note: if the offset is not in the map new empty list is created and the
71   * annotation is added to it
72   * @param the offset of the annotation
73   * @param the annotation instance to be placed in the list
74   * @return true if the offset is already in the map false otherwise
75   */
76      public boolean add(long elValue, Object o)
77      {
78  // get the list by offset
79          Object f = m.get(elValue);
80          if (f == null)
81          {
82  // there is no such offset in the map
83  // create one empty list
84              f = new ArrayList();
85  // put it in the map
86              m.put(elValue, f);
87  // add the annotation to it
88              ((ArrayList)f).add(o);
89  // update the size of the offsets array if necessery
90              if (theArray.length == size)
91              {
92              // allocate
93                  long[] temp = new long[theArray.length*2]; // + INCREMENT
94              // copy the old
95                  System.arraycopy(theArray, 0, temp, 0, theArray.length);
96              // fill the rest wit the large possible value
97                  java.util.Arrays.fill(temp, theArray.length, temp.length , Integer.MAX_VALUE);
98              // get it
99                  theArray = temp;
100             }
101             // put the offset into the array
102             theArray[size++] = elValue;
103             // indicate the 'new element' condition
104             return false;
105         }
106         // yes we already have an annotation liss for this offset
107         // add the annotation to it
108         ((ArrayList)f).add(o);
109 
110         return true;
111     } // add
112 
113     /**
114      * sort the offset's array in ascending way
115      */
116     public void sort()
117     {
118       java.util.Arrays.sort(theArray,0,size);
119     }
120     /**
121      * retrive the smallest offset of the array. If there was a tailset before
122      * then retrive the smallest or equal element given the index calculated ad tailSet() method
123      * @return the offset value conforming the above conditions
124      */
125     public long first()
126     {
127         if (tsindex >= size) return -1;
128         return theArray[tsindex];
129     } // first()
130 
131     /**
132      * calculate the index of the first element in the offset's array that is
133      * equal or not greater then the given one
134      * @param the value to search for
135      * @return actually <B>this</B>. Used to mimic the TreeSet.tailSet()
136      */
137     public SimpleSortedSet tailSet(long elValue)
138     {
139         // small speedup opt. because most of the queries are about to the same
140         // or the next element in the array
141         if (tsindex < theArray.length && elValue != theArray[tsindex])
142         {
143             if (tsindex<(size-1) && elValue > theArray[tsindex] &&
144                 elValue <= theArray[tsindex+1])
145                 {
146                     tsindex++;
147                    return this;
148                 }
149             int index = java.util.Arrays.binarySearch(theArray, elValue);
150             if (index < 0)
151                 index = ~index;
152             tsindex = index;
153         }
154         return this;
155     } // tailSet()
156 
157     /**
158      * is the map is empty
159      * @return true if teher is no element in the map
160      */
161     public boolean isEmpty()
162     {
163         return m.isEmpty();
164     } // isEmpty
165 
166     // return the number of distinct offsets in the map
167     public int size()
168     {
169         return size;
170     }
171 } //SimpleSortedSet
172 
173