Skip to content

Commit b8f81ec

Browse files
Various updates in preparation for Version 2.0.0
- Updated the setting implementation - All settings now have a normalizedProperty - Sub-class StringSetting has normalizedProperty and normalizedValue - Role and Permission classes massively simplified. - Added Configuration class for implementing membership and relationship configurations. - Added RelationshipConfiguration which is a persistent configuration which may be resolved from a relationship.
1 parent 864f149 commit b8f81ec

File tree

31 files changed

+1373
-324
lines changed

31 files changed

+1373
-324
lines changed
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
/*
2+
* Copyright 2020-2021 ONIXLabs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.onixlabs.corda.bnms.contract
18+
19+
import io.onixlabs.corda.core.contract.Hashable
20+
import net.corda.core.crypto.SecureHash
21+
import net.corda.core.serialization.CordaSerializable
22+
23+
/**
24+
* Represents a configuration consisting of a set of settings.
25+
*
26+
* @property settings The set of settings in this configuration.
27+
* @property permissions The set of permissions in this configuration.
28+
* @property roles The set of roles in this configuration.
29+
* @property hash The unique hash of all settings in this configuration.
30+
*/
31+
@CordaSerializable
32+
data class Configuration(val settings: Set<Setting<*>> = emptySet()) : Hashable {
33+
34+
val permissions: Set<Permission>
35+
get() = getSettingsByType()
36+
37+
val roles: Set<Role>
38+
get() = getSettingsByType()
39+
40+
override val hash: SecureHash
41+
get() = computeHash()
42+
43+
/**
44+
* Gets all settings by type and optionally by property.
45+
*
46+
* @param V The underlying setting value type.
47+
* @param S the underlying setting type.
48+
* @param settingType The setting type.
49+
* @param valueType The setting's value type.
50+
* @param property The setting's property.
51+
* @param ignoreCase Determines whether to ignore case when filtering by property.
52+
* @return Returns all settings matching the specified type and property.
53+
*/
54+
fun <V, S : Setting<in V>> getSettingsByType(
55+
settingType: Class<S>,
56+
valueType: Class<V>? = null,
57+
property: String? = null,
58+
ignoreCase: Boolean = false
59+
): Set<S> {
60+
val resultsFilteredByType = settings.filterByType(settingType, valueType)
61+
return if (property != null) resultsFilteredByType.filterByProperty(property, ignoreCase).toSet()
62+
else resultsFilteredByType.toSet()
63+
}
64+
65+
/**
66+
* Gets all settings by type and optionally by property.
67+
*
68+
* @param T The underlying [Setting] type.
69+
* @param property The setting's property.
70+
* @param ignoreCase Determines whether to ignore case when filtering by property.
71+
* @return Returns all settings matching the specified type and property.
72+
*/
73+
inline fun <reified T : Setting<*>> getSettingsByType(
74+
property: String? = null,
75+
ignoreCase: Boolean = false
76+
): Set<T> {
77+
val resultsFilteredByType = settings.filterByType<T>()
78+
return if (property != null) resultsFilteredByType.filterByProperty(property, ignoreCase).toSet()
79+
else resultsFilteredByType.toSet()
80+
}
81+
82+
/**
83+
* Gets a single setting by type and optionally by property.
84+
*
85+
* @param T The underlying [Setting] type.
86+
* @param settingType The setting type.
87+
* @param valueType The setting's value type.
88+
* @param property The setting's property.
89+
* @param ignoreCase Determines whether to ignore case when filtering by property.
90+
* @return Returns a single setting matching the specified type and property.
91+
*/
92+
fun <V, S : Setting<in V>> getSettingByType(
93+
settingType: Class<S>,
94+
valueType: Class<V>? = null,
95+
property: String? = null,
96+
ignoreCase: Boolean = false
97+
): S = getSettingsByType(settingType, valueType, property, ignoreCase).single()
98+
99+
/**
100+
* Gets a single setting by type and optionally by property.
101+
*
102+
* @param T The underlying [Setting] type.
103+
* @param property The setting's property.
104+
* @param ignoreCase Determines whether to ignore case when filtering by property.
105+
* @return Returns a single setting matching the specified type and property.
106+
*/
107+
inline fun <reified T : Setting<*>> getSettingByType(
108+
property: String? = null,
109+
ignoreCase: Boolean = false
110+
): T = getSettingsByType<T>(property, ignoreCase).single()
111+
112+
/**
113+
* Gets a single setting by type and optionally by property, or null if no matching setting exists.
114+
*
115+
* @param T The underlying [Setting] type.
116+
* @param settingType The setting type.
117+
* @param valueType The setting's value type.
118+
* @param property The setting's property.
119+
* @param ignoreCase Determines whether to ignore case when filtering by property.
120+
* @return Returns a single setting matching the specified type and property, or null if no matching setting exists.
121+
*/
122+
fun <V, S : Setting<in V>> getSettingByTypeOrNull(
123+
settingType: Class<S>,
124+
valueType: Class<V>? = null,
125+
property: String? = null,
126+
ignoreCase: Boolean = false
127+
): S? = getSettingsByType(settingType, valueType, property, ignoreCase).singleOrNull()
128+
129+
/**
130+
* Gets a single setting by type and optionally by property, or null if no matching setting exists.
131+
*
132+
* @param T The underlying [Setting] type.
133+
* @param property The setting's property.
134+
* @param ignoreCase Determines whether to ignore case when filtering by property.
135+
* @return Returns a single setting matching the specified type and property, or null if no matching setting exists.
136+
*/
137+
inline fun <reified T : Setting<*>> getSettingByTypeOrNull(
138+
property: String? = null,
139+
ignoreCase: Boolean = false
140+
): T? = getSettingsByType<T>(property, ignoreCase).singleOrNull()
141+
142+
/**
143+
* Determines whether the specified setting is contained in this configuration.
144+
*
145+
* @param setting The setting to find in this configuration.
146+
* @return Returns true if the specified setting is contained in this configuration; otherwise, false.
147+
*/
148+
fun hasSetting(setting: Setting<*>): Boolean {
149+
return setting in settings
150+
}
151+
152+
/**
153+
* Determines whether the specified setting is contained in this configuration.
154+
*
155+
* @param property The setting property to find in this configuration.
156+
* @param ignoreCase Determines whether to ignore case when filtering by property.
157+
* @return Returns true if the specified setting is contained in this configuration; otherwise, false.
158+
*/
159+
fun hasSetting(property: String, ignoreCase: Boolean = false): Boolean {
160+
return settings.any { it.property.equals(property, ignoreCase) }
161+
}
162+
163+
/**
164+
* Determines whether the specified role is contained in this configuration.
165+
*
166+
* @param role The role to find in this configuration.
167+
* @return Returns true if the specified role is contained in this configuration; otherwise, false.
168+
*/
169+
fun hasRole(role: Role): Boolean {
170+
return hasSetting(role)
171+
}
172+
173+
/**
174+
* Determines whether the specified role is contained in this configuration.
175+
*
176+
* @param role The role to find in this configuration.
177+
* @return Returns true if the specified role is contained in this configuration; otherwise, false.
178+
*/
179+
fun hasRole(role: String): Boolean {
180+
return roles.any { it.normalizedValue == role.toUpperCase() }
181+
}
182+
183+
/**
184+
* Determines whether the specified permission is contained in this configuration.
185+
*
186+
* @param permission The permission to find in this configuration.
187+
* @return Returns true if the specified permission is contained in this configuration; otherwise, false.
188+
*/
189+
fun hasPermission(permission: Permission): Boolean {
190+
return hasSetting(permission)
191+
}
192+
193+
/**
194+
* Determines whether the specified permission is contained in this configuration.
195+
*
196+
* @param permission The permission to find in this configuration.
197+
* @return Returns true if the specified permission is contained in this configuration; otherwise, false.
198+
*/
199+
fun hasPermission(permission: String): Boolean {
200+
return permissions.any { it.normalizedValue == permission.toUpperCase() }
201+
}
202+
203+
/**
204+
* Adds the specified settings to this configuration.
205+
*
206+
* @param settings The settings to add to this configuration.
207+
* @return Returns a new configuration containing the existing and new settings.
208+
*/
209+
fun addSettings(settings: Iterable<Setting<*>>): Configuration {
210+
return copy(settings = this.settings + settings)
211+
}
212+
213+
/**
214+
* Adds the specified settings to this configuration.
215+
*
216+
* @param settings The settings to add to this configuration.
217+
* @return Returns a new configuration with the specified settings added.
218+
*/
219+
fun addSettings(vararg settings: Setting<*>): Configuration {
220+
return addSettings(settings.toList())
221+
}
222+
223+
/**
224+
* Removes the specified settings from this configuration.
225+
*
226+
* @param settings The settings to remove from this configuration.
227+
* @return Returns a new configuration with the specified settings removed.
228+
*/
229+
fun removeSettings(settings: Iterable<Setting<*>>): Configuration {
230+
return copy(settings = this.settings - settings)
231+
}
232+
233+
/**
234+
* Removes the specified settings from this configuration.
235+
*
236+
* @param settings The settings to remove from this configuration.
237+
* @return Returns a new configuration with the specified settings removed.
238+
*/
239+
fun removeSettings(vararg settings: Setting<*>): Configuration {
240+
return removeSettings(settings.toList())
241+
}
242+
243+
/**
244+
* Adds the specified roles to this configuration.
245+
*
246+
* @param roles The roles to add to this configuration.
247+
* @return Returns a new configuration with the specified roles added.
248+
*/
249+
fun addRoles(roles: Iterable<Role>): Configuration {
250+
return copy(settings = this.settings + roles)
251+
}
252+
253+
/**
254+
* Adds the specified roles to this configuration.
255+
*
256+
* @param roles The roles to add to this configuration.
257+
* @return Returns a new configuration with the specified roles added.
258+
*/
259+
fun addRoles(vararg roles: Role): Configuration {
260+
return addRoles(roles.toList())
261+
}
262+
263+
/**
264+
* Removes the specified roles from this configuration.
265+
*
266+
* @param roles The roles to remove from this configuration.
267+
* @return Returns a new configuration with the specified roles removed.
268+
*/
269+
fun removeRoles(roles: Iterable<Role>): Configuration {
270+
return copy(settings = this.settings - roles)
271+
}
272+
273+
/**
274+
* Removes the specified roles from this configuration.
275+
*
276+
* @param roles The roles to remove from this configuration.
277+
* @return Returns a new configuration with the specified roles removed.
278+
*/
279+
fun removeRoles(vararg roles: Role): Configuration {
280+
return removeRoles(roles.toList())
281+
}
282+
283+
/**
284+
* Adds the specified permissions to this configuration.
285+
*
286+
* @param permissions The permissions to add to this configuration.
287+
* @return Returns a new configuration with the specified permissions added.
288+
*/
289+
fun addPermissions(permissions: Iterable<Permission>): Configuration {
290+
return copy(settings = this.settings + permissions)
291+
}
292+
293+
/**
294+
* Adds the specified permissions to this configuration.
295+
*
296+
* @param permissions The permissions to add to this configuration.
297+
* @return Returns a new configuration with the specified permissions added.
298+
*/
299+
fun addPermissions(vararg permissions: Permission): Configuration {
300+
return addPermissions(permissions.toList())
301+
}
302+
303+
/**
304+
* Removes the specified permissions from this configuration.
305+
*
306+
* @param permissions The permissions to remove from this configuration.
307+
* @return Returns a new configuration with the specified permissions removed.
308+
*/
309+
fun removePermissions(permissions: Iterable<Permission>): Configuration {
310+
return copy(settings = this.settings - permissions)
311+
}
312+
313+
/**
314+
* Removes the specified permissions from this configuration.
315+
*
316+
* @param permissions The permissions to remove from this configuration.
317+
* @return Returns a new configuration with the specified permissions removed.
318+
*/
319+
fun removePermissions(vararg permissions: Permission): Configuration {
320+
return removePermissions(permissions.toList())
321+
}
322+
323+
/**
324+
* Computes the hash of all settings.
325+
*/
326+
private fun computeHash(): SecureHash {
327+
return if (settings.count() == 0) return SecureHash.zeroHash
328+
else settings.map { it.hash }.sorted().reduce { lhs, rhs -> SecureHash.sha256("$lhs$rhs") }
329+
}
330+
}

0 commit comments

Comments
 (0)