001: /*
002: * filter.java
003: *
004: * Copyright (c) 1997-2007 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 org.pnuts.lib;
010:
011: import pnuts.lang.*;
012: import pnuts.lang.Runtime;
013: import java.util.*;
014: import java.io.*;
015: import java.lang.reflect.Array;
016: import java.lang.ref.SoftReference;
017: import org.pnuts.lang.ConstraintsTransformer;
018: import pnuts.compiler.Compiler;
019:
020: public class filter extends PnutsFunction {
021:
022: public filter() {
023: super ("filter");
024: }
025:
026: public boolean defined(int nargs) {
027: return nargs == 2;
028: }
029:
030: static class MyPnuts extends Pnuts {
031: MyPnuts(SimpleNode n) {
032: this .startNodes = n;
033: }
034: }
035:
036: static PnutsFunction buildFunc(String expr, Context context)
037: throws ParseException {
038: SimpleNode startNode;
039: try {
040: startNode = new PnutsParser(new StringReader(expr))
041: .StartSet(new ParseEnvironment() {
042: public void handleParseException(
043: ParseException e) throws ParseException {
044: throw e;
045: }
046: });
047: } catch (Exception e) {
048: throw new InternalError();
049: }
050: SimpleNode converted = ConstraintsTransformer
051: .buildExpression(startNode);
052: MyPnuts mp = new MyPnuts(converted);
053: Compiler compiler = new Compiler("_filter", false, true);
054: Pnuts compiled = compiler.compile(mp, context);
055: return (PnutsFunction) compiled.run(context);
056: }
057:
058: private final static String FILTER_SYMBOL = "pnuts.lib.filter.condition"
059: .intern();
060:
061: protected Object exec(Object[] args, final Context context) {
062: if (args.length != 2) {
063: undefined(args, context);
064: return null;
065: }
066: Object target = args[0];
067: Object cond = args[1];
068: PnutsFunction func = null;
069:
070: if (cond instanceof PnutsFunction) {
071: func = (PnutsFunction) cond;
072: } else if (cond instanceof String) {
073: try {
074: WeakHashMap whm;
075: synchronized (context) {
076: whm = (WeakHashMap) context.get(FILTER_SYMBOL);
077: if (whm == null) {
078: context.set(FILTER_SYMBOL,
079: whm = new WeakHashMap());
080: }
081: }
082: SoftReference ref = (SoftReference) whm.get(cond);
083: if (ref != null) {
084: func = (PnutsFunction) ref.get();
085: }
086: if (func == null) {
087: func = buildFunc((String) cond, context);
088: whm.put(cond, new SoftReference(func));
089: }
090: } catch (ParseException e) {
091: throw new PnutsException(e, context);
092: }
093: } else {
094: throw new IllegalArgumentException(String.valueOf(cond));
095: }
096:
097: final PnutsFunction function = func;
098:
099: class _Iterator extends FilterIterator {
100: protected _Iterator() {
101: }
102:
103: public _Iterator(Iterator it) {
104: super (it);
105: }
106:
107: protected boolean shouldInclude(Object obj) {
108: return ((Boolean) function.call(new Object[] { obj },
109: context)).booleanValue();
110: }
111: }
112:
113: class _Enumeration extends FilterEnumeration {
114: protected _Enumeration() {
115: }
116:
117: public _Enumeration(Enumeration en) {
118: super (en);
119: }
120:
121: protected boolean shouldInclude(Object obj) {
122: return ((Boolean) function.call(new Object[] { obj },
123: context)).booleanValue();
124: }
125: }
126:
127: class _Map extends FilterMap {
128: protected _Map(Map m, boolean dual) {
129: super (m, dual);
130: }
131:
132: protected boolean shouldInclude(Object key) {
133: return ((Boolean) function.call(new Object[] { key },
134: context)).booleanValue();
135: }
136:
137: protected boolean shouldInclude(Object key, Object value) {
138: return ((Boolean) function.call(new Object[] { key,
139: value }, context)).booleanValue();
140: }
141: }
142:
143: if (target instanceof Iterator) {
144: return new _Iterator((Iterator) target);
145: } else if (target instanceof Enumeration) {
146: return new _Enumeration((Enumeration) target);
147: } else if (target instanceof Collection) {
148: return new _Iterator(((Collection) target).iterator());
149: } else if (target instanceof Object[]) {
150: Object[] array = (Object[]) target;
151: ArrayList lst = new ArrayList();
152: for (int i = 0; i < array.length; i++) {
153: Object elem = array[i];
154: if (((Boolean) function.call(new Object[] { elem },
155: context)).booleanValue()) {
156: lst.add(elem);
157: }
158: }
159: return lst.iterator();
160: } else if (target instanceof Generator) {
161: final Generator g = (Generator) target;
162: return new Generator() {
163: public Object apply(final PnutsFunction closure,
164: final Context context) {
165: return g.apply(new PnutsFunction() {
166: protected Object exec(Object[] a, Context ctx) {
167: if (((Boolean) function.call(a, ctx))
168: .booleanValue()) {
169: closure.call(a, context);
170: }
171: return null;
172: }
173: }, context);
174: }
175: };
176: } else if (Runtime.isArray(target)) {
177: ArrayList lst = new ArrayList();
178: int len = Runtime.getArrayLength(target);
179: for (int i = 0; i < len; i++) {
180: Object elem = Array.get(target, i);
181: if (((Boolean) function.call(new Object[] { elem },
182: context)).booleanValue()) {
183: lst.add(elem);
184: }
185: }
186: return lst.iterator();
187: } else if (target instanceof Map) {
188: if (function.defined(2)) {
189: return new _Map((Map) target, true);
190: } else if (function.defined(1)) {
191: return new _Map((Map) target, false);
192: } else {
193: throw new IllegalArgumentException(String
194: .valueOf(function));
195: }
196: } else {
197: Enumeration e = context.getConfiguration().toEnumeration(
198: target);
199: if (e != null) {
200: return new _Enumeration(e);
201: } else {
202: throw new IllegalArgumentException(String
203: .valueOf(target));
204: }
205: }
206: }
207:
208: public String toString() {
209: return "function filter( (Collection|Iterator|Enumeration|array|Generator|Map) , condition)";
210: }
211: }
|