|
@@ -1,7 +1,9 @@
|
|
namespace Invercargill {
|
|
namespace Invercargill {
|
|
|
|
|
|
public delegate TProp PropertyGetter<TClass, TProp>(TClass object);
|
|
public delegate TProp PropertyGetter<TClass, TProp>(TClass object);
|
|
|
|
+ public delegate bool PropertyPredicate<TClass>(TClass object);
|
|
public delegate void PropertySetter<TClass, TProp>(TClass object, TProp value) throws Error;
|
|
public delegate void PropertySetter<TClass, TProp>(TClass object, TProp value) throws Error;
|
|
|
|
+ public delegate void PropertyDefaultSetter<TClass>(TClass object);
|
|
public delegate Tout PropertyGetterTransformer<Tin, Tout>(Tin object);
|
|
public delegate Tout PropertyGetterTransformer<Tin, Tout>(Tin object);
|
|
public delegate Tout PropertySetterTransformer<Tin, Tout>(Tin object) throws Error;
|
|
public delegate Tout PropertySetterTransformer<Tin, Tout>(Tin object) throws Error;
|
|
public delegate T ObjectConstructor<T>();
|
|
public delegate T ObjectConstructor<T>();
|
|
@@ -27,11 +29,16 @@ namespace Invercargill {
|
|
public void map_into(T object, KeyValues<string, Element> properties) throws Error {
|
|
public void map_into(T object, KeyValues<string, Element> properties) throws Error {
|
|
foreach (var mapping in mappings) {
|
|
foreach (var mapping in mappings) {
|
|
var exists = properties.has(mapping.name);
|
|
var exists = properties.has(mapping.name);
|
|
- if(!mapping.mandatory && !exists) {
|
|
|
|
|
|
+ if(mapping.undefined_setter != null && !exists) {
|
|
|
|
+ mapping.undefined_setter(object);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- if(mapping.mandatory && !exists){
|
|
|
|
|
|
+ if(mapping.undefined_setter == null && !exists){
|
|
throw new IndexError.KEY_NOT_FOUND(@"Failed to map into $(typeof(T).name()): Mandatory property \"$(mapping.name)\" was not present in the properties list");
|
|
throw new IndexError.KEY_NOT_FOUND(@"Failed to map into $(typeof(T).name()): Mandatory property \"$(mapping.name)\" was not present in the properties list");
|
|
|
|
+ }
|
|
|
|
+ var element = properties[mapping.name];
|
|
|
|
+ if(element.is_null()) {
|
|
|
|
+
|
|
}
|
|
}
|
|
mapping.setter(object, properties[mapping.name]);
|
|
mapping.setter(object, properties[mapping.name]);
|
|
}
|
|
}
|
|
@@ -46,10 +53,20 @@ namespace Invercargill {
|
|
public override Properties map_from(T object) {
|
|
public override Properties map_from(T object) {
|
|
var properties = new PropertiesDictionary();
|
|
var properties = new PropertiesDictionary();
|
|
foreach (var mapping in mappings) {
|
|
foreach (var mapping in mappings) {
|
|
- var val = mapping.getter(object);
|
|
|
|
- if(mapping.mandatory || !val.is_null()) {
|
|
|
|
- properties[mapping.name] = val;
|
|
|
|
|
|
+ // Check undefined
|
|
|
|
+ if(mapping.undefined_check != null && mapping.undefined_check(object)){
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check null
|
|
|
|
+ if(mapping.null_check != null && mapping.null_check(object)) {
|
|
|
|
+ properties[mapping.name] = new NullElement();
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Assign value
|
|
|
|
+ var val = mapping.getter(object);
|
|
|
|
+ properties[mapping.name] = val;
|
|
}
|
|
}
|
|
return properties;
|
|
return properties;
|
|
}
|
|
}
|
|
@@ -58,9 +75,12 @@ namespace Invercargill {
|
|
|
|
|
|
private class PropertyMapping<T> {
|
|
private class PropertyMapping<T> {
|
|
public string name;
|
|
public string name;
|
|
- public bool mandatory;
|
|
|
|
public PropertyGetter<T, Element> getter;
|
|
public PropertyGetter<T, Element> getter;
|
|
public PropertySetter<T, Element> setter;
|
|
public PropertySetter<T, Element> setter;
|
|
|
|
+ public PropertyPredicate<T>? null_check;
|
|
|
|
+ public PropertyPredicate<T>? undefined_check;
|
|
|
|
+ public PropertyDefaultSetter<T>? null_setter;
|
|
|
|
+ public PropertyDefaultSetter<T>? undefined_setter;
|
|
}
|
|
}
|
|
|
|
|
|
public class PropertyMapperBuilder<T> {
|
|
public class PropertyMapperBuilder<T> {
|
|
@@ -73,58 +93,57 @@ namespace Invercargill {
|
|
constructor = () => Object.new(typeof(T));
|
|
constructor = () => Object.new(typeof(T));
|
|
}
|
|
}
|
|
|
|
|
|
- public PropertyMapperBuilder<T> map<TProp>(string name, owned PropertyGetter<T, TProp> getter, owned PropertySetter<T, TProp> setter, bool mandatory = true) {
|
|
|
|
|
|
+ public virtual PropertyMappingBuilder<T> map<TProp>(string name, owned PropertyGetter<T, TProp> getter, owned PropertySetter<T, TProp> setter) {
|
|
|
|
+ PropertyMapping<T> mapping;
|
|
if(typeof(TProp).is_a(typeof(Element))) {
|
|
if(typeof(TProp).is_a(typeof(Element))) {
|
|
- add_mapping(new PropertyMapping<T>() {
|
|
|
|
|
|
+ mapping = new PropertyMapping<T>() {
|
|
name = name,
|
|
name = name,
|
|
- mandatory = mandatory,
|
|
|
|
getter = (owned)getter,
|
|
getter = (owned)getter,
|
|
- setter = (owned)setter
|
|
|
|
- });
|
|
|
|
|
|
+ setter = (owned)setter,
|
|
|
|
+ };
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- add_mapping(new PropertyMapping<T>() {
|
|
|
|
|
|
+ mapping = new PropertyMapping<T>() {
|
|
name = name,
|
|
name = name,
|
|
- mandatory = mandatory,
|
|
|
|
getter = (o) => new NativeElement<TProp>(getter(o)),
|
|
getter = (o) => new NativeElement<TProp>(getter(o)),
|
|
setter = (o,d) => setter(o, d.as<TProp>())
|
|
setter = (o,d) => setter(o, d.as<TProp>())
|
|
- });
|
|
|
|
|
|
+ };
|
|
}
|
|
}
|
|
- return this;
|
|
|
|
|
|
+ add_mapping(mapping);
|
|
|
|
+ return new PropertyMappingBuilder<T>(this, mapping);
|
|
}
|
|
}
|
|
|
|
|
|
- public PropertyMapperBuilder<T> map_properties_with<TObj>(string name, owned PropertyGetter<T, TObj> getter, owned PropertySetter<T, TObj> setter, PropertyMapper<TObj> mapper, bool mandatory = true) {
|
|
|
|
- return map_with<TObj, Properties>(name, getter, setter, mapper, mandatory);
|
|
|
|
|
|
+ public virtual PropertyMappingBuilder<T> map_properties_with<TObj>(string name, owned PropertyGetter<T, TObj> getter, owned PropertySetter<T, TObj> setter, PropertyMapper<TObj> mapper) {
|
|
|
|
+ return map_with<TObj, Properties>(name, getter, setter, mapper);
|
|
}
|
|
}
|
|
|
|
|
|
- public PropertyMapperBuilder<T> map_with<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>() {
|
|
|
|
|
|
+ public virtual PropertyMappingBuilder<T> map_with<TNative, TElement>(string name, owned PropertyGetter<T, TNative> getter, owned PropertySetter<T, TNative> setter, Mapper<TNative, TElement> mapper) {
|
|
|
|
+ var mapping = new PropertyMapping<T>() {
|
|
name = name,
|
|
name = name,
|
|
- mandatory = mandatory,
|
|
|
|
getter = (o) => new NativeElement<TElement>(mapper.map_from(getter(o))),
|
|
getter = (o) => new NativeElement<TElement>(mapper.map_from(getter(o))),
|
|
setter = (o,d) => setter(o, mapper.materialise(d.as<TElement>()))
|
|
setter = (o,d) => setter(o, mapper.materialise(d.as<TElement>()))
|
|
- });
|
|
|
|
- return this;
|
|
|
|
|
|
+ };
|
|
|
|
+ add_mapping(mapping);
|
|
|
|
+ return new PropertyMappingBuilder<T>(this, mapping);
|
|
}
|
|
}
|
|
|
|
|
|
- public PropertyMapperBuilder<T> map_many<TObj>(string name, owned PropertyGetter<T, Enumerable<TObj>> getter, owned PropertySetter<T, Enumerable<TObj>> setter, bool mandatory = true) {
|
|
|
|
- add_mapping(new PropertyMapping<T>() {
|
|
|
|
|
|
+ public virtual PropertyMappingBuilder<T> map_many<TObj>(string name, owned PropertyGetter<T, Enumerable<TObj>> getter, owned PropertySetter<T, Enumerable<TObj>> setter) {
|
|
|
|
+ var mapping = new PropertyMapping<T>() {
|
|
name = name,
|
|
name = name,
|
|
- mandatory = mandatory,
|
|
|
|
getter = (o) => new NativeElement<Elements>(getter(o).to_elements()),
|
|
getter = (o) => new NativeElement<Elements>(getter(o).to_elements()),
|
|
setter = (o,d) => setter(o, d.as<Elements>().elements_as<TObj>())
|
|
setter = (o,d) => setter(o, d.as<Elements>().elements_as<TObj>())
|
|
- });
|
|
|
|
- return this;
|
|
|
|
|
|
+ };
|
|
|
|
+ add_mapping(mapping);
|
|
|
|
+ return new PropertyMappingBuilder<T>(this, mapping);;
|
|
}
|
|
}
|
|
|
|
|
|
- public PropertyMapperBuilder<T> map_property_groups_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_with<TObj, Properties>(name, getter, setter, mapper, mandatory);
|
|
|
|
|
|
+ public virtual PropertyMappingBuilder<T> map_property_groups_with<TObj>(string name, owned PropertyGetter<T, Enumerable<TObj>> getter, owned PropertySetter<T, Enumerable<TObj>> setter, PropertyMapper<TObj> mapper) {
|
|
|
|
+ return map_many_with<TObj, Properties>(name, getter, setter, mapper);
|
|
}
|
|
}
|
|
|
|
|
|
- public PropertyMapperBuilder<T> map_many_with<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>() {
|
|
|
|
|
|
+ public virtual PropertyMappingBuilder<T> map_many_with<TNative, TElement>(string name, owned PropertyGetter<T, Enumerable<TNative>> getter, owned PropertySetter<T, Enumerable<TNative>> setter, Mapper<TNative, TElement> mapper) {
|
|
|
|
+ var mapping = new PropertyMapping<T>() {
|
|
name = name,
|
|
name = name,
|
|
- mandatory = mandatory,
|
|
|
|
getter = (o) => new NativeElement<Elements>(getter(o).select<TElement>(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) => {
|
|
setter = (o,d) => {
|
|
var collection = new Series<TNative>();
|
|
var collection = new Series<TNative>();
|
|
@@ -133,16 +152,16 @@ namespace Invercargill {
|
|
}
|
|
}
|
|
setter(o, collection.seal());
|
|
setter(o, collection.seal());
|
|
}
|
|
}
|
|
- });
|
|
|
|
- return this;
|
|
|
|
|
|
+ };
|
|
|
|
+ return new PropertyMappingBuilder<T>(this, mapping);;
|
|
}
|
|
}
|
|
|
|
|
|
- public PropertyMapperBuilder<T> set_constructor(ObjectConstructor<T> constructor) {
|
|
|
|
|
|
+ public virtual PropertyMapperBuilder<T> set_constructor(ObjectConstructor<T> constructor) {
|
|
this.constructor = constructor;
|
|
this.constructor = constructor;
|
|
return this;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
|
|
- public PropertyMapper<T> build() {
|
|
|
|
|
|
+ public virtual PropertyMapper<T> build() {
|
|
return new PropertyMapper<T>(mappings, constructor);
|
|
return new PropertyMapper<T>(mappings, constructor);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -151,4 +170,66 @@ namespace Invercargill {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-}
|
|
|
|
|
|
+
|
|
|
|
+ public class PropertyMappingBuilder<T> : PropertyMapperBuilder<T> {
|
|
|
|
+ private PropertyMapperBuilder<T> inner;
|
|
|
|
+ private PropertyMapping<T> mapping;
|
|
|
|
+ internal PropertyMappingBuilder(PropertyMapperBuilder<T> builder, PropertyMapping<T> mapping) {
|
|
|
|
+ inner = builder;
|
|
|
|
+ this.mapping = mapping;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public PropertyMappingBuilder<T> null_when(owned PropertyPredicate<T> predicate) {
|
|
|
|
+ mapping.null_check = predicate;
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public PropertyMappingBuilder<T> undefined_when(owned PropertyPredicate<T> predicate) {
|
|
|
|
+ mapping.undefined_check = predicate;
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public PropertyMappingBuilder<T> when_null(owned PropertyDefaultSetter<T> setter) {
|
|
|
|
+ mapping.null_setter = setter;
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public PropertyMappingBuilder<T> when_undefined(owned PropertyDefaultSetter<T> setter) {
|
|
|
|
+ mapping.undefined_setter = setter;
|
|
|
|
+ return this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override PropertyMappingBuilder<T> map<TProp>(string name, owned PropertyGetter<T, TProp> getter, owned PropertySetter<T, TProp> setter) {
|
|
|
|
+ return inner.map<TProp>(name, (owned)getter, (owned)setter);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override PropertyMappingBuilder<T> map_properties_with<TObj>(string name, owned PropertyGetter<T, TObj> getter, owned PropertySetter<T, TObj> setter, PropertyMapper<TObj> mapper) {
|
|
|
|
+ return inner.map_properties_with<TObj>(name, (owned)getter, (owned)setter, mapper);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override PropertyMappingBuilder<T> map_with<TNative, TElement>(string name, owned PropertyGetter<T, TNative> getter, owned PropertySetter<T, TNative> setter, Mapper<TNative, TElement> mapper) {
|
|
|
|
+ return inner.map_with<TNative, TElement>(name, (owned)getter, (owned)setter, mapper);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override PropertyMappingBuilder<T> map_many<TObj>(string name, owned PropertyGetter<T, Enumerable<TObj>> getter, owned PropertySetter<T, Enumerable<TObj>> setter) {
|
|
|
|
+ return inner.map_many<TObj>(name, (owned)getter, (owned)setter);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override PropertyMappingBuilder<T> map_property_groups_with<TObj>(string name, owned PropertyGetter<T, Enumerable<TObj>> getter, owned PropertySetter<T, Enumerable<TObj>> setter, PropertyMapper<TObj> mapper) {
|
|
|
|
+ return inner.map_property_groups_with<TObj>(name, getter, setter, mapper);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override PropertyMappingBuilder<T> map_many_with<TNative, TElement>(string name, owned PropertyGetter<T, Enumerable<TNative>> getter, owned PropertySetter<T, Enumerable<TNative>> setter, Mapper<TNative, TElement> mapper) {
|
|
|
|
+ return inner.map_many_with<TNative, TElement>(name, (owned)getter, (owned)setter, mapper);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override PropertyMapperBuilder<T> set_constructor(ObjectConstructor<T> constructor) {
|
|
|
|
+ return inner.set_constructor(constructor);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public override PropertyMapper<T> build() {
|
|
|
|
+ return inner.build();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+}
|