1 /* 2 Copyright (c) 2013 Andrey Penechko 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license the "Software" to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 // Provides optimized ways to interact with FlexibleObject descendants properties, which have some 30 // built in properties. 31 // 32 // If property name is statically specified and there is built in property with that name then it will be bound to it without looking into property array, 33 // otherwise it will look into property array. This will speed up binding of properties which is accessible at compile time. 34 module anchovy.utils.flexibleobject.flexibleaccess; 35 36 import std.traits : hasMember; 37 import std.variant : Variant; 38 import anchovy.utils.flexibleobject.flexibleobject : FlexibleObject; 39 40 41 private template hasStaticProperty(T, string property) 42 { 43 enum hasStaticProperty = __traits(hasMember, T, property); 44 } 45 46 // ditto 47 static Variant getProperty(string propname, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w) 48 { 49 static if(hasStaticProperty!(FlexibleObjectType, propname)) 50 { 51 return mixin("w."~propname); 52 } 53 else 54 { 55 return w[propname]; 56 } 57 } 58 59 // 60 // 61 // 62 static T getPropertyAs(T)(string propname, FlexibleObject w) 63 { 64 return w[propname].get!T; 65 } 66 67 static T getPropertyAs(T)(string propname, FlexibleObject w, T defaultValue) 68 { 69 if (auto property = propname in (cast(FlexibleObject)w).properties) 70 { 71 return property.get!T; 72 } 73 else 74 { 75 return defaultValue; 76 } 77 } 78 79 // ditto 80 static T getPropertyAs(string propname, T, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w) 81 { 82 static if(hasStaticProperty!(FlexibleObjectType, propname)) 83 { 84 return mixin("w."~propname~".value.get!T"); 85 } 86 else 87 { 88 return w[propname].get!T; 89 } 90 } 91 92 // ditto 93 static T getPropertyAs(string propname, T, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w, T defaultValue) 94 { 95 static if(hasStaticProperty!(FlexibleObjectType, propname)) 96 { 97 return mixin("w."~propname~".value.get!T"); 98 } 99 else 100 { 101 if (auto property = propname in (cast(FlexibleObject)w).properties) 102 { 103 return property.get!T; 104 } 105 else 106 { 107 return defaultValue; 108 } 109 } 110 } 111 112 // 113 // 114 // 115 static T getPropertyAsBase(T)(string propname, FlexibleObject w) 116 { 117 auto property = w[propname]; 118 119 if (property.convertsTo!T) 120 return property.get!T; 121 else 122 return null; 123 } 124 125 // ditto 126 static T getPropertyAsBase(string propname, T, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w) 127 { 128 static if(hasStaticProperty!(FlexibleObjectType, propname)) 129 { 130 auto property = mixin("w."~propname~".value"); 131 132 if (property.convertsTo!T) 133 return property.get!T; 134 else 135 return null; 136 } 137 else 138 { 139 auto property = w[propname]; 140 141 if (property.convertsTo!T) 142 return property.get!T; 143 else 144 return null; 145 } 146 } 147 148 149 // Peek property value 150 static T* peekPropertyAs(T)(string propname, FlexibleObject w) 151 { 152 return w[propname].peek!T; 153 } 154 155 // ditto 156 static T* peekPropertyAs(string propname, T, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w) 157 { 158 static if(hasStaticProperty!(FlexibleObjectType, propname)) 159 { 160 return mixin("w."~propname~".value.peek!T"); 161 } 162 else 163 { 164 return w[propname].peek!T; 165 } 166 } 167 168 // 169 // 170 // 171 static T coercePropertyAs(T)(FlexibleObject w, string propname) 172 { 173 return w[propname].coerce!T; 174 } 175 176 static T coercePropertyAs(T)(FlexibleObject w, string propname, T defaultValue) 177 { 178 if (auto property = propname in (cast(FlexibleObject)w).properties) 179 { 180 return property.value.coerce!T; 181 } 182 else 183 { 184 return defaultValue; 185 } 186 } 187 188 // ditto 189 static T coercePropertyAs(string propname, T, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w) 190 { 191 static if(hasStaticProperty!(FlexibleObjectType, propname)) 192 { 193 return mixin("w."~propname~".value.coerce!T"); 194 } 195 else 196 { 197 return w[propname].coerce!T; 198 } 199 } 200 201 // ditto 202 static T coercePropertyAs(string propname, T, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w, T defaultValue) 203 { 204 static if(hasStaticProperty!(FlexibleObjectType, propname)) 205 { 206 return mixin("w."~propname~".value.coerce!T"); 207 } 208 else 209 { 210 if (auto property = propname in (cast(FlexibleObject)w).properties) 211 { 212 return (*property).value.coerce!T; 213 } 214 else 215 { 216 return defaultValue; 217 } 218 } 219 } 220 221 bool hasProperty(string propname, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w) 222 { 223 return (propname in (cast(FlexibleObject)w).properties) !is null; 224 } 225 226 // 227 // 228 // 229 static void setProperty(ValueType)(FlexibleObject w, string propname, ValueType value) 230 { 231 w[propname] = value; 232 } 233 234 // ditto 235 static void setProperty(string propname, ValueType, FlexibleObjectType : FlexibleObject)(FlexibleObjectType w, ValueType value) 236 { 237 static if(hasStaticProperty!(FlexibleObjectType, propname)) 238 { 239 auto property = mixin("w."~propname); 240 241 static if (is(ValueType:Variant)) 242 { 243 property.value = value; 244 } 245 else 246 { 247 property.value = Variant(value); 248 } 249 } 250 else 251 { 252 static if (is(ValueType:Variant)) 253 { 254 w[propname] = value; 255 } 256 else 257 { 258 w[propname] = Variant(value); 259 } 260 } 261 } 262 263 // Binds property1 to property2. when property2 changes, property1 will be notified. 264 static void bindProperty(T1 : FlexibleObject, T2 : FlexibleObject)(T1 object1, string property1, T2 object2, string property2) 265 { 266 assert(false); 267 } 268 // ditto 269 static void bindProperty(string property1, string property2, T1 : FlexibleObject, T2 : FlexibleObject)(FlexibleObject object1, FlexibleObject object2) 270 { 271 assert(false); 272 } 273 // ditto 274 static void bindProperty(string property2, T1 : FlexibleObject, T2 : FlexibleObject)(FlexibleObject object1, string property1, FlexibleObject object2) 275 { 276 assert(false); 277 } 278 // ditto 279 static void bindProperty(string property1, T1 : FlexibleObject, T2 : FlexibleObject)(FlexibleObject object1, FlexibleObject object2, string property2) 280 { 281 assert(false); 282 }