/** * Copyright (C) Zhang,Yuexiang (xfeep) * */ package nginx.clojure.clj; import static nginx.clojure.MiniConstants.NGX_HTTP_CLOJURE_GET_HEADER_FLAG_HEADERS_OUT; import java.util.Iterator; import nginx.clojure.NginxSimpleHandler.SimpleEntry; import nginx.clojure.java.JavaLazyHeaderMap; import clojure.lang.ASeq; import clojure.lang.ArityException; import clojure.lang.Counted; import clojure.lang.IFn; import clojure.lang.IMapEntry; import clojure.lang.IPersistentCollection; import clojure.lang.IPersistentMap; import clojure.lang.ISeq; import clojure.lang.ITransientAssociative; import clojure.lang.ITransientCollection; import clojure.lang.ITransientMap; import clojure.lang.MapEntry; import clojure.lang.Obj; import clojure.lang.PersistentArrayMap; import clojure.lang.RT; import clojure.lang.Util; @SuppressWarnings("unchecked") public class LazyHeaderMap extends JavaLazyHeaderMap implements IPersistentMap, IFn, ITransientAssociative, ITransientMap { public LazyHeaderMap(long r, boolean headersOut) { super(r, headersOut); } @Override public Iterator iterator() { return new Iterator<MapEntry>() { int i = 0; @Override public boolean hasNext() { return i < size -1; } @Override public MapEntry next() { return element(i++); } @Override public void remove() { throw new UnsupportedOperationException("remove not supported now!"); } }; } public MapEntry element(int i) { SimpleEntry se = entry(i); if (se.value != null && se.value.getClass().isArray()) { se.value = RT.seq(se.value); } return new MapEntry(se.key, se.value); } @Override public boolean containsKey(Object keyObj) { String key = NginxClojureHandler.normalizeHeaderNameHelper(keyObj); return super.containsKey(keyObj); } @Override public IMapEntry entryAt(Object key) { Object val = valAt(key); return val == null ? null : new MapEntry(key, val); } @Override public int count() { return size; } @Override public IPersistentCollection cons(Object o) { throw new UnsupportedOperationException("cons not supported now!"); } @Override public IPersistentCollection empty() { //TODO: empty by jni return PersistentArrayMap.EMPTY; } @Override public boolean equiv(Object o) { return o == this; } static class LazyHeaderSeq extends ASeq implements Counted{ LazyHeaderMap h; int i; public LazyHeaderSeq(LazyHeaderMap h, int i) { this.h = h; this.i = i; } @Override public Object first() { return h.element(i); } @Override public ISeq next() { if (i < h.size -1) { return new LazyHeaderSeq(h, i+1); } return null; } @Override public Obj withMeta(IPersistentMap meta) { throw new UnsupportedOperationException("withMeta not supported now!"); } @Override public int count() { return h.size - i; } } @Override public ISeq seq() { return new LazyHeaderSeq(this, 0); } @Override public Object valAt(Object keyObj) { String key = NginxClojureHandler.normalizeHeaderNameHelper(keyObj); Object v = super.get(key); if (v != null && v.getClass().isArray()) { return RT.seq(v); } return v; } @Override public Object valAt(Object key, Object notFound) { Object val = valAt(key); return val == null ? notFound : val; } @Override public LazyHeaderMap assoc(Object key, Object val) { if ( (flag & NGX_HTTP_CLOJURE_GET_HEADER_FLAG_HEADERS_OUT) == 0 ) { throw new UnsupportedOperationException("assoc not supported for read-only request map!"); }else { put(NginxClojureHandler.normalizeHeaderNameHelper(key), val); return this; } } @Override public IPersistentMap assocEx(Object key, Object val) { throw new UnsupportedOperationException("assocEx not supported now!"); } @Override public LazyHeaderMap without(Object key) { if ( (flag & NGX_HTTP_CLOJURE_GET_HEADER_FLAG_HEADERS_OUT) == 0 ) { throw new UnsupportedOperationException("without not supported for read-only request map!"); }else { remove(NginxClojureHandler.normalizeHeaderNameHelper(key)); return this; } } public Object call() { return invoke(); } public void run(){ try { invoke(); } catch(Exception e) { throw Util.sneakyThrow(e); } } public Object invoke() { return throwArity(0); } public Object invoke(Object keyObj) { return valAt(keyObj); } public Object invoke(Object keyObj, Object notFound) { return valAt(keyObj, notFound); } public Object invoke(Object arg1, Object arg2, Object arg3) { return throwArity(3); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) { return throwArity(4); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { return throwArity(5); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { return throwArity(6); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { return throwArity(7); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { return throwArity(8); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { return throwArity(9); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { return throwArity(10); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11) { return throwArity(11); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) { return throwArity(12); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13) { return throwArity(13); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14) { return throwArity(14); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15) { return throwArity(15); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16) { return throwArity(16); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17) { return throwArity(17); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18) { return throwArity(18); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18, Object arg19) { return throwArity(19); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20) { return throwArity(20); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, Object... args) { return throwArity(21); } public Object applyTo(ISeq arglist) { return applyToHelper(this, Util.ret1(arglist,arglist = null)); } static public Object applyToHelper(IFn ifn, ISeq arglist) { switch(RT.boundedLength(arglist, 20)) { case 0: arglist = null; return ifn.invoke(); case 1: return ifn.invoke(Util.ret1(arglist.first(),arglist = null)); case 2: return ifn.invoke(arglist.first() , Util.ret1((arglist = arglist.next()).first(),arglist = null) ); default: throw new RuntimeException("can not take more than 2 args"); } } public Object throwArity(int n){ String name = getClass().getSimpleName(); int suffix = name.lastIndexOf("__"); throw new ArityException(n, (suffix == -1 ? name : name.substring(0, suffix)).replace('_', '-')); } @Override public ITransientCollection conj(Object val) { MapEntry me = (MapEntry)val; assoc(me.key(), me.val()); return this; } @Override public LazyHeaderMap persistent() { return this; } }