KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > env > ArrayValue


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.quercus.env;
31
32 import com.caucho.quercus.function.Marshal;
33 import com.caucho.quercus.function.MarshalFactory;
34 import com.caucho.vfs.WriteStream;
35
36 import java.io.IOException JavaDoc;
37 import java.io.Serializable JavaDoc;
38 import java.lang.reflect.Array JavaDoc;
39 import java.util.*;
40 import java.util.logging.Level JavaDoc;
41 import java.util.logging.Logger JavaDoc;
42
43 /**
44  * Represents a PHP array value.
45  */

46 abstract public class ArrayValue extends Value {
47   private static final Logger JavaDoc log
48     = Logger.getLogger(ArrayValue.class.getName());
49
50   protected static final StringValue KEY = new StringValueImpl("key");
51   protected static final StringValue VALUE = new StringValueImpl("value");
52
53   private static final int SORT_REGULAR = 0;
54   private static final int SORT_NUMERIC = 1;
55   private static final int SORT_STRING = 2;
56   private static final int SORT_LOCALE_STRING = 5;
57
58   public static final GetKey GET_KEY = new GetKey();
59   public static final GetValue GET_VALUE = new GetValue();
60
61   protected Entry _current;
62
63   protected ArrayValue()
64   {
65   }
66
67   /**
68    * Returns the type.
69    */

70   public String JavaDoc getType()
71   {
72     return "array";
73   }
74
75   /**
76    * Converts to a boolean.
77    */

78   public boolean toBoolean()
79   {
80     return getSize() != 0;
81   }
82
83   /**
84    * Converts to a string.
85    */

86   public String JavaDoc toString()
87   {
88     return "Array";
89   }
90
91   /**
92    * Converts to an object.
93    */

94   public Object JavaDoc toObject()
95   {
96     return null;
97   }
98
99   /**
100    * Converts to a java object.
101    */

102   @Override JavaDoc
103   public Object JavaDoc toJavaObject()
104   {
105     return this;
106   }
107
108   //
109
// Conversions
110
//
111

112   /**
113    * Converts to an object.
114    */

115   public Value toArray()
116   {
117     return this;
118   }
119   
120   /**
121    * Converts to an array value
122    */

123   @Override JavaDoc
124   public ArrayValue toArrayValue(Env env)
125   {
126     return this;
127   }
128
129   /**
130    * Converts to an object.
131    */

132   public Value toObject(Env env)
133   {
134     Value obj = env.createObject();
135
136     for (Entry entry = getHead(); entry != null; entry = entry._next) {
137       Value key = entry.getKey();
138
139       if (key instanceof StringValue) {
140         // XXX: intern?
141
obj.putField(env, key.toString(), entry.getValue());
142       }
143     }
144
145     return obj;
146   }
147
148   /**
149    * Converts to a java List object.
150    */

151   public Collection toJavaCollection(Env env, Class JavaDoc type)
152   {
153     Collection coll = null;
154     
155     if (type.isAssignableFrom(HashSet.class)) {
156       coll = new HashSet();
157     }
158     else if (type.isAssignableFrom(TreeSet.class)) {
159       coll = new TreeSet();
160     }
161     else {
162       try {
163         coll = (Collection) type.newInstance();
164       }
165       catch (Throwable JavaDoc e) {
166         log.log(Level.FINE, e.toString(), e);
167         env.warning(L.l("Can't assign array to {0}", type.getName()));
168
169         return null;
170       }
171     }
172     
173     for (Entry entry = getHead(); entry != null; entry = entry._next) {
174       coll.add(entry.getValue().toJavaObject());
175     }
176
177     return coll;
178   }
179   
180   /**
181    * Converts to a java List object.
182    */

183   public List toJavaList(Env env, Class JavaDoc type)
184   {
185     List list = null;
186     
187     if (type.isAssignableFrom(ArrayList.class)) {
188       list = new ArrayList();
189     }
190     else if (type.isAssignableFrom(LinkedList.class)) {
191       list = new LinkedList();
192     }
193     else if (type.isAssignableFrom(Vector.class)) {
194       list = new Vector();
195     }
196     else {
197       try {
198         list = (List) type.newInstance();
199       }
200       catch (Throwable JavaDoc e) {
201         log.log(Level.FINE, e.toString(), e);
202         env.warning(L.l("Can't assign array to {0}", type.getName()));
203
204         return null;
205       }
206     }
207
208     for (Entry entry = getHead(); entry != null; entry = entry._next) {
209       list.add(entry.getValue().toJavaObject());
210     }
211
212     return list;
213   }
214   
215   /**
216    * Converts to a java object.
217    */

218   @Override JavaDoc
219   public Map toJavaMap(Env env, Class JavaDoc type)
220   {
221     Map map = null;
222     
223     if (type.isAssignableFrom(TreeMap.class)) {
224       map = new TreeMap();
225     }
226     else if (type.isAssignableFrom(LinkedHashMap.class)) {
227       map = new LinkedHashMap();
228     }
229     else {
230       try {
231         map = (Map) type.newInstance();
232       }
233       catch (Throwable JavaDoc e) {
234         log.log(Level.FINE, e.toString(), e);
235     
236         env.warning(L.l("Can't assign array to {0}",
237                         type.getName()));
238
239     return null;
240       }
241     }
242
243     for (Entry entry = getHead(); entry != null; entry = entry._next) {
244       map.put(entry.getKey().toJavaObject(),
245               entry.getValue().toJavaObject());
246     }
247
248     return map;
249   }
250
251   /**
252    * Returns true for an array.
253    */

254   public boolean isArray()
255   {
256     return true;
257   }
258
259   /**
260    * Copy as a return value
261    */

262   public Value copyReturn()
263   {
264     return copy(); // php/3a5e
265
}
266
267   /**
268    * Copy for assignment.
269    */

270   abstract public Value copy();
271
272   /**
273    * Copy for serialization
274    */

275   abstract public Value copy(Env env, IdentityHashMap<Value,Value> map);
276
277   /**
278    * Returns the size.
279    */

280   abstract public int getSize();
281
282   /**
283    * Clears the array
284    */

285   abstract public void clear();
286
287   /**
288    * Adds a new value.
289    */

290   abstract public Value put(Value key, Value value);
291
292   /**
293    * Add
294    */

295   abstract public Value put(Value value);
296
297   /**
298    * Add to front.
299    */

300   abstract public ArrayValue unshift(Value value);
301
302   /**
303    * Splices.
304    */

305   abstract public ArrayValue splice(int begin, int end, ArrayValue replace);
306
307   /**
308    * Returns the value as an array.
309    */

310   public Value getArray(Value index)
311   {
312     Value value = get(index);
313
314     Value array = value.toAutoArray();
315     
316     if (value != array) {
317       value = array;
318
319       put(index, value);
320     }
321
322     return value;
323   }
324
325   /**
326    * Returns the value as an argument which may be a reference.
327    */

328   abstract public Value getArg(Value index);
329
330   /**
331    * Returns the field value, creating an object if it's unset.
332    */

333   public Value getObject(Env env, Value fieldName)
334   {
335     Value value = get(fieldName);
336
337     Value object = value.toAutoObject(env);
338     if (value != object) {
339       value = object;
340
341       put(fieldName, value);
342     }
343
344     return value;
345   }
346
347   /**
348    * Sets the array ref.
349    */

350   abstract public Value putRef();
351
352   /**
353    * Creatse a tail index.
354    */

355   abstract public Value createTailKey();
356
357   /**
358    * Returns a union of this array and the rValue as array.
359    * If the rValue is not an array, the returned union contains the elements
360    * of this array only.
361    *
362    * To append a value to this ArrayValue use the {@link #put(Value)} method.
363    */

364   public Value add(Value rValue)
365   {
366     rValue = rValue.toValue();
367
368     if (! (rValue instanceof ArrayValue))
369       return copy();
370
371     ArrayValue rArray = (ArrayValue) rValue;
372
373     ArrayValue result = new ArrayValueImpl(rArray);
374
375     for (Entry entry = getHead(); entry != null; entry = entry._next) {
376       result.put(entry.getKey(), entry.getValue());
377     }
378
379     return result;
380   }
381
382   /**
383    * Returns the field values.
384    */

385   public Collection<Value> getIndices()
386   {
387     return new KeySet();
388   }
389
390   /**
391    * Returns the field keys.
392    */

393   public Value []getKeyArray()
394   {
395     int size = getSize();
396
397     if (size == 0)
398       return NULL_VALUE_ARRAY;
399
400     Value []keys = new Value[size];
401
402     int i = 0;
403     for (Entry ptr = getHead(); ptr != null; ptr = ptr._next)
404       keys[i++] = ptr.getKey();
405
406     return keys;
407   }
408
409   /**
410    * Returns the field values.
411    */

412   public Value []getValueArray(Env env)
413   {
414     int size = getSize();
415
416     if (size == 0)
417       return NULL_VALUE_ARRAY;
418
419     Value []values = new Value[size];
420
421     int i = 0;
422     for (Entry ptr = getHead(); ptr != null; ptr = ptr._next) {
423       // XXX: the toValue() needs a test
424
values[i++] = ptr.getValue().toValue().copy();
425     }
426
427     return values;
428   }
429
430   /**
431    * Gets a new value.
432    */

433   abstract public Value get(Value key);
434
435   /**
436    * Removes a value.
437    */

438   abstract public Value remove(Value key);
439
440   /**
441    * Returns the array ref.
442    */

443   abstract public Var getRef(Value index);
444
445   /**
446    * Returns an iterator of the entries.
447    */

448   public Set<Value> keySet()
449   {
450     return new KeySet();
451   }
452
453   /**
454    * Returns a set of all the of the entries.
455    */

456   public Set<Map.Entry<Value,Value>> entrySet()
457   {
458     return new EntrySet();
459   }
460
461   /**
462    * Returns a collection of the values.
463    */

464   public Collection<Value> values()
465   {
466     return new ValueCollection();
467   }
468
469   /**
470    * Convenience for lib.
471    */

472   public void put(String JavaDoc key, String JavaDoc value)
473   {
474     put(new StringValueImpl(key), new StringValueImpl(value));
475   }
476
477   /**
478    * Convenience for lib.
479    */

480   public void put(String JavaDoc key, long value)
481   {
482     put(new StringValueImpl(key), new LongValue(value));
483   }
484
485   /**
486    * Convenience for lib.
487    */

488   public void put(String JavaDoc key, boolean value)
489   {
490     put(new StringValueImpl(key), value ? BooleanValue.TRUE : BooleanValue.FALSE);
491   }
492
493   /**
494    * Convenience for lib.
495    */

496   public void put(String JavaDoc value)
497   {
498     put(new StringValueImpl(value));
499   }
500
501   /**
502    * Convenience for lib.
503    */

504   public void put(long value)
505   {
506     put(new LongValue(value));
507   }
508
509   /**
510    * Appends as an argument - only called from compiled code
511    *
512    * XXX: change name to appendArg
513    */

514   public ArrayValue append(Value key, Value value)
515   {
516     put(key, value);
517
518     return this;
519   }
520
521   /**
522    * Appends as an argument - only called from compiled code
523    *
524    * XXX: change name to appendArg
525    */

526   public ArrayValue append(Value value)
527   {
528     put(value);
529
530     return this;
531   }
532
533   /**
534    * Appends as an argument - only called from compiled code
535    *
536    * XXX: change name to appendArg
537    */

538   public void putAll(ArrayValue array)
539   {
540     for (Map.Entry<Value, Value> entry : array.entrySet())
541       put(entry.getKey(), entry.getValue());
542   }
543
544   /**
545    * Convert to an array.
546    */

547   public static Value toArray(Value value)
548   {
549     value = value.toValue();
550
551     if (value instanceof ArrayValue)
552       return value;
553     else
554       return new ArrayValueImpl().put(value);
555   }
556
557   /**
558    * Compare two arrays.
559    */

560   public int compareArray(ArrayValue rValue)
561   {
562     // XXX: "if key from operand 1 is not found in operand 2 then
563
// arrays are uncomparable, otherwise - compare value by value"
564
int lArraySize = this.getSize();
565     int rArraySize = rValue.getSize();
566     if (lArraySize < rArraySize) return -1;
567     if (lArraySize > rArraySize) return 1;
568     return 0;
569   }
570
571   /**
572    * Prints the value.
573    * @param env
574    */

575   public void print(Env env)
576   {
577     env.print("Array");
578   }
579
580   /**
581    * Pops the top value.
582    */

583   abstract public Value pop();
584
585   /**
586    * Shuffles the array
587    */

588   abstract public void shuffle();
589
590   /**
591    * Returns the head.
592    */

593   abstract public Entry getHead();
594
595   /**
596    * Returns the tail.
597    */

598   abstract protected Entry getTail();
599
600   /**
601    * Returns the current value.
602    */

603   public Value current()
604   {
605     if (_current != null)
606       return _current.getValue();
607     else
608       return BooleanValue.FALSE;
609   }
610
611   /**
612    * Returns the current key
613    */

614   public Value key()
615   {
616     if (_current != null)
617       return _current.getKey();
618     else
619       return NullValue.NULL;
620   }
621
622   /**
623    * Returns true if there are more elements.
624    */

625   public boolean hasCurrent()
626   {
627     return _current != null;
628   }
629
630   /**
631    * Returns the next value.
632    */

633   public Value next()
634   {
635     if (_current != null)
636       _current = _current._next;
637
638     return current();
639   }
640
641   /**
642    * Returns the previous value.
643    */

644   public Value prev()
645   {
646     if (_current != null)
647       _current = _current._prev;
648
649     return current();
650   }
651
652   /**
653    * The each iterator
654    */

655   public Value each()
656   {
657     if (_current == null)
658       return NullValue.NULL;
659
660     ArrayValue result = new ArrayValueImpl();
661
662     result.put(LongValue.ZERO, _current.getKey());
663     result.put(KEY, _current.getKey());
664
665     result.put(LongValue.ONE, _current.getValue());
666     result.put(VALUE, _current.getValue());
667
668     _current = _current._next;
669
670     return result;
671   }
672
673   /**
674    * Returns the first value.
675    */

676   public Value reset()
677   {
678     _current = getHead();
679
680     return current();
681   }
682
683   /**
684    * Returns the last value.
685    */

686   public Value end()
687   {
688     _current = getTail();
689
690     return current();
691   }
692
693   /**
694    * Returns the corresponding key if this array contains the given value
695    *
696    * @param value the value to search for in the array
697    *
698    * @return the key if it is found in the array, NULL otherwise
699    *
700    * @throws NullPointerException
701    */

702   public Value contains(Value value)
703   {
704     for (Entry entry = getHead(); entry != null; entry = entry._next) {
705       if (entry.getValue().eq(value))
706         return entry.getKey();
707     }
708
709     return NullValue.NULL;
710   }
711
712   /**
713    * Returns the corresponding key if this array contains the given value
714    *
715    * @param value the value to search for in the array
716    *
717    * @return the key if it is found in the array, NULL otherwise
718    *
719    * @throws NullPointerException
720    */

721   public Value containsStrict(Value value)
722   {
723     for (Entry entry = getHead(); entry != null; entry = entry._next) {
724       if (entry.getValue().eql(value))
725         return entry.getKey();
726     }
727
728     return NullValue.NULL;
729   }
730
731   /**
732    * Returns the corresponding valeu if this array contains the given key
733    *
734    * @param key the key to search for in the array
735    *
736    * @return the value if it is found in the array, NULL otherwise
737    *
738    * @throws NullPointerException
739    */

740   abstract public Value containsKey(Value key);
741
742   /**
743    * Returns an object array of this array. This is a copy of this object's
744    * backing structure. Null elements are not included.
745    *
746    * @return an object array of this array
747    */

748   public Map.Entry<Value, Value>[] toEntryArray()
749   {
750     ArrayList<Map.Entry<Value, Value>> array =
751       new ArrayList<Map.Entry<Value, Value>>(getSize());
752
753     for (Entry entry = getHead(); entry != null; entry = entry._next)
754       array.add(entry);
755
756     Map.Entry<Value, Value>[]result = new Entry[array.size()];
757
758     return array.toArray(result);
759   }
760
761   /**
762    * Sorts this array based using the passed Comparator
763    *
764    * @param comparator the comparator for sorting the array
765    * @param resetKeys true if the keys should not be preserved
766    * @param strict true if alphabetic keys should not be preserved
767    */

768   public void sort(Comparator<Map.Entry<Value, Value>> comparator,
769                    boolean resetKeys, boolean strict)
770   {
771     Entry []entries;
772
773     entries = new Entry[getSize()];
774
775     int i = 0;
776     for (Entry entry = getHead(); entry != null; entry = entry._next) {
777       entries[i++] = entry;
778     }
779
780     Arrays.sort(entries, comparator);
781
782     clear();
783
784     long base = 0;
785
786     if (! resetKeys)
787       strict = false;
788
789     for (int j = 0; j < entries.length; j++) {
790       Value key = entries[j].getKey();
791
792       if (resetKeys && (! (key instanceof StringValue) || strict))
793         put(LongValue.create(base++), entries[j].getValue());
794       else
795         put(entries[j].getKey(), entries[j].getValue());
796     }
797   }
798
799   /**
800    * Serializes the value.
801    */

802   public void serialize(StringBuilder JavaDoc sb)
803   {
804     sb.append("a:");
805     sb.append(getSize());
806     sb.append(":{");
807
808     for (Entry entry = getHead(); entry != null; entry = entry._next) {
809       entry.getKey().serialize(sb);
810       entry.getValue().serialize(sb);
811     }
812
813     sb.append("}");
814   }
815
816   /**
817    * Exports the value.
818    */

819   public void varExport(StringBuilder JavaDoc sb)
820   {
821     sb.append("array(");
822
823     boolean isFirst = true;
824     for (Entry entry = getHead(); entry != null; entry = entry._next) {
825       entry.getKey().varExport(sb);
826       sb.append(" => ");
827       entry.getValue().varExport(sb);
828       sb.append(", ");
829     }
830
831     sb.append(")");
832   }
833
834   /**
835    * Resets all numerical keys with the first index as base
836    *
837    * @param base the initial index
838    * @param strict if true, string keys are also reset
839    */

840   public boolean keyReset(long base, boolean strict)
841   {
842     Entry []entries;
843
844     entries = new Entry[getSize()];
845
846     int i = 0;
847     for (Entry entry = getHead(); entry != null; entry = entry._next) {
848       entries[i++] = entry;
849     }
850
851     clear();
852
853     for (int j = 0; j < entries.length; j++) {
854       Value key = entries[j].getKey();
855
856       if (! (key instanceof StringValue) || strict)
857         put(LongValue.create(base++), entries[j].getValue());
858       else
859         put(entries[j].getKey(), entries[j].getValue());
860     }
861
862     return true;
863   }
864
865   /**
866    * Test for equality
867    *
868    * @param rValue rhs ArrayValue to compare to
869    *
870    * @return true if this is equal to rValue, false otherwise
871    */

872   public boolean eq(Value rValue)
873   {
874     if (rValue == null)
875       return false;
876
877     for (Map.Entry<Value, Value> entry: entrySet()) {
878       Value entryValue = entry.getValue();
879
880       Value entryKey = entry.getKey();
881
882       Value rEntryValue = rValue.get(entryKey);
883
884       if ((rEntryValue instanceof ArrayValue) &&
885           !entryValue.eq((ArrayValue) rEntryValue))
886         return false;
887
888       if (! entryValue.eq(rEntryValue))
889         return false;
890     }
891
892     return true;
893   }
894
895   /**
896    * Test for ===
897    *
898    * @param rValue rhs ArrayValue to compare to
899    *
900    * @return true if this is equal to rValue, false otherwise
901    */

902   public boolean eql(Value rValue)
903   {
904     if (rValue == null)
905       return false;
906     else if (getSize() != rValue.getSize())
907       return false;
908
909     rValue = rValue.toValue();
910
911     if (! (rValue instanceof ArrayValue))
912       return false;
913
914     ArrayValue rArray = (ArrayValue) rValue;
915
916     Iterator<Map.Entry<Value,Value>> iterA = entrySet().iterator();
917     Iterator<Map.Entry<Value,Value>> iterB = rArray.entrySet().iterator();
918
919     while (iterA.hasNext() && iterB.hasNext()) {
920       Map.Entry<Value,Value> entryA = iterA.next();
921       Map.Entry<Value,Value> entryB = iterB.next();
922
923       if (! entryA.getKey().eql(entryB.getKey()))
924         return false;
925
926       if (! entryA.getValue().eql(entryB.getValue()))
927         return false;
928     }
929
930     if (iterA.hasNext() || iterB.hasNext())
931       return false;
932     else
933       return true;
934   }
935
936   public void varDumpImpl(Env env,
937                           WriteStream out,
938                           int depth,
939                           IdentityHashMap<Value, String JavaDoc> valueSet)
940     throws IOException JavaDoc
941   {
942     out.println("array(" + getSize() + ") {");
943
944     for (Map.Entry<Value,Value> mapEntry : entrySet()) {
945       ArrayValue.Entry entry = (ArrayValue.Entry) mapEntry;
946
947       entry.varDumpImpl(env, out, depth + 1, valueSet);
948
949       out.println();
950     }
951
952     printDepth(out, 2 * depth);
953
954     out.print("}");
955   }
956
957   protected void printRImpl(Env env,
958                             WriteStream out,
959                             int depth,
960                             IdentityHashMap<Value, String JavaDoc> valueSet)
961     throws IOException JavaDoc
962   {
963     out.println("Array");
964     printDepth(out, 8 * depth);
965     out.println("(");
966
967     for (Map.Entry<Value,Value> mapEntry : entrySet()) {
968       ArrayValue.Entry entry = (ArrayValue.Entry) mapEntry;
969
970       entry.printRImpl(env, out, depth, valueSet);
971     }
972
973     printDepth(out, 8 * depth);
974     out.println(")");
975   }
976
977   public final static class Entry
978     implements Map.Entry<Value,Value>, Serializable JavaDoc
979   {
980     final Value _key;
981     Value _value;
982
983     Entry _prev;
984     Entry _next;
985
986     int _index;
987
988     public Entry(Value key)
989     {
990       _key = key;
991       _value = NullValue.NULL;
992     }
993
994     public Entry(Value key, Value value)
995     {
996       _key = key;
997       _value = value;
998     }
999
1000    public Entry getNext()
1001    {
1002      return _next;
1003    }
1004
1005    public Value getRawValue()
1006    {
1007      return _value;
1008    }
1009    
1010    public Value getValue()
1011    {
1012      return _value.toValue();
1013    }
1014
1015    public Value getKey()
1016    {
1017      return _key;
1018    }
1019
1020    public Value toValue()
1021    {
1022      // The value may be a var
1023
// XXX: need test
1024
return _value.toValue();
1025    }
1026
1027    /**
1028     * Argument used/declared as a ref.
1029     */

1030    public Var toRefVar()
1031    {
1032      // php/376a
1033

1034      Value val = _value;
1035
1036      if (val instanceof Var)
1037        return (Var) val;
1038      else {
1039        Var var = new Var(val);
1040
1041        _value = var;
1042
1043        return var;
1044      }
1045    }
1046
1047    /**
1048     * Converts to an argument value.
1049     */

1050    public Value toArgValue()
1051    {
1052      return _value.toValue();
1053    }
1054
1055    public Value setValue(Value value)
1056    {
1057      Value oldValue = _value;
1058
1059      _value = value;
1060
1061      return oldValue;
1062    }
1063
1064    /**
1065     * Converts to a variable reference (for function arguments)
1066     */

1067    public Value toRef()
1068    {
1069      Value value = _value;
1070
1071      if (value instanceof Var)
1072        return new RefVar((Var) value);
1073      else {
1074        _value = new Var(value);
1075
1076        return new RefVar((Var) _value);
1077      }
1078    }
1079
1080    /**
1081     * Converts to a variable reference (for function arguments)
1082     */

1083    public Value toArgRef()
1084    {
1085      Value value = _value;
1086
1087      if (value instanceof Var)
1088        return new RefVar((Var) value);
1089      else {
1090        _value = new Var(_value);
1091
1092        return new RefVar((Var) _value);
1093      }
1094    }
1095
1096    public Value toArg()
1097    {
1098      // php/39a4
1099
Value value = _value;
1100
1101      // php/39aj
1102
if (value instanceof Var)
1103        return value;
1104      else {
1105        _value = new Var(value);
1106
1107        return _value;
1108      }
1109    }
1110
1111    public void varDumpImpl(Env env,
1112                            WriteStream out,
1113                            int depth,
1114                            IdentityHashMap<Value, String JavaDoc> valueSet)
1115      throws IOException JavaDoc
1116    {
1117      printDepth(out, 2 * depth);
1118      out.print("[");
1119
1120      if (_key instanceof StringValue)
1121        out.print("\"" + _key + "\"");
1122      else
1123        out.print(_key);
1124
1125      out.println("]=>");
1126
1127      printDepth(out, 2 * depth);
1128
1129      _value.varDump(env, out, depth, valueSet);
1130    }
1131
1132    protected void printRImpl(Env env,
1133                              WriteStream out,
1134                              int depth,
1135                              IdentityHashMap<Value, String JavaDoc> valueSet)
1136      throws IOException JavaDoc
1137    {
1138      printDepth(out, 8 * depth);
1139      out.print(" [");
1140      out.print(_key);
1141      out.print("] => ");
1142      if (_value != null)
1143        _value.printR(env, out, depth + 1, valueSet);
1144      out.println();
1145    }
1146
1147    private void printDepth(WriteStream out, int depth)
1148      throws java.io.IOException JavaDoc
1149    {
1150      for (int i = depth; i > 0; i--)
1151        out.print(' ');
1152    }
1153
1154    public String JavaDoc toString()
1155    {
1156      return "ArrayValue.Entry[" + getKey() + "]";
1157    }
1158  }
1159
1160  /**
1161   * Takes the values of this array and puts them in a java array
1162   */

1163  public Value[] valuesToArray()
1164  {
1165    Value[] values = new Value[getSize()];
1166
1167    int i = 0;
1168    for (Entry ptr = getHead(); ptr != null; ptr = ptr.getNext()) {
1169      values[i++] = ptr.getValue();
1170    }
1171
1172    return values;
1173  }
1174
1175  /**
1176   * Takes the values of this array, unmarshals them to objects of type
1177   * <i>elementType</i>, and puts them in a java array.
1178   */

1179  public Object JavaDoc valuesToArray(Env env, Class JavaDoc elementType)
1180  {
1181    int size = getSize();
1182
1183    Object JavaDoc array = Array.newInstance(elementType, size);
1184
1185    MarshalFactory factory = env.getModuleContext().getMarshalFactory();
1186    Marshal elementMarshal = factory.create(elementType);
1187
1188    int i = 0;
1189
1190    for (Entry ptr = getHead(); ptr != null; ptr = ptr.getNext()) {
1191      Array.set(array, i++, elementMarshal.marshal(env,
1192                                                   ptr.getValue(),
1193                                                   elementType));
1194    }
1195
1196    return array;
1197  }
1198
1199  public class EntrySet extends AbstractSet<Map.Entry<Value,Value>> {
1200    EntrySet()
1201    {
1202    }
1203
1204    public int size()
1205    {
1206      return ArrayValue.this.getSize();
1207    }
1208
1209    public Iterator<Map.Entry<Value,Value>> iterator()
1210    {
1211      return new EntryIterator(getHead());
1212    }
1213  }
1214
1215  public class KeySet extends AbstractSet<Value> {
1216    KeySet()
1217    {
1218    }
1219
1220    public int size()
1221    {
1222      return ArrayValue.this.getSize();
1223    }
1224
1225    public Iterator<Value> iterator()
1226    {
1227      return new KeyIterator(getHead());
1228    }
1229  }
1230
1231  public class ValueCollection extends AbstractCollection<Value> {
1232    ValueCollection()
1233    {
1234    }
1235
1236    public int size()
1237    {
1238      return ArrayValue.this.getSize();
1239    }
1240
1241    public Iterator<Value> iterator()
1242    {
1243      return new ValueIterator(getHead());
1244    }
1245  }
1246
1247  public static class EntryIterator
1248    implements Iterator<Map.Entry<Value,Value>> {
1249    private Entry _current;
1250
1251    EntryIterator(Entry head)
1252    {
1253      _current = head;
1254    }
1255
1256    public boolean hasNext()
1257    {
1258      return _current != null;
1259    }
1260
1261    public Map.Entry<Value,Value> next()
1262    {
1263      if (_current != null) {
1264        Map.Entry<Value,Value> next = _current;
1265        _current = _current._next;
1266
1267        return next;
1268      }
1269      else
1270        return null;
1271    }
1272
1273    public void remove()
1274    {
1275      throw new UnsupportedOperationException JavaDoc();
1276    }
1277  }
1278
1279  public static class KeyIterator
1280    implements Iterator<Value> {
1281    private Entry _current;
1282
1283    KeyIterator(Entry head)
1284    {
1285      _current = head;
1286    }
1287
1288    public boolean hasNext()
1289    {
1290      return _current != null;
1291    }
1292
1293    public Value next()
1294    {
1295      if (_current != null) {
1296        Value next = _current.getKey();
1297        _current = _current._next;
1298
1299        return next;
1300      }
1301      else
1302        return null;
1303    }
1304
1305    public void remove()
1306    {
1307      throw new UnsupportedOperationException JavaDoc();
1308    }
1309  }
1310
1311  public static class ValueIterator
1312    implements Iterator<Value> {
1313    private Entry _current;
1314
1315    ValueIterator(Entry head)
1316    {
1317      _current = head;
1318    }
1319
1320    public boolean hasNext()
1321    {
1322      return _current != null;
1323    }
1324
1325    public Value next()
1326    {
1327      if (_current != null) {
1328        Value next = _current.getValue();
1329        _current = _current._next;
1330
1331        return next;
1332      }
1333      else
1334        return null;
1335    }
1336
1337    public void remove()
1338    {
1339      throw new UnsupportedOperationException JavaDoc();
1340    }
1341  }
1342
1343  public static class ValueComparator
1344    implements Comparator<Map.Entry<Value,Value>>
1345  {
1346    public static final ValueComparator CMP = new ValueComparator();
1347    
1348    private ValueComparator()
1349    {
1350    }
1351    
1352    public int compare(Map.Entry<Value,Value> aEntry,
1353                       Map.Entry<Value,Value> bEntry)
1354    {
1355      try {
1356        Value aValue = aEntry.getValue();
1357        Value bValue = bEntry.getValue();
1358
1359        if (aValue.eq(bValue))
1360          return 0;
1361        else if (aValue.lt(bValue))
1362          return -1;
1363        else
1364          return 1;
1365      } catch (Throwable JavaDoc e) {
1366        throw new RuntimeException JavaDoc(e);
1367      }
1368    }
1369  }
1370
1371  public static class KeyComparator
1372    implements Comparator<Map.Entry<Value,Value>>
1373  {
1374    public static final KeyComparator CMP = new KeyComparator();
1375    
1376    private KeyComparator()
1377    {
1378    }
1379    
1380    public int compare(Map.Entry<Value,Value> aEntry,
1381                       Map.Entry<Value,Value> bEntry)
1382    {
1383      try {
1384        Value aKey = aEntry.getKey();
1385        Value bKey = bEntry.getKey();
1386
1387        if (aKey.eq(bKey))
1388          return 0;
1389        else if (aKey.lt(bKey))
1390          return -1;
1391        else
1392          return 1;
1393      } catch (Throwable JavaDoc e) {
1394        throw new RuntimeException JavaDoc(e);
1395      }
1396    }
1397  }
1398
1399  public static abstract class AbstractGet {
1400    public abstract Value get(Map.Entry<Value, Value> entry);
1401  }
1402
1403  public static class GetKey extends AbstractGet
1404  {
1405    public static final GetKey GET = new GetKey();
1406    
1407    private GetKey()
1408    {
1409    }
1410    
1411    public Value get(Map.Entry<Value, Value> entry)
1412    {
1413      return entry.getKey();
1414    }
1415  }
1416
1417  public static class GetValue extends AbstractGet {
1418    public static final GetValue GET = new GetValue();
1419    
1420    private GetValue()
1421    {
1422    }
1423    
1424    public Value get(Map.Entry<Value, Value> entry)
1425    {
1426      return entry.getValue();
1427    }
1428  }
1429}
1430
1431
1432
Popular Tags