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 Alexandru Ermicioi 29 **/ 30 module aermicioi.aedi_property_reader.csv.csv; 31 32 import std.experimental.allocator; 33 import std.experimental.logger; 34 import std.range : array; 35 import aermicioi.aedi.configurer.annotation.annotation; 36 import aermicioi.aedi_property_reader.convertor.convertor; 37 import aermicioi.aedi_property_reader.convertor.accessor; 38 import aermicioi.aedi_property_reader.convertor.setter; 39 import aermicioi.aedi_property_reader.convertor.std_conv; 40 import aermicioi.aedi_property_reader.convertor.inspector; 41 import aermicioi.aedi_property_reader.convertor.type_guesser; 42 import aermicioi.aedi_property_reader.core.document; 43 import aermicioi.aedi_property_reader.core.core; 44 45 alias CsvDocumentContainer = PolicyDocument!( 46 string[string][], 47 string[string], 48 WithContainerScanning!( 49 aermicioi.aedi_property_reader.core.config, 50 )(), 51 WithInitializer!( 52 StdConvStringPrebuiltConvertorsFactory 53 )(), 54 WithContainerScanning!( 55 aermicioi.aedi_property_reader.csv.csv, 56 )(), 57 WithConvertorAggregation!CombinedConvertor(), 58 WithLocatorForUnregisteredComponents("csv-document-locator"), 59 WithDefaultRegisterers 60 ); 61 62 @component 63 auto runtimeCsvTypeGuesser( 64 TypeGuesser!string guesser 65 ) { 66 return new DelegatingObjectTypeGuesser!(string[string], string)( 67 new SimpleTypeGuesser!(string[string])(), 68 guesser 69 ); 70 } 71 72 @component 73 auto propertyAccessor() { 74 return new AssociativeArrayAccessor!(string[string]); 75 } 76 77 @component 78 auto rootAccessor( 79 Convertor defaultConvertor 80 ) { 81 return new KeyConvertingAccessor!(string[string][], string[string], string, size_t)( 82 new ArrayAccessor!(string[string][]), 83 defaultConvertor 84 ); 85 } 86 87 @component 88 auto runtimeEntryAccessor( 89 PropertyAccessor!(string[string], string) propertyAccessor, 90 ) { 91 return new WrappingFieldAccessor!(string[string], string)(propertyAccessor); 92 } 93 94 @component 95 auto runtimeRootPathAccessor( 96 PropertyAccessor!(string[string], string) propertyAccessor, 97 PropertyAccessor!(string[string][], string[string]) rootAccessor, 98 Convertor defaultConvertor 99 ) { 100 auto accessor = new AggregatePropertyAccessor!(Object, Object)( 101 new UnwrappingComponentAccessor!(string[string][], Object)( 102 new WrappingFieldAccessor!(string[string][], string[string])( 103 rootAccessor 104 ) 105 ), 106 new UnwrappingComponentAccessor!(string[string], Object)( 107 new WrappingFieldAccessor!(string[string], string)( 108 propertyAccessor 109 ) 110 ) 111 ); 112 113 return new WrappingComponentAccessor!(string[string][], Object)( 114 dsl( 115 accessor, 116 accessor 117 ) 118 ); 119 } 120 121 /** 122 Create a csv document container 123 124 Params: 125 data = associative array with parsed csv content 126 allocator = allocator used to convert types 127 128 Returns: 129 DocumentContainer!(string[string][], string[string]) 130 **/ 131 auto csv( 132 string[string][] data 133 ) { 134 CsvDocumentContainer container = CsvDocumentContainer(data); 135 136 return container; 137 } 138 139 /** 140 ditto 141 **/ 142 auto csv() { 143 return csv(cast(string[string][]) []); 144 } 145 146 /** 147 Create a csv document container from a csv file or text. 148 149 Params: 150 fileOrData = file path or csv text 151 accessor = accessor used for accessing data 152 allocator = allocator used to convert types 153 returnEmpty = either to return an empty document container if csv file or text is invalid. 154 155 Returns: 156 DocumentContainer!(string[string][], string[string]) 157 **/ 158 auto csv( 159 string fileOrData, 160 bool returnEmpty = true 161 ) { 162 163 import std.file : exists, readText; 164 import std.csv : csvReader, CSVException; 165 166 try { 167 if (fileOrData.exists) { 168 return fileOrData.readText.csvReader!(string[string])(null).array.csv(); 169 } 170 171 return fileOrData.csvReader!(string[string])(null).array.csv(); 172 } catch (CSVException e) { 173 debug(trace) trace("Error parsing csv: ", e); 174 175 if (returnEmpty) { 176 debug(trace) trace("Providing empty container"); 177 return csv(); 178 } 179 180 throw new Exception( 181 "Could not create csv convertor container from file or content passed in pathOrData: " ~ fileOrData, 182 e 183 ); 184 } 185 }