001 
002 /*
003  *  JScripter Simulation 1.0 - For Java To Script
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package org.jscripter.sim;
021 
022 import java.util.TreeMap;
023 
024 import js.ArrayLike;
025 import js.Vars;
026 import js.core.JsArray;
027 import js.core.JsFunction;
028 
029 final class SimArray<T> extends TreeMap<Integer, T> implements ArrayLike<T>
030 {
031     private static final long serialVersionUID = 1L;
032 
033     public SimArray() {}
034 
035     public SimArray(ArrayLike<T> a) {
036         synchronized(a) {
037             for (int i = 0, len = a.length(); i < len; i++) {
038                 push(a.get(i));
039             }
040         }
041     }
042 
043     //@Override
044     public final synchronized boolean delete(int i) {
045         if (isEmpty()) {
046             return false;
047         }
048         return remove(i + firstKey()) != null;
049     }
050 
051     //@Override
052     public final synchronized T get(int i) {
053         if (isEmpty()) {
054             return null;
055         }
056         return super.get(i + firstKey());
057     }
058 
059     //@Override
060     public final synchronized T set(int i, T v) {
061         if (isEmpty()) {
062             put(0, null);
063         }
064         put(i + firstKey(), v);
065         return v;
066     }
067 
068     private final void relength() {
069         if (isEmpty()) {
070             return;
071         }
072         int last = lastKey();
073         while(super.get(last) == null)  {
074             remove(last);
075             if (isEmpty()) {
076                 return;
077             }
078             last = lastKey();
079         }
080     }
081 
082     //@Override
083     public final synchronized int length() {
084         relength();
085         return isEmpty() ? 0 : lastKey() - firstKey() + 1;
086     }
087 
088     //@Override
089     public final synchronized int length(int len) {
090         return len;
091     }
092 
093     //@Override
094     public final Integer index() {
095         return null;
096     }
097 
098     //@Override
099     public final String input() {
100         return null;
101     }
102 
103     //@Override
104     public final synchronized T pop() {
105         relength();
106         return isEmpty() ? null : remove(lastKey());
107     }
108 
109     @SuppressWarnings("unchecked")
110     //@Override
111     public final synchronized int push(Object v) {
112         relength();
113         if (isEmpty()) {
114             put(0, (T)v);
115         } else {
116             put(lastKey() + 1, (T)v);
117         }
118         return length();
119     }
120 
121     //@Override
122     public final synchronized ArrayLike<T> concat(Vars<?> args) {
123         return SimArrays.concat(new SimArrayList<T>(), this, args);
124     }
125 
126     //@Override
127     public final synchronized ArrayLike<T> concat(Object arg) {
128         return SimArrays.concat(new SimArrayList<T>(), this, arg);
129     }
130 
131     //@Override
132     public final synchronized String join() {
133         return SimArrays.join(this);
134     }
135 
136     //@Override
137     public final synchronized String join(Object separator) {
138         return SimArrays.join(this, separator);
139     }
140 
141     @SuppressWarnings("unchecked")
142     //@Override
143     public final synchronized int push(Vars<?> args) {
144         relength();
145         ArrayLike<?> a = args.var();
146         for (int i = 0, len = a.length(); i < len; i++) {
147             if (isEmpty()) {
148                 put(0, (T)a.get(i));
149             } else {
150                 put(lastKey() + 1, (T)a.get(i));
151             }
152         }
153         return length();
154     }
155 
156     //@Override
157     public final synchronized void reverse() {
158         SimArrays.reverse(this);
159     }
160 
161     //@Override
162     public final synchronized T shift() {
163         relength();
164         return isEmpty() ? null : remove(firstKey());
165     }
166 
167     //@Override
168     public final synchronized ArrayLike<T> slice(Vars<?> args) {
169         return SimArrays.slice(this, args);
170     }
171 
172     //@Override
173     public final synchronized ArrayLike<T> slice(Object start) {
174         return SimArrays.slice(this, start);
175     }
176 
177     //@Override
178     public final synchronized ArrayLike<T> slice(Object start, Object end) {
179         return SimArrays.slice(this, start, end);
180     }
181 
182     //@Override
183     public final synchronized ArrayLike<T> sort() {
184         throw new UnsupportedOperationException();
185     }
186 
187     //@Override
188     public final synchronized ArrayLike<T> sort(JsFunction<? extends Number> orderfunc) {
189         throw new UnsupportedOperationException();
190     }
191 
192     //@Override
193     public final synchronized ArrayLike<T> splice(Vars<?> args) {
194         ArrayLike<?> a = args.var();
195         int len = a.length();
196         if (len < 2) {
197             return splice(a.get(0));
198         } else if (len < 3) {
199             return splice(a.get(0), a.get(1));
200         } else if (len < 4) {
201             return splice(a.get(0), a.get(1), a.get(2));
202         } else {
203             Vars<Object> vars = new Vars<Object>();
204             for (int i = 3; i < len; i++) {
205                 vars.add(a.get(i));
206             }
207             return splice(a.get(0), a.get(1), vars);
208         }
209     }
210 
211     //@Override
212     public final synchronized ArrayLike<T> splice(Object start) {
213         relength();
214         SimArray<T> a = new SimArray<T>();
215         if (!isEmpty()) {
216             int i = SimUtil.getNumber(start).intValue() + firstKey();
217             int last = lastKey();
218             for (int j = 0; i <= last; i++, j++) {
219                 T v = remove(i);
220                 if (v != null) {
221                     a.put(j, v);
222                 }
223             }
224         }
225         return a;
226     }
227 
228     //@Override
229     public final synchronized ArrayLike<T> splice(Object start, Object deleteCount) {
230         relength();
231         SimArray<T> a = new SimArray<T>();
232         if (!isEmpty()) {
233             int i = SimUtil.getNumber(start).intValue() + firstKey();
234             int n = SimUtil.getNumber(deleteCount).intValue();
235             for (int j = 0; j < n; i++, j++) {
236                 T v = remove(i);
237                 if (v != null) {
238                     a.put(j, v);
239                 }
240             }
241         }
242         return a;
243     }
244 
245     @SuppressWarnings("unchecked")
246     //@Override
247     public final synchronized ArrayLike<T> splice(Object start, Object deleteCount, Object arg) {
248         relength();
249         SimArray<T> a = new SimArray<T>();
250         if (!isEmpty()) {
251             int i = SimUtil.getNumber(start).intValue() + firstKey();
252             int n = SimUtil.getNumber(deleteCount).intValue();
253             for (int j = 0; j < n; i++, j++) {
254                 T v = remove(i);
255                 if (v != null) {
256                     a.put(j, v);
257                 }
258             }
259             put(i, (T)arg);
260         }
261         return a;
262     }
263 
264     @SuppressWarnings("unchecked")
265     //@Override
266     public final synchronized ArrayLike<T> splice(Object start, Object deleteCount, Vars<?> args) {
267         relength();
268         SimArray<T> a = new SimArray<T>();
269         if (!isEmpty()) {
270             int i = SimUtil.getNumber(start).intValue() + firstKey();
271             int n = SimUtil.getNumber(deleteCount).intValue();
272             for (int j = 0; j < n; i++, j++) {
273                 T v = remove(i);
274                 if (v != null) {
275                     a.put(j, v);
276                 }
277             }
278             ArrayLike<?> va = args.var();
279             for (int j = 0, len = va.length(); j < len; j++) {
280                 put(i++, (T)va.get(i));
281             }
282         }
283         return a;
284     }
285 
286     @SuppressWarnings("unchecked")
287     //@Override
288     public final synchronized int unshift(Object arg) {
289         relength();
290         put(firstKey() - 1, (T)arg);
291         return length();
292     }
293 
294     @SuppressWarnings("unchecked")
295     //@Override
296     public final synchronized int unshift(Vars<?> args) {
297         relength();
298         ArrayLike<?> a = args.var();
299         for (int i = 0, len = a.length(); i < len; i++) {
300             put(firstKey() - 1, (T)a.get(i));
301         }
302         return length();
303     }
304 
305     //@Override
306     public final String toString() {
307         return SimArrays.toString(this);
308     }
309 
310     //@Override
311     public final SimArray<T> valueOf() {
312         return this;
313     }
314 
315     //@Override
316     public final JsArray var() {
317         throw new UnsupportedOperationException();
318     }
319 }