View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript-Util: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2005 Kevin Rogers
4   //
5   // This file is part of MillScript-Util.
6   //
7   // MillScript-Util is free software; you can redistribute it and/or modify it under
8   // the terms of the GNU General Public License as published by the Free
9   // Software Foundation; either version 2 of the License, or (at your option)
10  // any later version.
11  //
12  // MillScript-Util is distributed in the hope that it will be useful, but WITHOUT
13  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  // more details.
16  //
17  // You should have received a copy of the GNU General Public License along with
18  // MillScript-Util; if not, write to the Free Software Foundation, Inc., 59 Temple
19  // Place, Suite 330, Boston, MA  02111-1307  USA
20  ////////////////////////////////////////////////////////////////////////////////
21  package org.millscript.commons.util.list;
22  
23  import java.io.Serializable;
24  
25  import org.millscript.commons.alert.alerts.Fault;
26  import org.millscript.commons.util.IList;
27  import org.millscript.commons.util.ListIterator;
28  import org.millscript.commons.util.alerts.ListIndexOutOfBoundsAlert;
29  import org.millscript.commons.util.iterator.AbstractListIterator;
30  
31  /**
32   * This class provides an immutable <code>List</code> implementation which is
33   * backed by a String(i.e. a list of characters).
34   */
35  public class IStringList extends AbstractIList< Character > implements Cloneable, Serializable {
36  
37      /**
38       * This is the ID from the release 0.1.0 for future compatibility.
39       */
40      private static final long serialVersionUID = 1025372624400670L;
41  
42      /**
43       * This class provides a map interator implementation which iterates over
44       * the characters in a string and their position in the string.
45       */
46      public static class StringListIterator extends AbstractListIterator< Character > {
47  
48          /**
49           * The backing string for this iterator.
50           */
51          private final String string;
52  
53          /**
54           * Constructs a new string map iterator to iterate over the characters
55           * in the specified string and their position in the string.
56           *
57           * @param obj   the string whose characters to iterate over
58           */
59          public StringListIterator( final String s ) {
60              this.string = s;
61          }
62  
63          /**
64           * @see org.millscript.commons.util.iterator.AbstractMapIterator#getValue()
65           */
66          @Override
67          protected Character getValue() {
68              return new Character( this.string.charAt( super.position - 1 ) );
69          }
70  
71          /**
72           * @see org.millscript.commons.util.MapIterator#hasNext()
73           */
74          public boolean hasNext() {
75              return super.position < this.string.length();
76          }
77  
78          /**
79           * @see org.millscript.commons.util.iterator.AbstractMapIterator#outOfBounds()
80           */
81          @Override
82          protected boolean outOfBounds() {
83              return super.position == 0 || super.position > this.string.length();
84          }
85  
86      }
87  
88      /**
89       * The backing store string.
90       */
91      private final String store;
92  
93      /**
94       * Constructs a new empty immutable string list. 
95       */
96      public IStringList() {
97          this.store = "";
98      }
99  
100     /**
101      * Constructs a new immutable string list with the specified backing
102      * string.
103      *
104      * @param objects   the backing string
105      */
106     public IStringList( final String string ) {
107         this.store = string;
108     }
109 
110     /**
111      * Constructs a new immutable string list with a copy of the specified
112      * backing string, starting and ending at the specified indices.
113      *
114      * @param objects   the backing string to copy
115      * @param start the index of the first element in the slice
116      * @param end   the index of the last element in the slice. If end &lt;
117      * start, the new list will be empty
118      */
119     public IStringList( final String string, final int start, final int end ) {
120         if ( start > end ) {
121             this.store = "";
122         } else if ( start < 1 || start > string.length() ) {
123             throw new ListIndexOutOfBoundsAlert(
124                 "First index in slice must be between 1 and the length of the string"
125             ).culprit(
126                 "index",
127                 start
128             ).decorate( string ).mishap();
129         } else if ( end > string.length() ) {
130             throw new ListIndexOutOfBoundsAlert(
131                 "Last index in slice must not be greater than the length of the string"
132             ).culprit(
133                 "index",
134                 end
135             ).decorate( string ).mishap();
136         } else if ( start == 1 && end == string.length() ){
137             // You should really have called IStringList() if you knew
138             // you where looking at the whole string
139             this.store = string;
140         } else {
141             try {
142                 final StringBuffer temp = new StringBuffer( end - start + 1 );
143                 temp.append( string.substring( start - 1, end ) );
144                 this.store = temp.toString();
145             } catch ( Exception ex ) {
146                 throw new Fault(
147                     "Failed to take a copy of the specified string slice"
148                 ).setParentThrowable( ex ).mishap();
149             } 
150         }
151     }
152 
153     /**
154      * @see java.lang.Object#clone()
155      */
156     @Override
157     public Object clone() throws CloneNotSupportedException {
158         // Nothing special required for this clone
159         return super.clone();
160     }
161 
162     /**
163      * @see org.millscript.commons.util.list.AbstractIList#doGet(int)
164      */
165     @Override
166     protected Character doGet( final int pos ) {
167         return new Character( this.store.charAt( pos - 1 ) );
168     }
169 
170     /**
171      * @see org.millscript.commons.util.list.AbstractIList#doSlice(int, int, boolean)
172      */
173     @Override
174     protected IList< Character > doSlice( final int first, final int last, final boolean share ) {
175         if ( share ) {
176             return new IStringList(
177                 this.store.substring( first - 1, last )
178             );
179         } else {
180             // Return a copy of the relevant slice of the list
181             return new IStringList( this.store, first, last );
182         }
183     }
184 
185     /**
186      * @see org.millscript.commons.util.IList#indexOf(java.lang.Object)
187      */
188     public int indexOf( final Character value ) {
189         if ( value != null ) {
190             return this.store.indexOf( value.charValue() ) + 1;
191         }
192         return 0;
193     }
194 
195     /**
196      * @see org.millscript.commons.util.IMap#iterator(boolean)
197      */
198     public ListIterator< Character > iterator( final boolean share ) {
199         // Our backing store is immutable, so there's no point in trying to
200         // take a copy, we can always share
201         return new StringListIterator( this.store );
202     }
203 
204     /**
205      * @see org.millscript.commons.util.IMap#size()
206      */
207     public int size() {
208         return this.store.length();
209     }
210 
211 }