[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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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)
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)
components.forEach { component ->
if (exactMatch && component == query) {
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
}
}
return components.any { (exactMatch && it == query)
|| (!exactMatch && it.contains(query, ignoreCase = true)) }
}
/**

View File

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

View File

@ -143,7 +143,7 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri
val key = mapToKey(identity)
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.
keyToParties.set(key, identity)
keyToParties[key] = identity
} else {
keyToParties.addWithDuplicatesAllowed(key, identity)
}
@ -174,8 +174,10 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri
override fun partiesFromName(query: String, exactMatch: Boolean): Set<Party> {
return database.transaction {
val results = LinkedHashSet<Party>()
for ((x500name, partyId) in principalToParties.allPersisted()) {
partiesFromName(query, exactMatch, x500name, results, keyToParties[partyId]!!.party)
principalToParties.allPersisted().forEach { (x500name, partyId) ->
if (x500Matches(query, exactMatch, x500name)) {
results += keyToParties[partyId]!!.party
}
}
results
}