001: /*
002: * MerlinConfiguration.java
003: *
004: * Copyright (c) 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.lang;
010:
011: import java.lang.reflect.Array;
012: import java.util.Collection;
013: import java.util.Enumeration;
014: import java.util.List;
015: import java.util.Map;
016: import pnuts.lang.Package;
017:
018: /**
019: * This class defines the interface of runtime configuration, such as how to
020: * find method/field candidates, how to get the field value, how to get indexed
021: * elements, and so on. This class also provides the default implementation for
022: * J2SDK1.4 of this interface.
023: *
024: * @see pnuts.lang.Configuration
025: */
026: class MerlinConfiguration extends Java2Configuration {
027:
028: MerlinConfiguration() {
029: }
030:
031: MerlinConfiguration(Class stopClass) {
032: super (stopClass);
033: }
034:
035: public Object getElement(Context context, Object target, Object key) {
036: if (target instanceof Object[]) {
037: if (key instanceof Number) {
038: int idx = ((Number) key).intValue();
039: Object[] array = (Object[]) target;
040: int sz = array.length;
041: if (idx < 0 && idx >= -sz) {
042: idx += sz;
043: }
044: return array[idx];
045: } else if (key instanceof PnutsFunction) {
046: return filterGenerator((Object[]) target,
047: (PnutsFunction) key, context);
048: }
049: } else if (target instanceof Indexed) {
050: if (key instanceof Number) {
051: return ((Indexed) target)
052: .get(((Number) key).intValue());
053: } else if (key instanceof String) {
054: return getBeanProperty(context, target, (String) key);
055: }
056: } else if (target instanceof Package) {
057: return ((Property) target).get(((String) key).intern(),
058: context);
059: } else if (target instanceof Property) {
060: return ((Property) target).get((String) key, context);
061: } else if (target instanceof Map) {
062: return ((Map) target).get(key);
063: } else if (target instanceof Context) {
064: return ((Context) target).get(((String) key).intern());
065: } else if (target instanceof Generator) {
066: if (key instanceof Number) {
067: return generateNth((Generator) target, ((Number) key)
068: .intValue(), context);
069: } else if (key instanceof PnutsFunction) {
070: return filterGenerator((Generator) target,
071: (PnutsFunction) key, context);
072: }
073: } else {
074: if (key instanceof PnutsFunction) {
075: if (target instanceof Collection) {
076: return filterGenerator((Collection) target,
077: (PnutsFunction) key, context);
078: } else if ((target instanceof int[])
079: || (target instanceof byte[])
080: || (target instanceof short[])
081: || (target instanceof char[])
082: || (target instanceof long[])
083: || (target instanceof float[])
084: || (target instanceof double[])
085: || (target instanceof boolean[])) {
086: return filterGenerator((Object) target,
087: (PnutsFunction) key, context);
088: }
089: } else if (key instanceof String) {
090: return getBeanProperty(context, target, (String) key);
091: } else if (key instanceof Number) {
092: int idx = ((Number) key).intValue();
093: if (target instanceof List) {
094: List list = (List) target;
095: int sz = list.size();
096: if (idx < 0 && idx >= -sz) {
097: idx += sz;
098: }
099: return list.get(idx);
100: } else if (target instanceof String) {
101: String s = (String) target;
102: int sz = s.length();
103: if (idx < 0 && idx >= -sz) {
104: idx += sz;
105: }
106: return new Character(s.charAt(idx));
107: } else if (target instanceof CharSequence) {
108: CharSequence s = (CharSequence) target;
109: int sz = s.length();
110: if (idx < 0 && idx >= -sz) {
111: idx += sz;
112: }
113: return new Character(s.charAt(idx));
114: } else if (target instanceof int[]) {
115: int[] array = (int[]) target;
116: int sz = array.length;
117: if (idx < 0 && idx >= -sz) {
118: idx += sz;
119: }
120: return new Integer(array[idx]);
121: } else if (target instanceof byte[]) {
122: byte[] array = (byte[]) target;
123: int sz = array.length;
124: if (idx < 0 && idx >= -sz) {
125: idx += sz;
126: }
127: return new Byte(array[idx]);
128: } else if (target instanceof char[]) {
129: char[] array = (char[]) target;
130: int sz = array.length;
131: if (idx < 0 && idx >= -sz) {
132: idx += sz;
133: }
134: return new Character(array[idx]);
135: } else if (target instanceof float[]) {
136: float[] array = (float[]) target;
137: int sz = array.length;
138: if (idx < 0 && idx >= -sz) {
139: idx += sz;
140: }
141: return new Float(array[idx]);
142: } else if (target instanceof double[]) {
143: double[] array = (double[]) target;
144: int sz = array.length;
145: if (idx < 0 && idx >= -sz) {
146: idx += sz;
147: }
148: return new Double(array[idx]);
149: } else if (target instanceof boolean[]) {
150: boolean[] array = (boolean[]) target;
151: int sz = array.length;
152: if (idx < 0 && idx >= -sz) {
153: idx += sz;
154: }
155: return Boolean.valueOf(array[idx]);
156: } else if (target instanceof long[]) {
157: long[] array = (long[]) target;
158: int sz = array.length;
159: if (idx < 0 && idx >= -sz) {
160: idx += sz;
161: }
162: return new Long(array[idx]);
163: } else if (target instanceof short[]) {
164: short[] array = (short[]) target;
165: int sz = array.length;
166: if (idx < 0 && idx >= -sz) {
167: idx += sz;
168: }
169: return new Short(array[idx]);
170: } else if (target instanceof Map.Entry) {
171: if (idx == 0) {
172: return ((Map.Entry) target).getKey();
173: } else if (idx == 1) {
174: return ((Map.Entry) target).getValue();
175: } else {
176: return null;
177: }
178: }
179: }
180: }
181: if (target == null) {
182: throw new NullPointerException();
183: }
184: throw new PnutsException("illegal argument [key: "
185: + String.valueOf(key) + ", target: " + target + "]",
186: context);
187: }
188:
189: /**
190: * Defines the semantices of an expression like:
191: * <p>
192: *
193: * <pre>
194: * target[idx1..idx2]
195: * </pre>
196: *
197: * </p>
198: *
199: * @param context
200: * the context
201: * @param target
202: * the target object
203: * @param idx1
204: * the start index
205: * @param idx2
206: * the end index, which can be null
207: */
208: public Object getRange(Context context, Object target, Object idx1,
209: Object idx2) {
210: int from = ((Number) idx1).intValue();
211: int to = -1;
212: if (idx2 != null) {
213: to = ((Number) idx2).intValue();
214: }
215: if (target instanceof CharSequence) {
216: CharSequence s = (CharSequence) target;
217: int len = s.length();
218: if (from > len - 1) {
219: return s.subSequence(0, 0);
220: }
221: if (idx2 != null) {
222: if (from > to || to < 0) {
223: return s.subSequence(0, 0);
224: }
225: if (from < 0) {
226: from = 0;
227: }
228: if (to > len - 1) {
229: to = len - 1;
230: }
231: return s.subSequence(from, to + 1);
232: } else {
233: if (from < 0) {
234: from = 0;
235: }
236: return s.subSequence(from, len);
237: }
238: } else if (Runtime.isArray(target)) {
239: Class c = target.getClass().getComponentType();
240: int len = Runtime.getArrayLength(target);
241: if (from > len - 1) {
242: return Array.newInstance(c, 0);
243: }
244: if (idx2 == null) {
245: to = len - 1;
246: } else {
247: if (from > to || to < 0) {
248: return Array.newInstance(c, 0);
249: }
250: if (to > len - 1) {
251: to = len - 1;
252: }
253: }
254: if (from < 0) {
255: from = 0;
256: }
257: int size = to - from + 1;
258: if (size < 0) {
259: size = 0;
260: } else if (from + size > len) {
261: size = len - from;
262: }
263: Object ret = Array.newInstance(c, size);
264: if (size > 0) {
265: System.arraycopy(target, from, ret, 0, size);
266: }
267: return ret;
268: } else if (target instanceof List) {
269: List list = (List) target;
270: try {
271: int size = list.size();
272: if (from < 0) {
273: from = 0;
274: } else if (from > size) {
275: from = size;
276: }
277: if (idx2 == null) {
278: to = size;
279: } else {
280: if (from > to || to < 0) {
281: to = from;
282: } else {
283: to++;
284: if (to > size) {
285: to = size;
286: }
287: }
288: }
289: } catch (Exception e) {
290: // allow size() to throw an exception
291: }
292: return list.subList(from, to);
293: } else if (target instanceof Generator) {
294: if (idx2 != null) {
295: if (from > to || to < 0) {
296: from = -1;
297: to = -1;
298: } else if (from < 0) {
299: from = 0;
300: }
301: } else {
302: to = -1;
303: if (from < 0) {
304: from = 0;
305: }
306: }
307: return new Runtime.RangeGenerator((Generator) target, from,
308: to);
309: } else {
310: throw new PnutsException("illegal.type",
311: new Object[] { target }, context);
312: }
313: }
314:
315: static class CharSequenceEnum implements Enumeration {
316: CharSequence seq;
317:
318: int len;
319:
320: int pos = 0;
321:
322: CharSequenceEnum(CharSequence seq) {
323: this .seq = seq;
324: this .len = seq.length();
325: }
326:
327: public boolean hasMoreElements() {
328: return len > pos;
329: }
330:
331: public Object nextElement() {
332: return new Character(seq.charAt(pos++));
333: }
334: }
335:
336: public Enumeration toEnumeration(Object obj) {
337: Enumeration en = super .toEnumeration(obj);
338: if (en == null) {
339: if (obj instanceof CharSequence) {
340: en = new CharSequenceEnum((CharSequence) obj);
341: }
342: }
343: return en;
344: }
345: }
|