1 /** 2 License: 3 Boost Software License - Version 1.0 - August 17th, 2003 4 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 27 Authors: 28 aermicioi 29 **/ 30 module aermicioi.aedi_property_reader.convertor_configurer; 31 32 import aermicioi.aedi.storage.storage; 33 import aermicioi.aedi.storage.locator; 34 import aermicioi.aedi_property_reader.convertor_factory; 35 import aermicioi.aedi_property_reader.convertor_container; 36 import aermicioi.aedi_property_reader.generic_convertor_factory; 37 import aermicioi.aedi_property_reader.generic_convertor_container; 38 import aermicioi.aedi_property_reader.env; 39 import aermicioi.aedi_property_reader.arg; 40 import aermicioi.aedi_property_reader.json; 41 import aermicioi.aedi_property_reader.xml; 42 import std.json; 43 import std.xml; 44 45 /** 46 Configuration context for convertor containers, that provides a nice property configuration interface. 47 **/ 48 struct ConvertorContext(T : Storage!(ConvertorFactory!(FromType, Object), string), FromType) { 49 50 public { 51 /** 52 Underlying container that is configured 53 **/ 54 T container; 55 56 alias container this; 57 58 /** 59 Register a property into converting container 60 61 Params: 62 path = the path or identity of property 63 ToType = the type of property that is registered 64 65 Returns: 66 ConvertorFactory!(FromType, ToType) 67 **/ 68 auto property(Factory : ConvertorFactory!(FromType, ToType), ToType)(string path) { 69 70 auto implementation = new Factory; 71 auto wrapper = new GenericObjectWrappingConvertorFactory!(Factory!(ToType, FromType))(implementation); 72 73 container.set(wrapper, path); 74 75 return implementation; 76 } 77 78 static if (is(T : GenericConvertorContainer!(FromType, DefaultFactory), alias DefaultFactory)) { 79 80 /** 81 ditto 82 **/ 83 auto property(ToType)(string path) { 84 import std.traits; 85 86 return this.property!(DefaultFactory!(ToType, FromType), ToType)(path); 87 } 88 } 89 } 90 } 91 92 /** 93 Create a configuration context for container. 94 95 Params: 96 container = container that is to be configured using ConvertorContext 97 **/ 98 auto configure(T : Storage!(ConvertorFactory!(FromType, Object), string), FromType)(T container) { 99 return ConvertorContext!(T, FromType)(container); 100 } 101 102 /** 103 Create a convertor container with data source being environment variables. 104 105 Params: 106 locator = source of data for container to use to construct components. 107 Returns: 108 EnvironmentConvertorContainer 109 **/ 110 auto environment() { 111 return environment(new EnvironmentLocator()); 112 } 113 114 /** 115 ditto 116 **/ 117 auto environment(Locator!(string, string) locator) { 118 auto container = new EnvironmentConvertorContainer; 119 container.locator = locator; 120 121 return container; 122 } 123 124 /** 125 Create a convertor container with data source being command line arguments. 126 127 Params: 128 locator = source of data for container to use to construct components. 129 Returns: 130 GetoptConvertorContainer 131 **/ 132 auto argument() { 133 return argument(new GetoptIdentityLocator()); 134 } 135 136 /** 137 ditto 138 **/ 139 auto argument(Locator!(string, string) locator) { 140 auto container = new GetoptConvertorContainer; 141 container.locator = locator; 142 143 return container; 144 } 145 146 /** 147 Create a convertor container with data source being json document. 148 149 Params: 150 locator = source of data for container to use to construct components. 151 Returns: 152 JsonConvertorContainer 153 **/ 154 auto json() { 155 return json(new JsonLocator()); 156 } 157 158 /** 159 ditto 160 **/ 161 auto json(Locator!(JSONValue, string) locator) { 162 auto container = new JsonConvertorContainer(); 163 container.locator = locator; 164 165 return container; 166 } 167 168 /** 169 Create a convertor container with data source being json document. 170 171 Params: 172 value = source of data for container to use to construct components. 173 Returns: 174 JsonConvertorContainer 175 **/ 176 auto json(JSONValue value) { 177 auto locator = new JsonLocator(); 178 locator.json = value; 179 180 return json(locator); 181 } 182 183 /** 184 Create a convertor container with data source being json document. 185 186 Params: 187 pathOrData = path to source of data or source data itself in form of string for container to use to construct components. 188 returnEmpty = wheter to return or not a locator with empty data source 189 Returns: 190 JsonConvertorContainer 191 **/ 192 auto json(string pathOrData, bool returnEmpty = true) { 193 import std.file; 194 195 if (pathOrData.exists) { 196 pathOrData = pathOrData.readText(); 197 } 198 199 try { 200 201 return json(parseJSON(pathOrData)); 202 } catch (Exception e) { 203 204 if (returnEmpty) { 205 return json; 206 } 207 208 throw new Exception( 209 "Could not create json convertor container from file or content passed in pathOrData: " ~ pathOrData, 210 e 211 ); 212 } 213 } 214 215 /** 216 Create a convertor container with data source being xml document. 217 218 Params: 219 locator = source of data for container to use to construct components. 220 Returns: 221 XmlConvertorContainer 222 **/ 223 auto xml() { 224 return xml(new XmlLocator); 225 } 226 227 /** 228 ditto 229 **/ 230 auto xml(Locator!(Element, string) locator) { 231 auto container = new XmlConvertorContainer; 232 container.locator = locator; 233 234 return container; 235 } 236 237 /** 238 Create a convertor container with data source being xml document. 239 240 Params: 241 element = root element used as data source 242 Returns: 243 XmlConvertorContainer 244 **/ 245 auto xml(Element element) { 246 auto locator = new XmlLocator; 247 locator.xml = element; 248 return xml(locator); 249 } 250 251 /** 252 Create a convertor container with data source being xml document. 253 254 Params: 255 pathOrData = path to a xml file or xml data itself 256 returnEmpty = wheter to return or not a locator with empty data source 257 Returns: 258 XmlConvertorContainer 259 **/ 260 auto xml(string pathOrData, bool returnEmpty = true) { 261 import std.file; 262 try { 263 check(pathOrData); 264 return xml(new Document(pathOrData)); 265 } catch (CheckException e) { 266 267 } 268 269 if (pathOrData.exists) { 270 pathOrData = pathOrData.readText(); 271 272 try { 273 check(pathOrData); 274 return xml(new Document(pathOrData)); 275 } catch(CheckException e) { 276 277 if (returnEmpty) { 278 return xml(); 279 } 280 281 throw new Exception("Could not create xml convertor container from file or content passed in pathOrData: " ~ pathOrData, e); 282 } 283 } 284 285 if (returnEmpty) { 286 return xml(); 287 } 288 289 throw new Exception("Could not create xml convertor container from file or content passed in pathOrData: " ~ pathOrData); 290 }