فهرست منبع

Add ValueMapper class, Mapper interface, and map_through functions

Billy Barrow 1 ماه پیش
والد
کامیت
4aee3a55ac
4فایلهای تغییر یافته به همراه109 افزوده شده و 8 حذف شده
  1. 10 0
      src/lib/Mapper.vala
  2. 16 8
      src/lib/PropertyMapper.vala
  3. 81 0
      src/lib/ValueMapper.vala
  4. 2 0
      src/lib/meson.build

+ 10 - 0
src/lib/Mapper.vala

@@ -0,0 +1,10 @@
+namespace Invercargill {
+
+    public abstract class Mapper<TNative, TElement> {
+
+        public abstract TNative materialise(TElement element) throws Error;
+        public abstract TElement map_from(TNative native) throws Error;
+
+    }
+
+}

+ 16 - 8
src/lib/PropertyMapper.vala

@@ -5,7 +5,7 @@ namespace Invercargill {
     public delegate Tout PropertyGetterTransformer<Tin, Tout>(Tin object);
     public delegate Tout PropertySetterTransformer<Tin, Tout>(Tin object) throws Error;
     public delegate T ObjectConstructor<T>();
-    public class PropertyMapper<T> {
+    public class PropertyMapper<T> : Mapper<T, Properties> {
 
         private Vector<PropertyMapping<T>> mappings;
         private ObjectConstructor<T> constructor;
@@ -37,13 +37,13 @@ namespace Invercargill {
             }
         }
 
-        public T materialise(Properties properties) throws Error {
+        public override T materialise(Properties properties) throws Error {
             var obj = constructor();
             map_into(obj, properties);
             return obj;
         }
 
-        public Properties map_from(T object) {
+        public override Properties map_from(T object) {
             var properties = new PropertiesDictionary();
             foreach (var mapping in mappings) {
                 var val = mapping.getter(object);
@@ -94,11 +94,15 @@ namespace Invercargill {
         }
 
         public PropertyMapperBuilder<T> map_with<TObj>(string name, owned PropertyGetter<T, TObj> getter, owned PropertySetter<T, TObj> setter, PropertyMapper<TObj> mapper, bool mandatory = true) {
+            return map_through<TObj, Properties>(name, getter, setter, mapper, mandatory);
+        }
+
+        public PropertyMapperBuilder<T> map_through<TNative, TElement>(string name, owned PropertyGetter<T, TNative> getter, owned PropertySetter<T, TNative> setter, Mapper<TNative, TElement> mapper, bool mandatory = true) {
             add_mapping(new PropertyMapping<T>() {
                 name = name,
                 mandatory = mandatory,
-                getter = (o) => new NativeElement<Properties>(mapper.map_from(getter(o))),
-                setter = (o,d) => setter(o, mapper.materialise(d.as<Properties>()))
+                getter = (o) => new NativeElement<TElement>(mapper.map_from(getter(o))),
+                setter = (o,d) => setter(o, mapper.materialise(d.as<TElement>()))
             });
             return this;
         }
@@ -114,13 +118,17 @@ namespace Invercargill {
         }
 
         public PropertyMapperBuilder<T> map_many_with<TObj>(string name, owned PropertyGetter<T, Enumerable<TObj>> getter, owned PropertySetter<T, Enumerable<TObj>> setter, PropertyMapper<TObj> mapper, bool mandatory = true) {
+            return map_many_through<TObj, Properties>(name, getter, setter, mapper, mandatory);
+        }
+
+        public PropertyMapperBuilder<T> map_many_through<TNative, TElement>(string name, owned PropertyGetter<T, Enumerable<TNative>> getter, owned PropertySetter<T, Enumerable<TNative>> setter, Mapper<TNative, TElement> mapper, bool mandatory = true) {
             add_mapping(new PropertyMapping<T>() {
                 name = name,
                 mandatory = mandatory,
-                getter = (o) => new NativeElement<Elements>(getter(o).select<Properties>(i => mapper.map_from(i)).to_elements()),
+                getter = (o) => new NativeElement<Elements>(getter(o).select<TElement>(i => mapper.map_from(i)).to_elements()),
                 setter = (o,d) => {
-                    var collection = new Series<TObj>();
-                    foreach (var properties in d.as<Elements>().elements_as<Properties>()) {
+                    var collection = new Series<TNative>();
+                    foreach (var properties in d.as<Elements>().elements_as<TElement>()) {
                         collection.add(mapper.materialise(properties));
                     }
                     setter(o, collection.seal());

+ 81 - 0
src/lib/ValueMapper.vala

@@ -0,0 +1,81 @@
+
+namespace Invercargill {
+
+    public class ValueMapper<TNative, TElement> : Mapper<TNative, TElement> {
+
+        private Dictionary<TNative, TElement> nte { get; set; }
+        private Dictionary<TElement, TNative> etn { get; set; }
+
+        public override TNative materialise (TElement element) throws IndexError {
+            return etn.get(element);
+        }
+
+        public override TElement map_from (TNative native) throws IndexError {
+            return nte.get(native);
+        }
+
+        public static ValueMapper<TNative, TElement> build_for<TNative, TElement>(Func<ValueMapperBuilder<TNative, TElement>> func) {
+            int location = (int)func;
+            return keyed_once<ValueMapper<TNative, TElement>>(location, () => {
+                var builder = new ValueMapperBuilder<TNative, TElement>();
+                func(builder);
+                return builder.build();
+            });
+        }
+
+        internal ValueMapper(ValueMapperBuilder<TNative, TElement> builder) {
+            nte = new Dictionary<TNative, TElement>(builder.native_hash_func, builder.native_equal_func);
+            etn = new Dictionary<TElement, TNative>(builder.element_hash_func, builder.element_equal_func);
+
+            foreach (var item in builder.mappings) {
+                nte.set(item.native, item.element);
+                etn.set(item.element, item.native);
+            }
+        }
+
+    }
+
+    private class ValueMapping<TNative, TElement> {
+        public TNative native { get; set; }
+        public TElement element { get; set; }
+    }
+
+    public class ValueMapperBuilder<TNative, TElement> {
+        internal HashFunc<TNative>? native_hash_func = null;
+        internal EqualFunc<TNative>? native_equal_func = null;
+
+        internal HashFunc<TElement>? element_hash_func = null;
+        internal EqualFunc<TElement>? element_equal_func = null;
+
+        internal Vector<ValueMapping<TNative, TElement>> mappings = new Vector<ValueMapping<TNative, TElement>>();
+
+        public ValueMapperBuilder<TNative, TElement> map(TNative native, TElement element) {
+            mappings.add(new ValueMapping<TNative, TElement> (){
+                native = native,
+                element = element
+            });
+
+            return this;
+        }
+
+        public ValueMapperBuilder<TNative, TElement> with_native_equality(EqualFunc<TNative> eq, HashFunc<TNative>? hash = null) {
+            native_equal_func = eq;
+            native_hash_func = hash;
+            return this;
+        }
+
+        public ValueMapperBuilder<TNative, TElement> with_element_equality(EqualFunc<TNative> eq, HashFunc<TNative>? hash = null) {
+            element_equal_func = eq;
+            element_hash_func = hash;
+            return this;
+        }
+
+        public ValueMapper<TNative, TElement> build() {
+            return new ValueMapper<TNative, TElement>(this);
+        }
+
+
+        
+    }
+
+}

+ 2 - 0
src/lib/meson.build

@@ -21,7 +21,9 @@ sources += files('Grouping.vala')
 sources += files('Interfaces.vala')
 sources += files('Element.vala')
 sources += files('Converter.vala')
+sources += files('Mapper.vala')
 sources += files('PropertyMapper.vala')
+sources += files('ValueMapper.vala')
 sources += files('KeyValuePair.vala')
 sources += files('Attempt.vala')
 sources += files('Cache.vala')