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 moduleaermicioi.aedi_property_reader.json.accessor;
31 32 importaermicioi.aedi.configurer.annotation.annotation;
33 importaermicioi.aedi_property_reader.convertor.accessor;
34 importaermicioi.aedi_property_reader.convertor.exception : NotFoundException;
35 importstd.json;
36 importstd.exception;
37 importstd.conv : text, to;
38 importstd.experimental.allocator;
39 importstd.experimental.logger;
40 importaermicioi.aedi_property_reader.convertor.traits : n;
41 42 @component43 @qualifier!(PropertyAccessor!JSONValue)
44 autojsonPropertyAccessor(JsonPropertyAccessorpropertyAccessor, JsonIndexAccessorpropertyIndexer) {
45 returndsl(propertyAccessor, propertyIndexer);
46 }
47 48 @component49 autoruntimeJsonPropertyAccessor(PropertyAccessor!JSONValueaccessor) {
50 returnnewWrappingFieldAccessor!JSONValue(accessor);
51 }
52 53 /**
54 Accessor allowing access through JSONValues that are associative arrays
55 **/56 @component57 classJsonPropertyAccessor : PropertyAccessor!JSONValue {
58 59 /**
60 Get a property out of component
61 62 Params:
63 component = a component which has some properties identified by property.
64 Throws:
65 NotFoundException in case when no requested property is available.
66 InvalidArgumentException in case when passed arguments are somehow invalid for use.
67 Returns:
68 FieldType accessed property.
69 **/70 JSONValueaccess(JSONValuecomponent, instringproperty, RCIAllocatorallocator = theAllocator) const {
71 72 if (this.has(component, property)) {
73 returncomponent.object[property];
74 }
75 76 thrownewNotFoundException(text("${component} doesn't have ${identity}"), property, component.to!string);
77 }
78 79 /**
80 Check if requested property is present in component.
81 82 Check if requested property is present in component.
83 The method could have allocation side effects due to the fact that
84 it is not restricted in calling access method of the accessor.
85 86 Params:
87 component = component which is supposed to have property
88 property = speculated property that is to be tested if it is present in component
89 Returns:
90 true if property is in component
91 **/92 boolhas(inJSONValuecomponent, instringproperty, RCIAllocatorallocator = theAllocator) constnothrow {
93 94 try {
95 96 return (component.type == JSON_TYPE.OBJECT) && ((propertyincomponent.object) !isnull);
97 } catch (Exceptione) {
98 99 debug(trace) error("Failed to check property ", property, " existence in json ", component).n;
100 }
101 102 returnfalse;
103 }
104 105 /**
106 Identify the type of supported component.
107 108 Identify the type of supported component. It returns type info of component
109 if it is supported by accessor, otherwise it will return typeid(void) denoting that
110 the type isn't supported by accessor. The accessor is not limited to returning the type
111 info of passed component, it can actually return type info of super type or any type
112 given the returned type is implicitly convertible or castable to ComponentType.
113 114 Params:
115 component = the component for which accessor should identify the underlying type
116 117 Returns:
118 TypeInfo type information about passed component, or typeid(void) if component is not supported.
119 **/120 TypeInfocomponentType(JSONValuecomponent) constnothrow {
121 returntypeid(JSONValue);
122 }
123 124 }
125 126 /**
127 Accessor allowing access to properties in a JSONValue array
128 **/129 @component130 classJsonIndexAccessor : PropertyAccessor!JSONValue {
131 132 /**
133 Get a property out of component
134 135 Params:
136 component = a component which has some properties identified by property.
137 Throws:
138 NotFoundException in case when no requested property is available.
139 InvalidArgumentException in case when passed arguments are somehow invalid for use.
140 Returns:
141 FieldType accessed property.
142 **/143 JSONValueaccess(JSONValuecomponent, instringproperty, RCIAllocatorallocator = theAllocator) const {
144 145 if (this.has(component, property)) {
146 importstd.conv : to;
147 148 returncomponent.array[property.to!size_t];
149 }
150 151 thrownewNotFoundException(text("${component} doesn't have child on index ${identity}"), property.to!string, component.to!string);
152 }
153 154 /**
155 Check if requested property is present in component.
156 157 Check if requested property is present in component.
158 The method could have allocation side effects due to the fact that
159 it is not restricted in calling access method of the accessor.
160 161 Params:
162 component = component which is supposed to have property
163 property = speculated property that is to be tested if it is present in component
164 Returns:
165 true if property is in component
166 **/167 boolhas(inJSONValuecomponent, instringproperty, RCIAllocatorallocator = theAllocator) constnothrow {
168 169 try {
170 importstd..string : isNumeric;
171 importstd.conv : to;
172 173 return (component.type == JSON_TYPE.ARRAY) &&
174 property.isNumeric && (component.array.length > property.to!size_t);
175 } catch (Exceptione) {
176 177 debug(trace) error("Failed to check indexed property ", property, " existence in json ", component).n;
178 }
179 180 returnfalse;
181 }
182 183 /**
184 Identify the type of supported component.
185 186 Identify the type of supported component. It returns type info of component
187 if it is supported by accessor, otherwise it will return typeid(void) denoting that
188 the type isn't supported by accessor. The accessor is not limited to returning the type
189 info of passed component, it can actually return type info of super type or any type
190 given the returned type is implicitly convertible or castable to ComponentType.
191 192 Params:
193 component = the component for which accessor should identify the underlying type
194 195 Returns:
196 TypeInfo type information about passed component, or typeid(void) if component is not supported.
197 **/198 TypeInfocomponentType(JSONValuecomponent) constnothrow {
199 returntypeid(JSONValue);
200 }
201 }