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.storage.storage; 33 import aermicioi.aedi.storage.locator; 34 import aermicioi.aedi_property_reader.xml.accessor; 35 import aermicioi.aedi_property_reader.xml.convertor; 36 import aermicioi.aedi_property_reader.core.accessor; 37 import aermicioi.aedi_property_reader.core.convertor; 38 import aermicioi.aedi_property_reader.core.type_guesser; 39 import aermicioi.aedi_property_reader.core.document; 40 import aermicioi.aedi_property_reader.xml.type_guesser; 41 import std.experimental.allocator; 42 import std.xml; 43 import std.traits; 44 45 alias XmlDocumentContainer = AdvisedDocumentContainer!(XmlElement, XmlElement, XmlConvertor); 46 47 /** 48 Create a convertor container with data source being xml document. 49 50 Params: 51 value = source of data for container to use to construct components. 52 accessor = property accessing logic 53 guesser = type guesser based on held xml value 54 allocator = allocator used to allocate converted values 55 Returns: 56 JsonConvertorContainer 57 **/ 58 auto xml(XmlElement value, PropertyAccessor!XmlElement accessor, TypeGuesser!XmlElement guesser, RCIAllocator allocator = theAllocator) { 59 60 XmlDocumentContainer container = new XmlDocumentContainer(value); 61 container.guesser = guesser; 62 container.accessor = accessor; 63 container.allocator = allocator; 64 65 return container; 66 } 67 68 /** 69 ditto 70 **/ 71 auto xml(XmlElement value, TypeGuesser!XmlElement guesser, RCIAllocator allocator = theAllocator) { 72 73 return value.xml(accessor, guesser, allocator); 74 } 75 76 /** 77 ditto 78 **/ 79 auto xml(XmlElement value, RCIAllocator allocator = theAllocator) { 80 81 auto container = value.xml(accessor, new XmlTypeGuesser(new StringToScalarConvTypeGuesser), allocator); 82 83 static if (is(StringToScalarConvTypeGuesser : StdConvTypeGuesser!(S, Types), S, Types...)) { 84 static foreach (T; Types) { 85 container.set(XmlConvertor!(T, S)(), fullyQualifiedName!T); 86 } 87 } 88 89 return container; 90 } 91 92 /** 93 ditto 94 **/ 95 auto xml(RCIAllocator allocator = theAllocator) { 96 97 return XmlElement(new Document("<root><root>")).xml(allocator); 98 } 99 100 101 /** 102 Create a convertor container with data source being xml document. 103 104 Params: 105 pathOrData = path to a xml file or xml data itself 106 returnEmpty = wheter to return or not a locator with empty data source 107 Returns: 108 XmlConvertorContainer 109 **/ 110 auto xml(string pathOrData, bool returnEmpty = true) { 111 import std.experimental.logger; 112 import std.file; 113 debug(trace) trace("Loading xml document from ", pathOrData); 114 115 try { 116 debug(trace) trace("Attempting to parse ", pathOrData, " as xml"); 117 118 check(pathOrData); 119 120 debug(trace) trace("Parsed as xml"); 121 return xml(XmlElement(new Document(pathOrData))); 122 } catch (CheckException e) { 123 124 debug(trace) trace(pathOrData, " is does not contain valid xml due to: ", e); 125 } 126 127 debug(trace) trace("Attempting to parse ", pathOrData, " as xml file"); 128 if (pathOrData.exists) { 129 130 pathOrData = pathOrData.readText(); 131 132 try { 133 check(pathOrData); 134 135 debug(trace) trace("Parsed as xml"); 136 return xml(XmlElement(new Document(pathOrData))); 137 } catch(CheckException e) { 138 139 debug(trace) trace(pathOrData, " does not contain valid xml due to: ", e); 140 if (returnEmpty) { 141 debug(trace) trace("Returning empty document"); 142 return xml(); 143 } 144 145 throw new Exception("Could not create xml convertor container from file or content passed in pathOrData: " ~ pathOrData, e); 146 } 147 } 148 149 if (returnEmpty) { 150 return xml(); 151 } 152 153 throw new Exception("Could not create xml convertor container from file or content passed in pathOrData: " ~ pathOrData); 154 } 155 156 package auto accessor() { 157 return dsl( 158 new AggregatePropertyAccessor!XmlElement( 159 new TaggedElementPropertyAccessorWrapper!(XmlElement, XmlElementPropertyAccessor)(new XmlElementPropertyAccessor), 160 new TaggedElementPropertyAccessorWrapper!(XmlElement, XmlAttributePropertyAccessor)(new XmlAttributePropertyAccessor), 161 ), 162 new TaggedElementPropertyAccessorWrapper!(XmlElement, XmlElementIndexAccessor)(new XmlElementIndexAccessor) 163 ); 164 }