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.arg.accessor; 31 32 import aermicioi.aedi.configurer.annotation.annotation; 33 import aermicioi.aedi_property_reader.convertor.accessor; 34 import aermicioi.aedi_property_reader.convertor.exception : NotFoundException; 35 import aermicioi.aedi_property_reader.convertor.placeholder; 36 import std.algorithm; 37 import std.array; 38 import std.experimental.allocator; 39 import std..string; 40 import std.conv; 41 import std.range; 42 43 struct ArgumentsHolder { 44 string[][string] byKeyValues; 45 string[string] byKeyValue; 46 string[] byValue; 47 } 48 49 @component 50 class ArgumentAccessor : PropertyAccessor!(ArgumentsHolder, Object) { 51 52 private { 53 PropertyAccessor!(string[][string], string[]) byKeyValuesAccessor; 54 PropertyAccessor!(string[string], string) byKeyValueAccessor; 55 PropertyAccessor!(string[], string) byValueAccessor; 56 } 57 58 @autowired 59 this( 60 PropertyAccessor!(string[][string], string[]) byKeyValuesAccessor, 61 PropertyAccessor!(string[string], string) byKeyValueAccessor, 62 PropertyAccessor!(string[], string) byValueAccessor 63 ) { 64 this.byKeyValuesAccessor = byKeyValuesAccessor; 65 this.byKeyValueAccessor = byKeyValueAccessor; 66 this.byValueAccessor = byValueAccessor; 67 } 68 69 /** 70 Get a property out of component 71 72 Params: 73 component = a component which has some properties identified by property. 74 Throws: 75 NotFoundException in case when no requested property is available. 76 InvalidArgumentException in case when passed arguments are somehow invalid for use. 77 Returns: 78 FieldType accessed property. 79 **/ 80 Object access(ArgumentsHolder component, string property, RCIAllocator allocator = theAllocator) const { 81 if (byValueAccessor.has(component.byValue, property, allocator)) { 82 return this.byValueAccessor.access(component.byValue, property, allocator).pack(allocator); 83 } 84 85 if (byKeyValueAccessor.has(component.byKeyValue, property, allocator)) { 86 return this.byKeyValueAccessor.access(component.byKeyValue, property, allocator).pack(allocator); 87 } 88 89 if (byKeyValuesAccessor.has(component.byKeyValues, property, allocator)) { 90 return this.byKeyValuesAccessor.access(component.byKeyValues, property, allocator).pack(allocator); 91 } 92 93 import std.conv : to; 94 throw new NotFoundException("Can't find property ${property} argument list of ${component}", property, component.to!string); 95 } 96 97 /** 98 Check if requested property is present in component. 99 100 Check if requested property is present in component. 101 The method could have allocation side effects due to the fact that 102 it is not restricted in calling access method of the accessor. 103 104 Params: 105 component = component which is supposed to have property 106 property = speculated property that is to be tested if it is present in component 107 Returns: 108 true if property is in component 109 **/ 110 bool has(ArgumentsHolder component, in string property, RCIAllocator allocator = theAllocator) const nothrow { 111 112 return this.byValueAccessor.has(component.byValue, property, allocator) || 113 this.byKeyValueAccessor.has(component.byKeyValue, property, allocator) || 114 this.byKeyValuesAccessor.has(component.byKeyValues, property, allocator); 115 } 116 117 /** 118 Identify the type of supported component. 119 120 Identify the type of supported component. It returns type info of component 121 if it is supported by accessor, otherwise it will return typeid(void) denoting that 122 the type isn't supported by accessor. The accessor is not limited to returning the type 123 info of passed component, it can actually return type info of super type or any type 124 given the returned type is implicitly convertible or castable to ComponentType. 125 126 Params: 127 component = the component for which accessor should identify the underlying type 128 129 Returns: 130 TypeInfo type information about passed component, or typeid(void) if component is not supported. 131 **/ 132 TypeInfo componentType(ArgumentsHolder component) const nothrow { 133 return typeid(ArgumentsHolder); 134 } 135 }