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.xml.xml; 31 32 import aermicioi.aedi : qualifier, component, lref; 33 import aermicioi.aedi.storage.storage; 34 import aermicioi.aedi.storage.locator; 35 import aermicioi.aedi_property_reader.xml.accessor; 36 import aermicioi.aedi_property_reader.xml.convertor; 37 import aermicioi.aedi_property_reader.convertor.accessor; 38 import aermicioi.aedi_property_reader.convertor.convertor; 39 import aermicioi.aedi_property_reader.convertor.chaining_convertor : ByTypePricingStrategy; 40 import aermicioi.aedi_property_reader.convertor.type_guesser; 41 import aermicioi.aedi_property_reader.core.document; 42 import aermicioi.aedi_property_reader.core.core; 43 import aermicioi.aedi_property_reader.convertor.std_conv; 44 import aermicioi.aedi_property_reader.xml.type_guesser; 45 import std.experimental.allocator; 46 import std.experimental.logger; 47 import std.xml; 48 import std.traits; 49 50 auto XmlConvertors( 51 XmlConvertor xmlConvertor, 52 CombinedConvertor combined, 53 ) { 54 combined.add(xmlConvertor); 55 }; 56 57 auto XmlArrayConvertors( 58 CombinedConvertor convertor, 59 ByTypePricingStrategy byTypePricingStrategy 60 ) { 61 import std.meta : AliasSeq; 62 63 static foreach (FromType; AliasSeq!(Element[])) { 64 byTypePricingStrategy.add(typeid(FromType), 900); 65 static foreach (ToType; AliasSeq!(ScalarArrayConvertibleTypes, StringArrayConvertibleTypes)) { 66 byTypePricingStrategy.add(typeid(ToType), 900); 67 convertor.add(new RangeToArrayConvertor!(ToType, FromType)(convertor)); 68 } 69 } 70 }; 71 72 alias XmlDocumentContainer = PolicyDocument!( 73 Element, 74 Element, 75 WithContainerScanning!( 76 aermicioi.aedi_property_reader.core.config, 77 )(), 78 WithInitializer!( 79 StdConvStringPrebuiltConvertorsFactory 80 )(), 81 WithConvertorAggregation!CombinedConvertor(), 82 WithContainerScanning!( 83 aermicioi.aedi_property_reader.xml.type_guesser, 84 aermicioi.aedi_property_reader.xml.accessor, 85 aermicioi.aedi_property_reader.xml.inspector, 86 aermicioi.aedi_property_reader.xml.convertor, 87 aermicioi.aedi_property_reader.xml.xml 88 )(), 89 WithLocatorForUnregisteredComponents("xml-document-locator"), 90 WithInitializer!( 91 XmlConvertors 92 )(), 93 WithInitializer!( 94 XmlArrayConvertors 95 )(), 96 WithDefaultRegisterers 97 ); 98 99 /** 100 Create a convertor container with data source being xml document. 101 102 Params: 103 value = source of data for container to use to construct components. 104 accessor = property accessing logic 105 guesser = type guesser based on held xml value 106 allocator = allocator used to allocate converted values 107 Returns: 108 XmlConvertorContainer 109 **/ 110 auto xml(Element value) { 111 112 XmlDocumentContainer container = XmlDocumentContainer(value); 113 114 return container; 115 } 116 117 /** 118 ditto 119 **/ 120 auto xml() { 121 122 return new Document("<root><root>").xml(); 123 } 124 125 126 /** 127 Create a convertor container with data source being xml document. 128 129 Params: 130 pathOrData = path to a xml file or xml data itself 131 returnEmpty = wheter to return or not a locator with empty data source 132 Returns: 133 XmlConvertorContainer 134 **/ 135 auto xml(string pathOrData, bool returnEmpty = true) { 136 import std.experimental.logger : trace; 137 import std.file : exists, readText; 138 debug(trace) trace("Loading xml document from ", pathOrData); 139 140 try { 141 debug(trace) trace("Attempting to parse ", pathOrData, " as xml"); 142 143 check(pathOrData); 144 145 debug(trace) trace("Parsed as xml"); 146 return xml(new Document(pathOrData)); 147 } catch (CheckException e) { 148 149 debug(trace) trace(pathOrData, " is does not contain valid xml due to: ", e); 150 } 151 152 debug(trace) trace("Attempting to parse ", pathOrData, " as xml file"); 153 if (pathOrData.exists) { 154 155 pathOrData = pathOrData.readText(); 156 157 try { 158 check(pathOrData); 159 160 debug(trace) trace("Parsed as xml"); 161 return xml(new Document(pathOrData)); 162 } catch(CheckException e) { 163 164 debug(trace) trace(pathOrData, " does not contain valid xml due to: ", e); 165 if (returnEmpty) { 166 debug(trace) trace("Returning empty document"); 167 return xml(); 168 } 169 170 throw new Exception( 171 "Could not create xml convertor container from file or content passed in pathOrData: " ~ pathOrData, e 172 ); 173 } 174 } 175 176 if (returnEmpty) { 177 return xml(); 178 } 179 180 throw new Exception( 181 "Could not create xml convertor container from file or content passed in pathOrData: " ~ pathOrData 182 ); 183 }