checkpoint
[sbp.git] / src / edu / berkeley / sbp / bind / Bindable.java
index d045e16..a51996e 100644 (file)
@@ -1,3 +1,5 @@
+// Copyright 2006 all rights reserved; see LICENSE file for BSD-style license
+
 package edu.berkeley.sbp.bind;
 
 import edu.berkeley.sbp.util.*;
@@ -8,6 +10,7 @@ import java.util.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.io.*;
+import java.security.*;
 import static edu.berkeley.sbp.util.Reflection.*;
 
 public abstract class Bindable implements ToJava {
@@ -20,6 +23,12 @@ public abstract class Bindable implements ToJava {
 
     public abstract Annotation[][] getArgAnnotations();
     public abstract String[]       getArgNames();
+    public abstract Class[]        getArgTypes();
+
+    public Binding createBinding() { return new SimpleBinding(); }
+    public Binding createBinding(final int[] map) { return new SimpleBinding(map); }
+    public Binding createBinding(final int[] map, Object prepend) { return new SimpleBinding(map, prepend); }
+
 
     public static Bindable create(Object o) {
         if (o instanceof Class) return new BindableClass((Class)o);
@@ -28,15 +37,18 @@ public abstract class Bindable implements ToJava {
         return null;
     }
 
+    // Subclasses //////////////////////////////////////////////////////////////////////////////
+
     private static class BindableMethod extends Bindable {
         private final Method _method;
         public String toString() { return "BindableMethod["+_method+"]"; }
         public BindableMethod(Method _method) { this._method = _method; }
         public String getSimpleName() { return _method.getName(); }
-        public <A extends Annotation> A getAnnotation(Class<A> c) { return _method.getAnnotation(c); }
+        public <A extends Annotation> A getAnnotation(final Class<A> c) { return _method.getAnnotation(c); }
         public Object impose(Object[] fields) { return Reflection.impose(_method, fields); }
         public Annotation[][] getArgAnnotations() { return _method.getParameterAnnotations(); }
         public String[]       getArgNames() { return new String[_method.getParameterTypes().length]; }
+        public Class[]        getArgTypes() { return _method.getParameterTypes(); }
         public void toJava(StringBuffer sb) {
             sb.append("Bindable.create(");
             sb.append(_method.getDeclaringClass().getName().replace('$','.'));
@@ -52,11 +64,12 @@ public abstract class Bindable implements ToJava {
         private final Constructor _constructor;
         public String toString() { return "BindableConstructor["+_constructor+"]"; }
         public BindableConstructor(Constructor _constructor) { this._constructor = _constructor; }
-        public String getSimpleName() { return _constructor.getName(); }
+        public String getSimpleName() { return _constructor.getDeclaringClass().getSimpleName(); }
         public <A extends Annotation> A getAnnotation(Class<A> c) { return _constructor.getAnnotation(c); }
         public Object impose(Object[] fields) { return Reflection.impose(_constructor, fields); }
         public Annotation[][] getArgAnnotations() { return _constructor.getParameterAnnotations(); }
         public String[]       getArgNames() { return new String[_constructor.getParameterTypes().length]; }
+        public Class[]        getArgTypes() { return _constructor.getParameterTypes(); }
         public void toJava(StringBuffer sb) {
             sb.append("Bindable.create(");
             sb.append(_constructor.getDeclaringClass().getName().replace('$','.'));
@@ -70,12 +83,7 @@ public abstract class Bindable implements ToJava {
         private final Class _class;
         public String toString() { return "BindableClass["+_class+"]"; }
         public BindableClass(Class _class) { this._class = _class; }
-        public String getSimpleName() {
-            String s = _class.getSimpleName();
-            if (s.indexOf('$') != -1)
-                return s.substring(s.indexOf('$')+1);
-            return s;
-        }
+        public String getSimpleName() { return _class.getSimpleName(); }
         public <A extends Annotation> A getAnnotation(Class<A> c) { return (A)_class.getAnnotation(c); }
         public Object impose(Object[] fields) { return Reflection.impose(_class, fields); }
         public Annotation[][] getArgAnnotations() {
@@ -92,6 +100,13 @@ public abstract class Bindable implements ToJava {
                 ret[i] = fields[i].getName();
             return ret;
         }
+        public Class[]       getArgTypes() {
+            Field[] fields = _class.getFields();
+            Class[] ret = new Class[fields.length];
+            for(int i=0; i<fields.length; i++)
+                ret[i] = fields[i].getType();
+            return ret;
+        }
         public void toJava(StringBuffer sb) {
             sb.append("Bindable.create(");
             sb.append(_class.getName().replace('$','.'));
@@ -100,6 +115,8 @@ public abstract class Bindable implements ToJava {
     }
 
 
+    // Helpers //////////////////////////////////////////////////////////////////////////////
+
     private static void appendClassArray(StringBuffer sb, Class[] c) {
         sb.append("new Class[] {");
         for(int i=0; i<c.length; i++) {
@@ -115,4 +132,40 @@ public abstract class Bindable implements ToJava {
         if (!c.isArray()) return c.getName().replace('$','.');
         return makeClass(c.getComponentType())+"[]";
     }
+
+
+    // Creating Bindings //////////////////////////////////////////////////////////////////////////////
+
+    private class SimpleBinding implements Binding, ToJava {
+        private int[] map = null;
+        private Object prepend = null;
+        public SimpleBinding() { }
+        public SimpleBinding(int[] map) { this.map = map; }
+        public SimpleBinding(int[] map, Object prepend) { this.map = map; this.prepend = prepend; }
+
+        public Object invoke(Object[] o) {
+            if (map==null) return impose(o);
+            int max = 0;
+            for(int i=0; i<map.length; i++) max = Math.max(map[i], max);
+            Object[] o2 = new Object[max+1];
+            for(int i=0; i<o.length; i++) o2[map[i]+(prepend==null?0:1)] = o[i];
+            if (prepend != null) o2[0] = prepend;
+            return impose(o2);
+        }
+
+        public void toJava(StringBuffer sb) {
+            Bindable.this.toJava(sb);
+            sb.append(".createBinding(");
+            if (map != null) {
+                sb.append("new int[] {");
+                for(int i=0; i<map.length; i++) {
+                    sb.append(i);
+                    if (i<map.length-1) sb.append(",");
+                }
+                sb.append("}");
+            }
+            sb.append(")");
+        }
+    }
+
 }