Переглянути джерело

new: customizable ResolveModel chain in ResolvePattern

Mariusz Sieroń 6 роки тому
батько
коміт
41593596d6

+ 331 - 0
assira/src/main/java/net/ranides/assira/reflection/ResolveModel.java

@@ -0,0 +1,331 @@
+package net.ranides.assira.reflection;
+
+import net.ranides.assira.collection.arrays.NativeArray;
+import net.ranides.assira.generic.SerializableCode;
+import net.ranides.assira.reflection.impl.RCompareUtils;
+import net.ranides.assira.text.StringTraits;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.regex.Matcher;
+
+public abstract class ResolveModel extends SerializableCode {
+
+    private static final long serialVersionUID = 1L;
+
+    public abstract boolean matchesType(IClass<?> that, String name);
+
+    public abstract boolean matches(Object that, String name);
+
+    public abstract Object get(ResolveStatus status, Object that, String name);
+
+    public abstract void set(ResolveStatus status, Object that, String name, Object value);
+
+    public abstract Object replace(ResolveStatus status, Object that, String name, Object value);
+
+    public abstract IClass<?> type(ResolveStatus status, IClass<?> that, String name);
+
+    public static ResolveModel ARRAY = new ResolveModel() {
+        @Override
+        public boolean matches(Object that, String name) {
+            return that != null && that.getClass().isArray() && StringTraits.isNumber(name);
+        }
+
+        @Override
+        public boolean matchesType(IClass<?> that, String name) {
+            return that.attributes().has(IAttribute.ARRAY) && StringTraits.isNumber(name);
+        }
+
+        @Override
+        public Object get(ResolveStatus _s, Object that, String name) {
+            return NativeArray.wrap(that).get(Integer.parseInt(name));
+        }
+
+        @Override
+        public void set(ResolveStatus _s, Object that, String name, Object value) {
+            NativeArray.wrap(that).set(Integer.parseInt(name), value);
+        }
+
+        @Override
+        public Object replace(ResolveStatus _s, Object that, String name, Object value) {
+            return NativeArray.wrap(that).replace(Integer.parseInt(name), value);
+        }
+
+        @Override
+        public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
+            return that.component();
+        }
+    };
+
+    public static ResolveModel LIST = new ResolveModel() {
+        @Override
+        public boolean matches(Object that, String name) {
+            return that instanceof List<?> && StringTraits.isNumber(name);
+        }
+
+        @Override
+        public boolean matchesType(IClass<?> that, String name) {
+            return that != IClass.NULL && RCompareUtils.isRawSuper(IClass.typeinfo(List.class), that) && StringTraits.isNumber(name);
+        }
+
+        @Override
+        public Object get(ResolveStatus _s, Object that, String name) {
+            return ((List<?>) that).get(Integer.parseInt(name));
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public void set(ResolveStatus _s, Object that, String name, Object value) {
+            ((List<Object>) that).set(Integer.parseInt(name), value);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Object replace(ResolveStatus _s, Object that, String name, Object value) {
+            List<Object> list = (List<Object>) that;
+            int index = Integer.parseInt(name);
+            Object prv = list.get(index);
+            list.set(index, value);
+            return prv;
+        }
+
+        @Override
+        public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
+            return that.params().get(0);
+        }
+    };
+
+    public static ResolveModel MAP = new ResolveModel() {
+        @Override
+        public boolean matches(Object that, String _name) {
+            return that instanceof Map<?,?>;
+        }
+
+        @Override
+        public boolean matchesType(IClass<?> that, String _name) {
+            return that!=IClass.NULL && RCompareUtils.isRawSuper(IClass.typeinfo(Map.class), that);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Object get(ResolveStatus status, Object that, String name) {
+            if(!((Map<String,Object>)that).containsKey(name)) {
+                status.error = true;
+            }
+            return ((Map<?,?>)that).get(name);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public void set(ResolveStatus _s, Object that, String name, Object value) {
+            ((Map<String,Object>)that).put(name, value);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Object replace(ResolveStatus _s, Object that, String name, Object value) {
+            return ((Map<String,Object>)that).put(name, value);
+        }
+
+        @Override
+        public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
+            return that.params().get(1);
+        }
+    };
+
+    public static ResolveModel MATCHER = new ResolveModel() {
+        @Override
+        public boolean matches(Object that, String _name) {
+            return that instanceof Matcher;
+        }
+
+        @Override
+        public boolean matchesType(IClass<?> that, String _name) {
+            return that != IClass.NULL && IClass.typeinfo(Matcher.class).isSuper(that);
+        }
+
+        @Override
+        public Object get(ResolveStatus _s, Object that, String name) {
+            if (StringTraits.isNumber(name)) {
+                return ((Matcher) that).group(Integer.parseInt(name));
+            } else {
+                return ((Matcher) that).group(name);
+            }
+        }
+
+        @Override
+        public void set(ResolveStatus _s, Object that, String name, Object value) {
+            throw new UnsupportedOperationException("Matcher is immutable.");
+        }
+
+        @Override
+        public Object replace(ResolveStatus _s, Object that, String name, Object value) {
+            throw new UnsupportedOperationException("Matcher is immutable.");
+        }
+
+        @Override
+        public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
+            return IClass.typeinfo(String.class);
+        }
+    };
+
+    public static ResolveModel CHARS = new ResolveModel() {
+        @Override
+        public boolean matches(Object that, String _name) {
+            return that instanceof CharSequence;
+        }
+
+        @Override
+        public boolean matchesType(IClass<?> that, String _name) {
+            return that != IClass.NULL && IClass.typeinfo(CharSequence.class).isSuper(that);
+        }
+
+        @Override
+        public Object get(ResolveStatus _s, Object that, String name) {
+            return ((CharSequence) that).charAt(Integer.parseInt(name));
+        }
+
+        @Override
+        public void set(ResolveStatus _s, Object that, String name, Object value) {
+            throw new UnsupportedOperationException("CharSequence is immutable.");
+        }
+
+        @Override
+        public Object replace(ResolveStatus _s, Object that, String name, Object value) {
+            throw new UnsupportedOperationException("CharSequence is immutable.");
+        }
+
+        @Override
+        public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
+            return IClass.typeinfo(char.class);
+        }
+    };
+
+    public static ResolveModel BEAN = new ResolveModel() {
+        @Override
+        public boolean matches(Object that, String _name) {
+            return that != null;
+        }
+
+        @Override
+        public boolean matchesType(IClass<?> that, String _name) {
+            return that != IClass.NULL;
+        }
+
+        @Override
+        public Object get(ResolveStatus status, Object that, String name) {
+            BeanModel model = BeanModel.typefor(that);
+            Object v = model.fluent(that).get(name);
+            if (v != null) {
+                return v;
+            }
+            Iterator<IField> f = field(model, name);
+            if (f.hasNext()) {
+                return f.next().accessible().get(that);
+            }
+            status.error = true;
+            return null;
+        }
+
+        private Iterator<IField> field(BeanModel model, String name) {
+            return model.type().fields().require(IAttribute.ANY).require(name).iterator();
+        }
+
+        @Override
+        public void set(ResolveStatus status, Object that, String name, Object value) {
+            BeanModel model = BeanModel.typefor(that);
+            if (model.properties().containsKey(name)) {
+                model.property(name).get().set(that, value);
+                return;
+            }
+            Iterator<IField> f = field(model, name);
+            if (f.hasNext()) {
+                f.next().accessible().set(that, value);
+                return;
+            }
+            status.error = true;
+        }
+
+        @Override
+        public Object replace(ResolveStatus status, Object that, String name, Object value) {
+            BeanModel model = BeanModel.typefor(that);
+            if (model.properties().containsKey(name)) {
+                return model.property(name).get().replace(that, value);
+            }
+            Iterator<IField> f = field(model, name);
+            if (f.hasNext()) {
+                return f.next().replace(that, value);
+            }
+            status.error = true;
+            return null;
+        }
+
+        @Override
+        public IClass<?> type(ResolveStatus status, IClass<?> that, String name) {
+            BeanModel model = BeanModel.typeinfo(that);
+            if (model.properties().containsKey(name)) {
+                return model.property(name).get().type();
+            }
+            Iterator<IField> f = field(model, name);
+            if (f.hasNext()) {
+                return f.next().type();
+            }
+            status.error = true;
+            return null;
+        }
+    };
+
+    protected static final class ResolveStatus {
+
+        public boolean error;
+
+    }
+
+    public static abstract class AbstractGetter<T> extends ResolveModel {
+
+        private final IClass<T> type;
+
+        public AbstractGetter(Class<T> type) {
+            this.type = IClass.typeinfo(type);
+        }
+
+        public abstract Optional<Object> get(T that, String name);
+
+        @Override
+        public boolean matchesType(IClass<?> that, String name) {
+            return type.isSuper(that);
+        }
+
+        @Override
+        public boolean matches(Object that, String name) {
+            return get(null, that, name) != null;
+        }
+
+        @Override
+        public Object get(ResolveStatus _s, Object that, String name) {
+            if(type.isInstance(that)) {
+                return get(type.cast(that), name).orElse(null);
+            }
+            return null;
+        }
+
+        @Override
+        public IClass<?> type(ResolveStatus status, IClass<?> that, String name) {
+            return IClass.typefor(get(status, that, name));
+        }
+
+        @Override
+        public void set(ResolveStatus status, Object that, String name, Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object replace(ResolveStatus status, Object that, String name, Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+
+    }
+}

+ 90 - 0
assira/src/main/java/net/ranides/assira/reflection/ResolveModels.java

@@ -0,0 +1,90 @@
+package net.ranides.assira.reflection;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ResolveModels implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final  ResolveModels DEFAULT = new ResolveModels(new ResolveModel[]{
+            ResolveModel.ARRAY,
+            ResolveModel.LIST,
+            ResolveModel.MAP,
+            ResolveModel.MATCHER,
+            ResolveModel.CHARS,
+            ResolveModel.BEAN
+    });
+
+    private final ResolveModel[] models;
+
+    private ResolveModels(ResolveModel[] models) {
+        this.models = models;
+    }
+
+    public static ResolveModelsBuilder builder() {
+        return new ResolveModelsBuilder();
+    }
+
+    public Object get(ResolveModel.ResolveStatus status, Object that, String name) {
+        for(ResolveModel m : models) {
+            if(m.matches(that, name)) {
+                return m.get(status, that, name);
+            }
+        }
+        status.error = true;
+        return null;
+    }
+
+    public void set(ResolveModel.ResolveStatus status, Object that, String name, Object value) {
+        for(ResolveModel m : models) {
+            if(m.matches(that, name)) {
+                m.set(status, that, name, value);
+                return;
+            }
+        }
+        status.error = true;
+    }
+
+    public Object replace(ResolveModel.ResolveStatus status, Object that, String name, Object value) {
+        for(ResolveModel m : models) {
+            if(m.matches(that, name)) {
+                return m.replace(status, that, name, value);
+            }
+        }
+        status.error = true;
+        return null;
+    }
+
+    public IClass<?> type(ResolveModel.ResolveStatus status, IClass<?> that, String name) {
+        for(ResolveModel m : models) {
+            if(m.matchesType(that, name)) {
+                return m.type(status, that, name);
+            }
+        }
+        status.error = true;
+        return null;
+    }
+
+    public static class ResolveModelsBuilder {
+
+        private final List<ResolveModel> models = new ArrayList<>();
+
+        public ResolveModelsBuilder add(ResolveModels models) {
+            this.models.addAll(Arrays.asList(models.models));
+            return this;
+        }
+
+        public ResolveModelsBuilder add(ResolveModel model) {
+            this.models.add(model);
+            return this;
+        }
+
+        public ResolveModels build() {
+            return new ResolveModels(models.toArray(new ResolveModel[0]));
+        }
+    }
+
+}

+ 29 - 336
assira/src/main/java/net/ranides/assira/reflection/ResolvePattern.java

@@ -9,13 +9,10 @@ package net.ranides.assira.reflection;
 
 import java.io.Serializable;
 import java.util.*;
-import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import net.ranides.assira.collection.arrays.NativeArray;
+
 import net.ranides.assira.generic.SerializationUtils;
 import net.ranides.assira.generic.Wrapper;
-import net.ranides.assira.reflection.impl.RCompareUtils;
-import net.ranides.assira.text.StringTraits;
 import net.ranides.assira.text.StringUtils;
 
 /**
@@ -27,6 +24,8 @@ public class ResolvePattern implements Serializable {
     private static final long serialVersionUID = 1L;
     
     private static final Pattern RE_INDEX = Pattern.compile("\\[([^\\]]+)\\]");
+
+    private final ResolveModels models;
     
     private final ResolveStrategy handler;
     
@@ -34,12 +33,12 @@ public class ResolvePattern implements Serializable {
     
     private final String[] tokens;
     
-    private ResolvePattern(ResolveStrategy handler, String expression) {
-        assert expression != null;
+    private ResolvePattern(ResolveModels models, ResolveStrategy handler, String expression) {
+        this.models = models;
         this.handler = handler;
         String[] array = StringUtils.replace(expression, RE_INDEX, m -> "."+m.group(1)+".").split("\\.");
         this.expression = expression;
-        this.tokens = Arrays.stream(array).filter(p->!p.isEmpty()).toArray(String[]::new);
+        this.tokens = Arrays.stream(array).map(String::trim).filter(p->!p.isEmpty()).toArray(String[]::new);
     }
 
     @Override
@@ -65,27 +64,30 @@ public class ResolvePattern implements Serializable {
     }
     
     public static ResolvePattern compile(String expression) {
-        return new ResolvePattern(ResolveStrategy.THROW, expression);
+        return new ResolvePattern(ResolveModels.DEFAULT, ResolveStrategy.THROW, expression);
     }
     
     public static ResolvePattern compile(ResolveStrategy handler, String expression) {
-        return new ResolvePattern(handler, expression);
+        return new ResolvePattern(ResolveModels.DEFAULT, handler, expression);
     }
-    
-    
+
+    public static ResolvePattern compile(ResolveModels models, ResolveStrategy handler, String expression) {
+        return new ResolvePattern(models, handler, expression);
+    }
+
     public String expression() {
         return expression;
     }
     
     public Object get(Object that) {
-        ResolveStatus status = new ResolveStatus();
+        ResolveModel.ResolveStatus status = new ResolveModel.ResolveStatus();
         for(int i=0,n=tokens.length-1; i<n; i++) {
-            that = iget(status, that, tokens[i]);
+            that = models.get(status, that, tokens[i]);
             if(status.error) {
                 return handler.get(this, tokens[i]);
             }
         }
-        Object out = iget(status, that, tokens[tokens.length-1]);
+        Object out = models.get(status, that, tokens[tokens.length-1]);
         if(status.error) {
             return handler.get(this);
         }
@@ -93,28 +95,28 @@ public class ResolvePattern implements Serializable {
     }
     
     public void set(Object that, Object value) {
-        ResolveStatus status = new ResolveStatus();
+        ResolveModel.ResolveStatus status = new ResolveModel.ResolveStatus();
         for(int i=0,n=tokens.length-1; i<n; i++) {
-            that = iget(status, that, tokens[i]);
+            that = models.get(status, that, tokens[i]);
             if(status.error) {
                 handler.get(this, tokens[i]);
             }
         }
-        iset(status, that, tokens[tokens.length-1], value);
+        models.set(status, that, tokens[tokens.length-1], value);
         if(status.error) {
             handler.set(this);
         }
     }
     
     public Object replace(Object that, Object value) {
-        ResolveStatus status = new ResolveStatus();
+        ResolveModel.ResolveStatus status = new ResolveModel.ResolveStatus();
         for(int i=0,n=tokens.length-1; i<n; i++) {
-            that = iget(status, that, tokens[i]);
+            that = models.get(status, that, tokens[i]);
             if(status.error) {
                 handler.get(this, tokens[i]);
             }
         }
-        Object out = ireplace(status, that, tokens[tokens.length-1], value);
+        Object out = models.replace(status, that, tokens[tokens.length-1], value);
         if(status.error) {
             return handler.replace(this);
         }
@@ -122,15 +124,15 @@ public class ResolvePattern implements Serializable {
     }
     
     public IClass<?> type(Object that) {
-        ResolveStatus status = new ResolveStatus();
+        ResolveModel.ResolveStatus status = new ResolveModel.ResolveStatus();
         IClass<?> type = IClass.typefor(that);
         for(int i=0,n=tokens.length-1; i<n; i++) {
-            type = itype(status, type, tokens[i]);
+            type = models.type(status, type, tokens[i]);
             if(status.error) {
                 return handler.type(this, tokens[i]);
             }
         }
-        IClass<?> out = itype(status, type, tokens[tokens.length-1]);
+        IClass<?> out = models.type(status, type, tokens[tokens.length-1]);
         if(status.error) {
             return handler.type(this);
         }
@@ -140,314 +142,11 @@ public class ResolvePattern implements Serializable {
     public Wrapper<Object> bind(Object that) {
         return new RWrapper(that);
     }
-    
-    private Object iget(ResolveStatus status, Object that, String name) {
-        for(Model m : MODELS) {
-            if(m.matches(that)) {
-                return m.get(status, that, name);
-            }
-        }
-        status.error = true;
-        return null;
-    }
-    
-    private void iset(ResolveStatus status, Object that, String name, Object value) {
-        for(Model m : MODELS) {
-            if(m.matches(that)) {
-                m.set(status, that, name, value);
-                return;
-            }
-        }
-        status.error = true;
-    }
-    
-    private Object ireplace(ResolveStatus status, Object that, String name, Object value) {
-        for(Model m : MODELS) {
-            if(m.matches(that)) {
-                return m.replace(status, that, name, value);
-            }
-        }
-        status.error = true;
-        return null;
-    }
-    
-    private IClass<?> itype(ResolveStatus status, IClass<?> that, String name) {
-        for(Model m : MODELS) {
-            if(m.matchesType(that)) {
-                return m.type(status, that, name);
-            }
-        }
-        status.error = true;
-        return null;
-    }
-    
+
     private Object writeReplace() {
-        return SerializationUtils.proxy(this, handler, expression);
+        return SerializationUtils.proxy(this, models, handler, expression);
     }
-    
-    private static final Model[] MODELS = Model.values();
-    
-    
-    private enum Model {
-        ARRAY(){
-            @Override
-            public boolean matches(Object that) {
-                return that != null && that.getClass().isArray();
-            }
-
-            @Override
-            public boolean matchesType(IClass<?> that) {
-                return that.attributes().has(IAttribute.ARRAY);
-            }
-
-            @Override
-            public Object get(ResolveStatus _s, Object that, String name) {
-                return NativeArray.wrap(that).get(Integer.parseInt(name));
-            }
-
-            @Override
-            public void set(ResolveStatus _s, Object that, String name, Object value) {
-                NativeArray.wrap(that).set(Integer.parseInt(name), value);
-            }
-
-            @Override
-            public Object replace(ResolveStatus _s, Object that, String name, Object value) {
-                return NativeArray.wrap(that).replace(Integer.parseInt(name), value);
-            }
-
-            @Override
-            public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
-                return that.component();
-            }
-        },
-        LIST(){
-            @Override
-            public boolean matches(Object that) {
-                return that instanceof List<?>;
-            }
-
-            @Override
-            public boolean matchesType(IClass<?> that) {
-                return that != IClass.NULL && RCompareUtils.isRawSuper(IClass.typeinfo(List.class), that);
-            }
-
-            @Override
-            public Object get(ResolveStatus _s, Object that, String name) {
-                return ((List<?>) that).get(Integer.parseInt(name));
-            }
-
-            @Override
-            @SuppressWarnings("unchecked")
-            public void set(ResolveStatus _s, Object that, String name, Object value) {
-                ((List<Object>) that).set(Integer.parseInt(name), value);
-            }
-
-            @Override
-            @SuppressWarnings("unchecked")
-            public Object replace(ResolveStatus _s, Object that, String name, Object value) {
-                List<Object> list = (List<Object>) that;
-                int index = Integer.parseInt(name);
-                Object prv = list.get(index);
-                list.set(index, value);
-                return prv;
-            }
-
-            @Override
-            public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
-                return that.params().get(0);
-            }
-        },
-        MAP(){
-            @Override
-            public boolean matches(Object that) {
-                return that instanceof Map<?,?>;
-            }
-
-            @Override
-            public boolean matchesType(IClass<?> that) {
-                return that!=IClass.NULL && RCompareUtils.isRawSuper(IClass.typeinfo(Map.class), that);
-            }
-
-            @Override
-            @SuppressWarnings("unchecked")
-            public Object get(ResolveStatus status, Object that, String name) {
-                if(!((Map<String,Object>)that).containsKey(name)) {
-                    status.error = true;
-                }
-                return ((Map<?,?>)that).get(name);
-            }
-
-            @Override
-            @SuppressWarnings("unchecked")
-            public void set(ResolveStatus _s, Object that, String name, Object value) {
-                ((Map<String,Object>)that).put(name, value);
-            }
-
-            @Override
-            @SuppressWarnings("unchecked")
-            public Object replace(ResolveStatus _s, Object that, String name, Object value) {
-                return ((Map<String,Object>)that).put(name, value);
-            }
-
-            @Override
-            public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
-                return that.params().get(1);
-            }
-        },
-        MATCHER(){
-            @Override
-            public boolean matches(Object that) {
-                return that instanceof Matcher;
-            }
-
-            @Override
-            public boolean matchesType(IClass<?> that) {
-                return that != IClass.NULL && IClass.typeinfo(Matcher.class).isSuper(that);
-            }
-
-            @Override
-            public Object get(ResolveStatus _s, Object that, String name) {
-                if (StringTraits.isNumber(name)) {
-                    return ((Matcher) that).group(Integer.parseInt(name));
-                } else {
-                    return ((Matcher) that).group(name);
-                }
-            }
-
-            @Override
-            public void set(ResolveStatus _s, Object that, String name, Object value) {
-                throw new UnsupportedOperationException("Matcher is immutable.");
-            }
-
-            @Override
-            public Object replace(ResolveStatus _s, Object that, String name, Object value) {
-                throw new UnsupportedOperationException("Matcher is immutable.");
-            }
-
-            @Override
-            public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
-                return IClass.typeinfo(String.class);
-            }
-        },
-        CHARS(){
-            @Override
-            public boolean matches(Object that) {
-                return that instanceof CharSequence;
-            }
-
-            @Override
-            public boolean matchesType(IClass<?> that) {
-                return that != IClass.NULL && IClass.typeinfo(CharSequence.class).isSuper(that);
-            }
-
-            @Override
-            public Object get(ResolveStatus _s, Object that, String name) {
-                return ((CharSequence) that).charAt(Integer.parseInt(name));
-            }
-
-            @Override
-            public void set(ResolveStatus _s, Object that, String name, Object value) {
-                throw new UnsupportedOperationException("CharSequence is immutable.");
-            }
-
-            @Override
-            public Object replace(ResolveStatus _s, Object that, String name, Object value) {
-                throw new UnsupportedOperationException("CharSequence is immutable.");
-            }
-
-            @Override
-            public IClass<?> type(ResolveStatus _s, IClass<?> that, String name) {
-                return IClass.typeinfo(char.class);
-            }
-        },
-        BEAN(){
-            @Override
-            public boolean matches(Object that) {
-                return that != null;
-            }
 
-            @Override
-            public boolean matchesType(IClass<?> that) {
-                return that != IClass.NULL;
-            }
-
-            @Override
-            public Object get(ResolveStatus status, Object that, String name) {
-                BeanModel model = BeanModel.typefor(that);
-                Object v = model.fluent(that).get(name);
-                if (v != null) {
-                    return v;
-                }
-                Iterator<IField> f = field(model, name);
-                if (f.hasNext()) {
-                    return f.next().accessible().get(that);
-                }
-                status.error = true;
-                return null;
-            }
-
-            private Iterator<IField> field(BeanModel model, String name) {
-                return model.type().fields().require(IAttribute.ANY).require(name).iterator();
-            }
-
-            @Override
-            public void set(ResolveStatus status, Object that, String name, Object value) {
-                BeanModel model = BeanModel.typefor(that);
-                if (model.properties().containsKey(name)) {
-                    model.property(name).get().set(that, value);
-                    return;
-                }
-                Iterator<IField> f = field(model, name);
-                if (f.hasNext()) {
-                    f.next().accessible().set(that, value);
-                    return;
-                }
-                status.error = true;
-            }
-
-            @Override
-            public Object replace(ResolveStatus status, Object that, String name, Object value) {
-                BeanModel model = BeanModel.typefor(that);
-                if (model.properties().containsKey(name)) {
-                    return model.property(name).get().replace(that, value);
-                }
-                Iterator<IField> f = field(model, name);
-                if (f.hasNext()) {
-                    return f.next().replace(that, value);
-                }
-                status.error = true;
-                return null;
-            }
-
-            @Override
-            public IClass<?> type(ResolveStatus status, IClass<?> that, String name) {
-                BeanModel model = BeanModel.typeinfo(that);
-                if (model.properties().containsKey(name)) {
-                    return model.property(name).get().type();
-                }
-                Iterator<IField> f = field(model, name);
-                if (f.hasNext()) {
-                    return f.next().type();
-                }
-                status.error = true;
-                return null;
-            }
-        };
-        
-        public abstract boolean matchesType(IClass<?> that);
-        
-        public abstract boolean matches(Object that);
-        
-        public abstract Object get(ResolveStatus status, Object that, String name);
-        
-        public abstract void set(ResolveStatus status, Object that, String name, Object value);
-        
-        public abstract Object replace(ResolveStatus status, Object that, String name, Object value);
-        
-        public abstract IClass<?> type(ResolveStatus status, IClass<?> that, String name);
-        
-    }
-    
     private class RWrapper implements Wrapper<Object> {
         
         private final Object that;
@@ -477,12 +176,6 @@ public class ResolvePattern implements Serializable {
         }
     
     }
-    
-    private static final class ResolveStatus {
-        
-        public boolean error;
-        
-    }
-    
-    
+
+
 }

+ 11 - 2
assira/src/test/java/net/ranides/assira/generic/SerializableCodeTest.java

@@ -9,8 +9,7 @@ import java.io.IOException;
 import java.io.Serializable;
 import java.nio.charset.StandardCharsets;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.*;
 
 public class SerializableCodeTest {
 
@@ -36,6 +35,16 @@ public class SerializableCodeTest {
         assertNotNull(div);
     }
 
+    @Test
+    public void demo2() throws IOException {
+        byte[] div1 = SerializationUtils.write(new Divider2(5));
+        byte[] div2 = SerializationUtils.write(SerializableCode.wrap(new Divider2(5)));
+
+        assertNotNull(div1);
+        assertNotNull(div2);
+        assertArrayEquals(div1, div2);
+    }
+
 
     @Test
     public void fromBytes() throws IOException {

+ 2 - 2
assira/src/test/java/net/ranides/assira/reflection/ResolvePatternTest.java

@@ -150,10 +150,10 @@ public class ResolvePatternTest {
         assertEquals(3, ResolveUtils.get(numbers, "2"));
         assertEquals(3, ResolveUtils.get(numbers, ".[2]"));
 
-        assertThrows(NumberFormatException.class, ()->{
+        assertThrows(ResolveException.class, ()->{
             ResolveUtils.get(numbers, "[q]");
         });
-        assertThrows(NumberFormatException.class, ()->{
+        assertThrows(ResolveException.class, ()->{
             ResolveUtils.get(numbers, "0q");
         });