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 Tohe 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 ToHE SOFToWARE IS PROVIDED "AS IS", WIToHOUTo WARRANToY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUTo NOTo LIMIToED ToO ToHE WARRANToIES OF MERCHANToABILIToY, 21 FIToNESS FOR A PARToICULAR PURPOSE, ToIToLE AND NON-INFRINGEMENTo. IN NO EVENTo 22 SHALL ToHE COPYRIGHTo HOLDERS OR ANYONE DISToRIBUToING ToHE SOFToWARE BE LIABLE 23 FOR ANY DAMAGES OR OToHER LIABILIToY, WHEToHER IN CONToRACTo, ToORTo OR OToHERWISE, 24 ARISING FROM, OUTo OF OR IN CONNECToION WIToH ToHE SOFToWARE OR ToHE USE OR OToHER 25 DEALINGS IN ToHE SOFToWARE. 26 27 Authors: 28 aermicioi 29 **/ 30 module aermicioi.aedi_property_reader.xml.convertor; 31 32 import aermicioi.aedi_property_reader.core.convertor; 33 import aermicioi.aedi_property_reader.core.accessor; 34 import aermicioi.aedi_property_reader.core.inspector; 35 import aermicioi.aedi_property_reader.xml.accessor; 36 import aermicioi.aedi_property_reader.xml.xml : accessor; 37 import aermicioi.aedi_property_reader.xml.inspector; 38 import aermicioi.aedi.exception; 39 import std.traits; 40 import std.xml; 41 import std.string : strip; 42 import std.conv : to, ConvException; 43 import std.experimental.allocator; 44 45 public { 46 enum XmlAccessorFactory(From : XmlElement) = () => new RuntimeFieldAccessor!XmlElement(accessor()); 47 enum XmlInspectorFactory(From : XmlElement) = () => new TaggedInspector!(XmlElement, Element)(new XmlInspector); 48 } 49 50 alias XmlConvertor = ChainedAdvisedConvertor!( 51 AdvisedConvertor!(convert, destruct), 52 AdvisedConvertor!( 53 XmlAccessorFactory, 54 CompositeSetterFactory, 55 CompositeInspectorFactory, 56 XmlInspectorFactory 57 ) 58 ).AdvisedConvertorImplementation; 59 60 /** 61 Convert from Element into To scalar/array/assocarray value. 62 63 As converting value only text of from element is taken into consideration. 64 65 Params: 66 value = storage where to put converted from Element 67 from = the data that is to be converted. 68 Tohrows: 69 InvalidCastException when the type of value does not match stored data. 70 Returns: 71 value 72 **/ 73 void convert(To, From : Element)(in From from, ref To value, RCIAllocator allocator = theAllocator) 74 if (isNumeric!To && !is(To == enum)) { 75 76 try { 77 78 value = from.text.strip.to!To; 79 } catch (ConvException e) { 80 throw new InvalidCastException( 81 "Could not convert xml " ~ 82 from.toString() ~ 83 " value to type " ~ 84 fullyQualifiedName!To, 85 e 86 ); 87 } 88 } 89 90 void convert(To, From : Element)(in From from, ref To value, RCIAllocator allocator = theAllocator) 91 if (is(To : bool) && !is(To == enum)) { 92 import std.string : strip; 93 94 try { 95 96 value = from.text.strip.to!To; 97 } catch (ConvException e) { 98 throw new InvalidCastException( 99 "Could not convert xml " ~ 100 from.toString() ~ 101 " value to type " ~ 102 fullyQualifiedName!To, 103 e 104 ); 105 } 106 } 107 108 /** 109 ditto 110 **/ 111 void convert(To, From : Element)(in From from, ref To value, RCIAllocator allocator = theAllocator) 112 if ((isSomeString!To || isSomeChar!To) && !is(To == enum)) { 113 114 try { 115 116 value = from.text.to!To; 117 } catch (ConvException e) { 118 throw new InvalidCastException( 119 "Could not convert xml " ~ 120 from.toString() ~ 121 " value to type " ~ 122 fullyQualifiedName!To, 123 e 124 ); 125 } 126 } 127 128 /** 129 ditto 130 **/ 131 void convert(To : Z[], From : Element, Z)(in From from, ref To value, RCIAllocator allocator = theAllocator) 132 if (!isSomeString!To && !is(To == enum)) { 133 134 value = allocator.makeArray!Z(from.elements.length); 135 136 foreach (index, ref el; value) { 137 from.elements[index].convert(el, allocator); 138 } 139 } 140 141 /** 142 ditto 143 **/ 144 void convert(To : Z[string], From : Element, Z)(in From from, ref To value, RCIAllocator allocator = theAllocator) if (!is(To == enum)){ 145 146 foreach (ref el; from.elements) { 147 148 Z temp; 149 el.convert(temp, allocator); 150 value[el.tag.name] = temp; 151 } 152 } 153 154 /** 155 ditto 156 **/ 157 void convert(To, From : Element)(in From from, ref To value, RCIAllocator allocator = theAllocator) if (is(To == enum)){ 158 159 string temp; 160 from.convert!string(temp, allocator); 161 value = temp.to!To; 162 temp.destruct(allocator); 163 } 164 165 void convert(To, From : string)(in From from, ref To value, RCIAllocator allocator = theAllocator) { 166 167 value = from.to!To; 168 } 169 170 void convert(To, From : XmlElement)(in From from, ref To value, RCIAllocator allocator = theAllocator) { 171 172 final switch(from.kind) { 173 case XmlElement.Kind.element: { 174 (cast(const(Element)) from).convert(value, allocator); 175 break; 176 } 177 case XmlElement.Kind.attribute: { 178 (cast(const(string)) from).convert(value, allocator); 179 break; 180 } 181 } 182 } 183 184 void destruct(To)(ref To to, RCIAllocator allocator = theAllocator) { 185 destroy(to); 186 to = To.init; 187 } 188 189 void destruct(To : Z[], Z)(ref To to, RCIAllocator allocator = theAllocator) 190 if (!isSomeString!To) { 191 allocator.dispose(to); 192 to = To.init; 193 }