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.json.accessor; 31 32 import aermicioi.aedi_property_reader.core.accessor; 33 import aermicioi.aedi.exception.not_found_exception : NotFoundException; 34 import std.json; 35 import std.exception; 36 import std.conv : text; 37 import std.experimental.logger; 38 import aermicioi.aedi_property_reader.core.traits : n; 39 40 /** 41 Accessor allowing access through JSONValues that are associative arrays 42 **/ 43 class JsonPropertyAccessor : PropertyAccessor!JSONValue { 44 45 /** 46 Get a property out of component 47 48 Params: 49 component = a component which has some properties identified by property. 50 Throws: 51 NotFoundException in case when no requested property is available. 52 InvalidArgumentException in case when passed arguments are somehow invalid for use. 53 Returns: 54 FieldType accessed property. 55 **/ 56 JSONValue access(JSONValue component, in string property) const { 57 58 if (this.has(component, property)) { 59 return component.object[property]; 60 } 61 62 throw new NotFoundException(text("Json ", component, " doesn't have ", property)); 63 } 64 65 /** 66 Check if requested property is present in component. 67 68 Check if requested property is present in component. 69 The method could have allocation side effects due to the fact that 70 it is not restricted in calling access method of the accessor. 71 72 Params: 73 component = component which is supposed to have property 74 property = speculated property that is to be tested if it is present in component 75 Returns: 76 true if property is in component 77 **/ 78 bool has(in JSONValue component, in string property) const nothrow { 79 80 try { 81 82 return (component.type == JSON_TYPE.OBJECT) && ((property in component.object) !is null); 83 } catch (Exception e) { 84 85 debug(trace) error("Failed to check property ", property, " existence in json ", component).n; 86 } 87 88 return false; 89 } 90 91 /** 92 Identify the type of supported component. 93 94 Identify the type of supported component. It returns type info of component 95 if it is supported by accessor, otherwise it will return typeid(void) denoting that 96 the type isn't supported by accessor. The accessor is not limited to returning the type 97 info of passed component, it can actually return type info of super type or any type 98 given the returned type is implicitly convertible or castable to ComponentType. 99 100 Params: 101 component = the component for which accessor should identify the underlying type 102 103 Returns: 104 TypeInfo type information about passed component, or typeid(void) if component is not supported. 105 **/ 106 TypeInfo componentType(JSONValue component) const nothrow { 107 return typeid(JSONValue); 108 } 109 110 } 111 112 /** 113 Accessor allowing access to properties in a JSONValue array 114 **/ 115 class JsonIndexAccessor : PropertyAccessor!JSONValue { 116 117 /** 118 Get a property out of component 119 120 Params: 121 component = a component which has some properties identified by property. 122 Throws: 123 NotFoundException in case when no requested property is available. 124 InvalidArgumentException in case when passed arguments are somehow invalid for use. 125 Returns: 126 FieldType accessed property. 127 **/ 128 JSONValue access(JSONValue component, in string property) const { 129 130 if (this.has(component, property)) { 131 import std.conv : to; 132 133 return component.array[property.to!size_t]; 134 } 135 136 throw new NotFoundException(text("Json ", component, " doesn't have child on index ", property)); 137 } 138 139 /** 140 Check if requested property is present in component. 141 142 Check if requested property is present in component. 143 The method could have allocation side effects due to the fact that 144 it is not restricted in calling access method of the accessor. 145 146 Params: 147 component = component which is supposed to have property 148 property = speculated property that is to be tested if it is present in component 149 Returns: 150 true if property is in component 151 **/ 152 bool has(in JSONValue component, in string property) const nothrow { 153 154 try { 155 import std.string : isNumeric; 156 import std.conv : to; 157 158 return (component.type == JSON_TYPE.ARRAY) && property.isNumeric && (component.array.length > property.to!size_t); 159 } catch (Exception e) { 160 161 debug(trace) error("Failed to check indexed property ", property, " existence in json ", component).n; 162 } 163 164 return false; 165 } 166 167 /** 168 Identify the type of supported component. 169 170 Identify the type of supported component. It returns type info of component 171 if it is supported by accessor, otherwise it will return typeid(void) denoting that 172 the type isn't supported by accessor. The accessor is not limited to returning the type 173 info of passed component, it can actually return type info of super type or any type 174 given the returned type is implicitly convertible or castable to ComponentType. 175 176 Params: 177 component = the component for which accessor should identify the underlying type 178 179 Returns: 180 TypeInfo type information about passed component, or typeid(void) if component is not supported. 181 **/ 182 TypeInfo componentType(JSONValue component) const nothrow { 183 return typeid(JSONValue); 184 } 185 }