changeset 407:7fd9f1b7b878

replace LuanPropertyTable with LuanPropertyMeta
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 29 Apr 2015 13:01:00 -0600
parents 9321a33b9b1c
children 1b38de2b1845
files core/src/luan/Luan.java core/src/luan/LuanProperty.java core/src/luan/LuanPropertyMeta.java core/src/luan/LuanPropertyTable.java core/src/luan/impl/IndexExpr.java core/src/luan/modules/Table.luan core/src/luan/modules/TableLuan.java scripts/build-luan.sh stripe/src/luan/modules/stripe/Stripe.luan stripe/src/luan/modules/stripe/StripeLuan.java web/src/luan/modules/web/HttpServicer.java
diffstat 11 files changed, 179 insertions(+), 243 deletions(-) [+]
line wrap: on
line diff
--- a/core/src/luan/Luan.java	Wed Apr 29 11:24:00 2015 -0600
+++ b/core/src/luan/Luan.java	Wed Apr 29 13:01:00 2015 -0600
@@ -157,9 +157,5 @@
 		return new LuanTableImpl(list);
 	}
 
-	public static LuanTable newPropertyTable() {
-		return new LuanPropertyTable();
-	}
-
 	private Luan() {}  // never
 }
--- a/core/src/luan/LuanProperty.java	Wed Apr 29 11:24:00 2015 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-package luan;
-
-
-public abstract class LuanProperty {
-
-	public abstract Object get();
-
-	// return whether handled.  if not handled, then this object will be replaced
-	public boolean set(Object value) {
-		return false;
-	}
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/src/luan/LuanPropertyMeta.java	Wed Apr 29 13:01:00 2015 -0600
@@ -0,0 +1,65 @@
+package luan;
+
+
+public class LuanPropertyMeta extends LuanMeta implements DeepCloneable<LuanPropertyMeta> {
+	private LuanTable getters;
+	private LuanTable setters;
+
+	private LuanPropertyMeta() {}
+
+	public static LuanPropertyMeta newInstance() {
+		LuanPropertyMeta meta = new LuanPropertyMeta();
+		meta.getters = new LuanTableImpl();
+		meta.setters = new LuanTableImpl();
+		return meta;
+	}
+
+	public LuanTable getters() {
+		return getters;
+	}
+
+	public LuanTable setters() {
+		return setters;
+	}
+
+	@Override public LuanPropertyMeta shallowClone() {
+		return new LuanPropertyMeta();
+	}
+
+	@Override public void deepenClone(LuanPropertyMeta clone,DeepCloner cloner) {
+		clone.getters = cloner.get(getters);
+		clone.setters = cloner.get(setters);
+	}
+
+	@Override public Object __index(LuanState luan,LuanTable tbl,Object key) throws LuanException {
+		Object obj = getters.get(key);
+		if( obj == null )
+			return null;
+		if( !(obj instanceof LuanFunction) )
+			throw luan.exception("get for '"+key+"' isn't a function");
+		LuanFunction fn = (LuanFunction)obj;
+		return luan.call(fn);
+	}
+
+	@Override public boolean canNewindex() {
+		return true;
+	}
+
+	@Override public void __newindex(LuanState luan,LuanTable tbl,Object key,Object value) throws LuanException {
+		Object obj = setters.get(key);
+		if( obj == null )
+			throw luan.exception("can't set property '"+key+"'");
+		if( !(obj instanceof LuanFunction) )
+			throw luan.exception("set for '"+key+"' isn't a function");
+		LuanFunction fn = (LuanFunction)obj;
+		luan.call(fn,new Object[]{value});
+	}
+
+	@Override public LuanTable newMetatable() {
+		LuanTable mt = super.newMetatable();
+		mt.put( "get", getters );
+		mt.put( "set", setters );
+		return mt;
+	}
+
+}
--- a/core/src/luan/LuanPropertyTable.java	Wed Apr 29 11:24:00 2015 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-package luan;
-
-import java.util.Set;
-import java.util.Map;
-import java.util.AbstractMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ArrayList;
-
-
-class LuanPropertyTable extends LuanTableImpl {
-
-	@Override public LuanTableImpl shallowClone() {
-		return new LuanPropertyTable();
-	}
-
-	private Object fixValue(Object obj) {
-		return obj instanceof LuanProperty ? ((LuanProperty)obj).get() : obj;
-	}
-
-	@Override String repr(Set<LuanTableImpl> set,Object obj) {
-		return super.repr(set,fixValue(obj));
-	}
-
-	@Override public Object get(Object key) {
-		return fixValue(super.get(key));
-	}
-
-	@Override public void put(Object key,Object val) {
-		Object v = super.get(key);
-		if( v instanceof LuanProperty ) {
-			LuanProperty lp = (LuanProperty)v;
-			if( lp.set(val) )
-				return;
-		}
-		super.put(key,val);
-	}
-
-	@Override public Iterator<Map.Entry<Object,Object>> iterator() {
-		final Iterator<Map.Entry<Object,Object>> i = super.iterator();
-		return new Iterator<Map.Entry<Object,Object>>() {
-			public boolean hasNext() {
-				return i.hasNext();
-			}
-			public Map.Entry<Object,Object> next() {
-				Map.Entry<Object,Object> entry = i.next();
-				Object v = entry.getValue();
-				if( v instanceof LuanProperty ) {
-					LuanProperty lp = (LuanProperty)v;
-					return new AbstractMap.SimpleEntry<Object,Object>(entry.getKey(),lp.get());
-				}
-				return entry;
-			}
-			public void remove() {
-				i.remove();
-			}
-		};
-	}
-
-	@Override public List<Object> asList() {
-		List<Object> list = super.asList();
-		if( list.isEmpty() )
-			return list;
-		List<Object> rtn = new ArrayList<Object>();
-		for( Object obj : list ) {
-			rtn.add( fixValue(obj) );
-		}
-		return rtn;
-	}
-
-}
--- a/core/src/luan/impl/IndexExpr.java	Wed Apr 29 11:24:00 2015 -0600
+++ b/core/src/luan/impl/IndexExpr.java	Wed Apr 29 13:01:00 2015 -0600
@@ -44,9 +44,11 @@
 			return StringLuan.__index(luan,(String)obj,key);
 		if( obj instanceof byte[] )
 			return BinaryLuan.__index(luan,(byte[])obj,key);
-		Object value = JavaLuan.__index(luan,obj,key);
-		if( value != null )
-			return value;
+		if( obj != null ) {
+			Object value = JavaLuan.__index(luan,obj,key);
+			if( value != null )
+				return value;
+		}
 		throw luan.bit(op1.se()).exception( "attempt to index '"+op1.se().text()+"' (a " + Luan.type(obj) + " value)" );
 	}
 }
--- a/core/src/luan/modules/Table.luan	Wed Apr 29 11:24:00 2015 -0600
+++ b/core/src/luan/modules/Table.luan	Wed Apr 29 13:01:00 2015 -0600
@@ -4,6 +4,7 @@
 clone = TableLuan.clone
 concat = TableLuan.concat
 insert = TableLuan.insert
+new_property_table = TableLuan.new_property_table
 pack = TableLuan.pack
 remove = TableLuan.remove
 sort = TableLuan.sort
--- a/core/src/luan/modules/TableLuan.java	Wed Apr 29 11:24:00 2015 -0600
+++ b/core/src/luan/modules/TableLuan.java	Wed Apr 29 13:01:00 2015 -0600
@@ -11,6 +11,7 @@
 import luan.LuanException;
 import luan.LuanRuntimeException;
 import luan.LuanMethod;
+import luan.LuanPropertyMeta;
 
 
 public final class TableLuan {
@@ -114,4 +115,7 @@
 		return tbl.cloneTable();
 	}
 
+	public static LuanTable new_property_table() {
+		return LuanPropertyMeta.newInstance().newTable();
+	}
 }
--- a/scripts/build-luan.sh	Wed Apr 29 11:24:00 2015 -0600
+++ b/scripts/build-luan.sh	Wed Apr 29 13:01:00 2015 -0600
@@ -59,11 +59,8 @@
 
 cd $LUAN_HOME
 SRC=stripe/src
-CLASSPATH=$LUAN_HOME/core/src:$LUAN_HOME/$SRC
-for i in $LUAN_HOME/stripe/ext/* ; do CLASSPATH=$CLASSPATH:$i ; done
-javac -classpath $CLASSPATH `find $SRC -name *.java`
 cd $SRC
-jar cvf $LUAN_BUILD/luan/jars/luan-stripe-$VERSION.jar `find . -name *.class -o -name *.luan`
+jar cvf $LUAN_BUILD/luan/jars/luan-stripe-$VERSION.jar `find . -name *.luan`
 cp $LUAN_HOME/stripe/ext/* $LUAN_BUILD/luan/jars
 
 cp $LUAN_HOME/scripts/install.sh $LUAN_BUILD/luan
--- a/stripe/src/luan/modules/stripe/Stripe.luan	Wed Apr 29 11:24:00 2015 -0600
+++ b/stripe/src/luan/modules/stripe/Stripe.luan	Wed Apr 29 13:01:00 2015 -0600
@@ -2,7 +2,7 @@
 local Luan = require "luan:Luan"
 local error = Luan.error
 local assert_integer = Luan.assert_integer
-local StripeLuan = require "java:luan.modules.stripe.StripeLuan"
+local Table = require "luan:Table"
 local Stripe = require "java:com.stripe.Stripe"
 local Customer = require "java:com.stripe.model.Customer"
 local Charge = require "java:com.stripe.model.Charge"
@@ -13,14 +13,49 @@
 	Stripe.apiKey = api_key
 end
 
+
+local function customer_table(java_customer)
+
+	local function subscription()
+		local list = java_customer.getSubscriptions().getData()
+		local size = list.size()
+		size <= 1 or error "more than 1 subscription"
+		return size == 1 and list.get(0) or nil
+	end
+
+	local this = Table.new_property_table()
+	local meta = Luan.get_metatable(this)
+
+	meta.get.id = java_customer.getId
+
+	function meta.get.subscription_status()
+		local s = subscription()
+		return s and s.getStatus()
+	end
+
+	return this
+end
+
+
+local function charge_table(java_charge)
+	local this = Table.new_property_table()
+	local meta = Luan.get_metatable(this)
+
+	meta.get.id = java_charge.getId
+	meta.get.amount = java_charge.getAmount
+
+	return this
+end
+
+
 function create_customer(params)
 	local java_customer = Customer.create(params)
-	return StripeLuan.table(java_customer)
+	return customer_table(java_customer)
 end
 
 function retrieve_customer(id)
 	local java_customer = Customer.retrieve(id)
-	return StripeLuan.table(java_customer)
+	return customer_table(java_customer)
 end
 
 function create_charge(params)
@@ -28,5 +63,7 @@
 	params.amount = assert_integer(params.amount)
 	params.currency = params.currency or currency
 	local java_charge = Charge.create(params)
-	return StripeLuan.table(java_charge)
+	return charge_table(java_charge)
 end
+
+-- http://javadox.com/com.stripe/stripe-java/1.2.1/overview-summary.html
--- a/stripe/src/luan/modules/stripe/StripeLuan.java	Wed Apr 29 11:24:00 2015 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-package luan.modules.stripe;
-
-import luan.Luan;
-import luan.LuanTable;
-import luan.LuanProperty;
-import com.stripe.model.Customer;
-import com.stripe.model.Charge;
-import com.stripe.model.Subscription;
-import java.util.List;
-
-
-public final class StripeLuan {
-
-	public static LuanTable table(final Customer customer) {
-
-		LuanTable tbl = Luan.newPropertyTable();
-
-		tbl.put( "id", new LuanProperty() {
-			@Override public Object get() {
-				return customer.getId();
-			}
-		} );
-
-		tbl.put( "subscription_status", new LuanProperty() {
-			@Override public Object get() {
-				Subscription s = getSubscription(customer);
-				return s==null ? null : s.getStatus();
-			}
-		} );
-
-		return tbl;
-	}
-
-	public static LuanTable table(final Charge charge) {
-		LuanTable tbl = Luan.newPropertyTable();
-
-		tbl.put( "id", new LuanProperty() {
-			@Override public Object get() {
-				return charge.getId();
-			}
-		} );
-
-		tbl.put( "amount", new LuanProperty() {
-			@Override public Object get() {
-				return charge.getAmount();
-			}
-/*
-			@Override public boolean set(Object value) {
-				charge.setAmount(check_integer(value));  return true;
-			}
-*/
-		} );
-
-		return tbl;
-	}
-
-	public static Subscription getSubscription(Customer customer) {
-		List<Subscription> list = customer.getSubscriptions().getData();
-		switch(list.size()) {
-		case 0:
-			return null;
-		case 1:
-			return list.get(0);
-		default:
-			throw new RuntimeException("more than 1 subscription");
-		}
-	}
-/*
-	private static Integer check_integer(Object value) {
-		if( value==null )
-			return (Integer)null;
-		Integer i = Luan.asInteger(value);
-		if( i==null )
-			throw new IllegalArgumentException("value must be an integer");
-		return i;
-	}
-*/
-}
-
-// http://javadox.com/com.stripe/stripe-java/1.2.1/overview-summary.html
--- a/web/src/luan/modules/web/HttpServicer.java	Wed Apr 29 11:24:00 2015 -0600
+++ b/web/src/luan/modules/web/HttpServicer.java	Wed Apr 29 13:01:00 2015 -0600
@@ -29,7 +29,7 @@
 import luan.LuanMeta;
 import luan.LuanJavaFunction;
 import luan.LuanExitException;
-import luan.LuanProperty;
+import luan.LuanPropertyMeta;
 import luan.DeepCloner;
 import luan.modules.PackageLuan;
 import luan.modules.IoLuan;
@@ -118,7 +118,8 @@
 	}
 
 	private LuanTable requestTable() throws NoSuchMethodException {
-		LuanTable tbl = Luan.newPropertyTable();
+		LuanPropertyMeta meta = LuanPropertyMeta.newInstance();
+		LuanTable tbl = meta.newTable();
 		tbl.put("java",request);
 		LuanTable parameters = new NameMeta() {
 
@@ -153,29 +154,24 @@
 */
 		}.newTable();
 		tbl.put( "headers", headers );
-		tbl.put( "method", new LuanProperty() { public Object get() {
-			return request.getMethod();
-		} } );
-/*
-		tbl.put( "servlet_path", new LuanProperty() { public Object get() {
-			return request.getServletPath();
-		} } );
-*/
-		tbl.put( "path", new LuanProperty() { public Object get() {
-			return request.getRequestURI();
-		} } );
-		tbl.put( "server_name", new LuanProperty() { public Object get() {
-			return request.getServerName();
-		} } );
-		tbl.put( "url", new LuanProperty() { public Object get() {
-			return getURL(request);
-		} } );
-		tbl.put( "query_string", new LuanProperty() { public Object get() {
-			return getQueryString(request);
-		} } );
-		tbl.put( "remote_address", new LuanProperty() { public Object get() {
-			return request.getRemoteAddr();
-		} } );
+		meta.getters().put( "method", new LuanJavaFunction(
+			HttpServletRequest.class.getMethod( "getMethod" ), request
+		) );
+		meta.getters().put( "path", new LuanJavaFunction(
+			HttpServletRequest.class.getMethod( "getRequestURI" ), request
+		) );
+		meta.getters().put( "server_name", new LuanJavaFunction(
+			HttpServletRequest.class.getMethod( "getServerName" ), request
+		) );
+		meta.getters().put( "url", new LuanJavaFunction(
+			HttpServicer.class.getMethod( "getURL" ), this
+		) );
+		meta.getters().put( "query_string", new LuanJavaFunction(
+			HttpServicer.class.getMethod( "getQueryString" ), this
+		) );
+		meta.getters().put( "remote_address", new LuanJavaFunction(
+			HttpServletRequest.class.getMethod( "getRemoteAddr" ), request
+		) );
 		LuanTable cookies = new LuanMeta() {
 
 			@Override public Object __index(LuanState luan,LuanTable tbl,Object key) {
@@ -227,19 +223,22 @@
 					if( filename == null ) {
 						value = new String(part.getBytes());
 					} else {
-						LuanTable partTbl = Luan.newPropertyTable();
+						LuanPropertyMeta partMeta = LuanPropertyMeta.newInstance();
+						LuanTable partTbl = partMeta.newTable();
 						partTbl.put("filename",filename);
 						partTbl.put("content_type",part.getContentType());
-						partTbl.put( "content", new LuanProperty() { public Object get() {
-							try {
-								InputStream in = part.getInputStream();
-								byte[] content = Utils.readAll(in);
-								in.close();
-								return content;
-							} catch(IOException e) {
-								throw new RuntimeException(e);
+						partMeta.getters().put( "content", new LuanFunction() {
+							@Override public Object call(LuanState luan,Object[] args) throws LuanException {
+								try {
+									InputStream in = part.getInputStream();
+									byte[] content = Utils.readAll(in);
+									in.close();
+									return content;
+								} catch(IOException e) {
+									throw new RuntimeException(e);
+								}
 							}
-						} } );
+						} );
 						value = partTbl;
 					}
 					Object old = parameters.get(name);
@@ -267,7 +266,8 @@
 	}
 
 	private LuanTable responseTable() throws NoSuchMethodException {
-		LuanTable tbl = Luan.newPropertyTable();
+		LuanPropertyMeta meta = LuanPropertyMeta.newInstance();
+		LuanTable tbl = meta.newTable();
 		tbl.put("java",response);
 		add( tbl, "send_redirect", String.class );
 		add( tbl, "send_error", Integer.TYPE, String.class );
@@ -307,37 +307,27 @@
 */
 		}.newTable();
 		tbl.put( "headers", headers );
-		tbl.put( "content_type", new LuanProperty() {
-			@Override public Object get() {
-				return response.getContentType();
-			}
-			@Override public boolean set(Object value) {
-				response.setContentType(string(value));  return true;
-			}
-		} );
-		tbl.put( "character_encoding", new LuanProperty() {
-			@Override public Object get() {
-				return response.getCharacterEncoding();
-			}
-			@Override public boolean set(Object value) {
-				response.setCharacterEncoding(string(value));  return true;
-			}
-		} );
+		meta.getters().put( "content_type", new LuanJavaFunction(
+			HttpServletResponse.class.getMethod( "getContentType" ), response
+		) );
+		meta.setters().put( "content_type", new LuanJavaFunction(
+			HttpServletResponse.class.getMethod( "setContentType", String.class ), response
+		) );
+		meta.getters().put( "character_encoding", new LuanJavaFunction(
+			HttpServletResponse.class.getMethod( "getCharacterEncoding" ), response
+		) );
+		meta.setters().put( "character_encoding", new LuanJavaFunction(
+			HttpServletResponse.class.getMethod( "setCharacterEncoding", String.class ), response
+		) );
 		add( tbl, "text_writer" );
 		add( tbl, "set_cookie", String.class, String.class, Boolean.TYPE, String.class );
 		add( tbl, "remove_cookie", String.class, String.class );
-		tbl.put( "status", new LuanProperty() {
-			@Override public Object get() {
-				return response.getStatus();
-			}
-			@Override public boolean set(Object value) {
-				Integer i = Luan.asInteger(value);
-				if( i==null )
-					throw new IllegalArgumentException("value must be an integer");
-				response.setStatus(i);
-				return true;
-			}
-		} );
+		meta.getters().put( "status", new LuanJavaFunction(
+			HttpServletResponse.class.getMethod( "getStatus" ), response
+		) );
+		meta.setters().put( "status", new LuanJavaFunction(
+			HttpServletResponse.class.getMethod( "setStatus", Integer.TYPE ), response
+		) );
 		return tbl;
 	}
 
@@ -414,6 +404,10 @@
 
 	// static utils
 
+	public String getQueryString() {
+		return getQueryString(request);
+	}
+
 	public static String getQueryString(HttpServletRequest request) {
 		return getQueryString(request,0);
 	}
@@ -445,6 +439,10 @@
 		return queryBuf.toString();
 	}
 
+	public  String getURL() {
+		return getURL(request);
+	}
+
 	public static String getURL(HttpServletRequest request) {
 		return getURL(request,0);
 	}