[CORDA-2210] Add matching party on the first X500 attribute match (#4211)

This commit is contained in:
Konstantinos Chalkias
2018-11-12 11:59:04 +00:00
committed by GitHub
parent 81418ca7e7
commit 23907c40d9
3 changed files with 19 additions and 20 deletions

View File

@ -36,22 +36,17 @@ interface IdentityServiceInternal : IdentityService {
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class) @Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
fun verifyAndRegisterIdentity(identity: PartyAndCertificate, isNewRandomIdentity: Boolean): PartyAndCertificate? fun verifyAndRegisterIdentity(identity: PartyAndCertificate, isNewRandomIdentity: Boolean): PartyAndCertificate?
fun partiesFromName(query: String, exactMatch: Boolean, x500name: CordaX500Name, results: LinkedHashSet<Party>, party: Party) { // We can imagine this being a query over a lucene index in future.
//
// Kostas says: When exactMatch = false, we can easily use the Jaro-Winkler distance metric as it is best suited for short
// strings such as entity/company names, and to detect small typos. We can also apply it for city
// or any keyword related search in lists of records (not raw text - for raw text we need indexing)
// and we can return results in hierarchical order (based on normalised String similarity 0.0-1.0).
/** Check if [x500name] matches the [query]. */
fun x500Matches(query: String, exactMatch: Boolean, x500name: CordaX500Name): Boolean {
val components = listOfNotNull(x500name.commonName, x500name.organisationUnit, x500name.organisation, x500name.locality, x500name.state, x500name.country) val components = listOfNotNull(x500name.commonName, x500name.organisationUnit, x500name.organisation, x500name.locality, x500name.state, x500name.country)
components.forEach { component -> return components.any { (exactMatch && it == query)
if (exactMatch && component == query) { || (!exactMatch && it.contains(query, ignoreCase = true)) }
results += party
} else if (!exactMatch) {
// We can imagine this being a query over a lucene index in future.
//
// Kostas says: We can easily use the Jaro-Winkler distance metric as it is best suited for short
// strings such as entity/company names, and to detect small typos. We can also apply it for city
// or any keyword related search in lists of records (not raw text - for raw text we need indexing)
// and we can return results in hierarchical order (based on normalised String similarity 0.0-1.0).
if (component.contains(query, ignoreCase = true))
results += party
}
}
} }
/** /**

View File

@ -63,8 +63,10 @@ class InMemoryIdentityService(identities: List<PartyAndCertificate> = emptyList(
override fun partiesFromName(query: String, exactMatch: Boolean): Set<Party> { override fun partiesFromName(query: String, exactMatch: Boolean): Set<Party> {
val results = LinkedHashSet<Party>() val results = LinkedHashSet<Party>()
for ((x500name, partyAndCertificate) in principalToParties) { principalToParties.forEach { (x500name, partyAndCertificate) ->
partiesFromName(query, exactMatch, x500name, results, partyAndCertificate.party) if (x500Matches(query, exactMatch, x500name)) {
results += partyAndCertificate.party
}
} }
return results return results
} }

View File

@ -143,7 +143,7 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri
val key = mapToKey(identity) val key = mapToKey(identity)
if (isNewRandomIdentity) { if (isNewRandomIdentity) {
// Because this is supposed to be new and random, there's no way we have it in the database already, so skip the pessimistic check. // Because this is supposed to be new and random, there's no way we have it in the database already, so skip the pessimistic check.
keyToParties.set(key, identity) keyToParties[key] = identity
} else { } else {
keyToParties.addWithDuplicatesAllowed(key, identity) keyToParties.addWithDuplicatesAllowed(key, identity)
} }
@ -174,8 +174,10 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri
override fun partiesFromName(query: String, exactMatch: Boolean): Set<Party> { override fun partiesFromName(query: String, exactMatch: Boolean): Set<Party> {
return database.transaction { return database.transaction {
val results = LinkedHashSet<Party>() val results = LinkedHashSet<Party>()
for ((x500name, partyId) in principalToParties.allPersisted()) { principalToParties.allPersisted().forEach { (x500name, partyId) ->
partiesFromName(query, exactMatch, x500name, results, keyToParties[partyId]!!.party) if (x500Matches(query, exactMatch, x500name)) {
results += keyToParties[partyId]!!.party
}
} }
results results
} }