ArrayProxy.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.6.0).
003  * Copyright (c) 2007-2014 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019  */
020 package org.jenetics.internal.util;
021 
022 import static java.lang.String.format;
023 
024 import org.jenetics.util.Copyable;
025 
026 /**
027  * Abstraction for an ordered and bounded sequence of elements.
028  *
029  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
030  @since 1.4
031  @version 1.5 &mdash; <em>$Date: 2014-02-15 $</em>
032  */
033 public abstract class ArrayProxy<T> implements Copyable<ArrayProxy<T>> {
034 
035     protected final int _start;
036     protected final int _end;
037     protected final int _length;
038 
039     protected ArrayProxy(final int from, final int until) {
040         if (from < || until < || until < from) {
041             throw new IllegalArgumentException(format(
042                 "Invalid indexes [%d, %d)", from, until
043             ));
044         }
045 
046         _start = from;
047         _end = until;
048         _length = _end - _start;
049     }
050 
051     /**
052      * Return the <i>array</i> element at the specified, absolute position in
053      * the {@code ArrayProxy}. The array boundaries are not checked.
054      *
055      @param absoluteIndex absolute index of the element to return
056      @return the <i>array</i> element at the specified absolute position
057      */
058     public abstract T __get(final int absoluteIndex);
059 
060     /**
061      * Set the <i>array</i> element at the specified absolute position in the
062      * {@code ArrayProxy}. The array boundaries are not checked.
063      *
064      @param absoluteIndex absolute index of the <i>array</i> element
065      */
066     public abstract void __set(final int absoluteIndex, final T value);
067 
068     /**
069      * Return the <i>array</i> element at the specified position in the
070      * {@code ArrayProxy}. The array boundaries are not checked.
071      *
072      @param index index of the element to return
073      @return the <i>array</i> element at the specified position
074      */
075     public T uncheckedGet(final int index) {
076         return __get(index + _start);
077     }
078 
079     /**
080      * Set the <i>array</i> element at the specified position in the
081      * {@code ArrayProxy}. The array boundaries are not checked.
082      *
083      @param index index of the <i>array</i> element
084      */
085     public void uncheckedSet(final int index, final T value) {
086         __set(index + _start, value);
087     }
088 
089     /**
090      * Return the <i>array</i> element at the specified position in the
091      * {@code ArrayProxy}.
092      *
093      @param index index of the element to return
094      @return the <i>array</i> element at the specified position
095      @throws IndexOutOfBoundsException if the index it out of range
096      *         (index < 0 || index >= _length).
097      */
098     public T get(final int index) {
099         checkIndex(index);
100         return __get(index + _start);
101     }
102 
103     /**
104      * Set the <i>array</i> element at the specified position in the
105      * {@code ArrayProxy}
106      *
107      @param index the index of the element to set
108      @param value the <i>array</i> element
109      @throws IndexOutOfBoundsException if the index it out of range
110      *         (index < 0 || index >= _length).
111      */
112     public void set(final int index, final T value) {
113         checkIndex(index);
114         __set(index + _start, value);
115     }
116 
117     /**
118      * Return a new sub {@code ArrayProxy} object with the given start and end
119      * indexes. The underlying array storage is not copied. With the returned
120      * sub-array proxy it is possible to <i>write through</i> the original
121      * array.
122      *
123      @param from the start index of the new sub {@code ArrayProxy} object,
124      *        inclusively.
125      @param until the end index of the new sub {@code ArrayProxy} object,
126      *        exclusively.
127      @return a new array proxy (view) with the given start and end index.
128      @throws IndexOutOfBoundsException if the given indexes are out of bounds.
129      */
130     public abstract ArrayProxy<T> slice(final int from, final int until);
131 
132     /**
133      * Return a new sub {@code ArrayProxy} object with the given start index.
134      * The underlying array storage is not copied. With the returned sub-array
135      * proxy it is possible to <i>write through</i> the original array.
136      *
137      @param from the start index of the new sub {@code ArrayProxy} object,
138      *        inclusively.
139      @return a new array proxy (view) with the given start index.
140      @throws IndexOutOfBoundsException if the given indexes are out of bounds.
141      */
142     public ArrayProxy<T> slice(final int from) {
143         return slice(from, _length);
144     }
145 
146     /**
147      * Swap a given range with a range of the same size with another array.
148      * Implementations of this class should replace this with a optimized
149      * version, depending on the underlying data structure.
150      *
151      <pre>
152      *            from                until
153      *              |                   |
154      * this:  +---+---+---+---+---+---+---+---+---+---+---+---+
155      *              +---------------+
156      *                          +---------------+
157      * other: +---+---+---+---+---+---+---+---+---+---+---+---+
158      *                          |
159      *                      otherFrom
160      </pre>
161      *
162      @param from the start index of {@code this} range, inclusively.
163      @param until the end index of {@code this} range, exclusively.
164      @param other the other array to swap the elements with.
165      @param otherFrom the start index of the {@code other} array.
166      @throws IndexOutOfBoundsException if {@code start > end} or
167      *         if {@code from < 0 || until >= this.length() || otherFrom < 0 ||
168      *         otherFrom + (until - from) >= other.length()}
169      */
170     public void swap(
171         final int from,
172         final int until,
173         final ArrayProxy<T> other,
174         final int otherFrom
175     ) {
176         checkIndex(from, until);
177         other.checkIndex(otherFrom, otherFrom + (until - from));
178         cloneIfSealed();
179         other.cloneIfSealed();
180 
181         for (int i = (until - from); --i >= 0;) {
182             final T temp = uncheckedGet(i + from);
183             uncheckedSet(i + from, other.uncheckedGet(otherFrom + i));
184             other.uncheckedSet(otherFrom + i, temp);
185         }
186     }
187 
188     /**
189      * Clone the underlying data structure of this {@code ArrayProxy} if it is
190      * sealed.
191      <p/>
192      * The <i>default</i> implementation will look like this:
193      * [code]
194      *     public void cloneIfSealed() {
195      *         if (_sealed) {
196      *             _array = _array.clone();
197      *             _sealed = false;
198      *         }
199      *     }
200      * [/code]
201      */
202     public abstract void cloneIfSealed();
203 
204 
205     /**
206      * Set the seal flag for this {@code ArrayProxy} instance and return a new
207      * {@code ArrayProxy} object with an not set <i>seal</i> flag but with the
208      * same underlying data structure.
209      <p/>
210      * The <i>default</i> implementation will look like this:
211      * [code]
212      * public MyArrayProxy<T> seal() {
213      *     _sealed = true;
214      *     return new MyArrayProxy(_array, _start, _end);
215      * }
216      * [code]
217      *
218      @return a new {@code ArrayProxy} instance; for command chaining.
219      */
220     public abstract ArrayProxy<T> seal();
221 
222     /**
223      * Checks the given index.
224      *
225      @param from the index to check.
226      @throws java.lang.ArrayIndexOutOfBoundsException if the given index is
227      *         not in the valid range.
228      */
229     protected final void checkIndex(final int from) {
230         if (from < || from >= _length) {
231             throw new ArrayIndexOutOfBoundsException(format(
232                 "Index %s is out of bounds [0, %s)", from, _length
233             ));
234         }
235     }
236 
237     /**
238      * Check the given {@code from} and {@code until} indices.
239      *
240      @param from the start index, inclusively.
241      @param until the end index, exclusively.
242      @throws java.lang.ArrayIndexOutOfBoundsException if the given index is
243      *         not in the valid range.
244      */
245     protected final void checkIndex(final int from, final int until) {
246         if (from > until) {
247             throw new ArrayIndexOutOfBoundsException(format(
248                 "fromIndex(%d) > toIndex(%d)", from, until
249             ));
250         }
251         if (from < || until > _length) {
252             throw new ArrayIndexOutOfBoundsException(format(
253                 "Invalid index range: [%d, %s)", from, until
254             ));
255         }
256     }
257 
258 
259 }