Skip to content

Commit

Permalink
refactor(gate): business partner service
Browse files Browse the repository at this point in the history
 - employ early mapping from DTO to entity in order to make the service logic reusable for different DTOs (L/S/A DTOs for example)
 - merge more methods containing the same business logic
  • Loading branch information
nicoprow committed Oct 5, 2023
1 parent 8f791a2 commit a1ab2e3
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@

package org.eclipse.tractusx.bpdm.common.dto

enum class AddressType {
enum class AddressType(val businessPartnerTypes: Collection<BusinessPartnerType>) {

LegalAndSiteMainAddress,
LegalAddress,
SiteMainAddress,
AdditionalAddress
LegalAndSiteMainAddress(listOf(BusinessPartnerType.LEGAL_ENTITY, BusinessPartnerType.SITE)),
LegalAddress(listOf(BusinessPartnerType.LEGAL_ENTITY)),
SiteMainAddress(listOf(BusinessPartnerType.SITE)),
AdditionalAddress(listOf(BusinessPartnerType.ADDRESS))
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,37 @@ fun <T> MutableCollection<T>.replace(elements: Collection<T>) {
addAll(elements)
}


/**
* Copy overlapping elements by index from [elements] to [this] collection by applying the [copyFunction].
* Remove remaining elements in the original collection and add additional [elements] from given collection
*/
fun <T> MutableCollection<T>.copyAndSync(elements: Collection<T>, copyFunction: (T, T) -> T) {
// copy the overlap of the two collections
zip(elements).forEach { (fromState, toState) -> copyFunction(fromState, toState) }

val sizeDifference = size - elements.size
if (sizeDifference > 0) {
//Remove the remaining elements from the original collection
drop(elements.size).forEach { remove(it) }
} else {
//Add the additional elements to the original collection
addAll(elements.drop(size))
}
}

/**
* Partitions the elements in the collection according to the [predicate] function and subsequently applies [transform] to the partitioned elements
*/
fun <T, R> Collection<T>.partitionAndMap(
predicate: (T) -> Boolean,
transform: (T) -> R
): Pair<List<R>, List<R>> {

val (first, second) = partition { predicate(it) }
return Pair(first.map { transform(it) }, second.map { transform(it) })
}

fun <T> Collection<T>.findDuplicates(): Set<T> =
this.groupBy { it }
.filter { it.value.size > 1 }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,47 +29,47 @@ class PhysicalPostalAddress(
@AttributeOverride(name = "latitude", column = Column(name = "phy_latitude"))
@AttributeOverride(name = "longitude", column = Column(name = "phy_longitude"))
@AttributeOverride(name = "altitude", column = Column(name = "phy_altitude"))
val geographicCoordinates: GeographicCoordinate?,
var geographicCoordinates: GeographicCoordinate?,

@Column(name = "phy_country")
@Enumerated(EnumType.STRING)
val country: CountryCode?,
var country: CountryCode?,

/**
* Region within the country
*/
@Column(name = "phy_admin_area_l1_region")
val administrativeAreaLevel1: String?,
var administrativeAreaLevel1: String?,

/**
* Further possibility to describe the region/address(e.g. County)
*/
@Column(name = "phy_admin_area_l2")
val administrativeAreaLevel2: String?,
var administrativeAreaLevel2: String?,

/**
* Further possibility to describe the region/address(e.g. Township)
*/
@Column(name = "phy_admin_area_l3")
val administrativeAreaLevel3: String?,
var administrativeAreaLevel3: String?,

/**
* A postal code, also known as postcode, PIN or ZIP Code
*/
@Column(name = "phy_postcode")
val postalCode: String?,
var postalCode: String?,

/**
* The city of the address (Synonym: Town, village, municipality)
*/
@Column(name = "phy_city")
val city: String?,
var city: String?,

/**
* Divides the city in several smaller areas
*/
@Column(name = "phy_district_l1")
val district: String?,
var district: String?,

@Embedded
@AttributeOverride(name = "name", column = Column(name = "phy_street_name"))
Expand All @@ -80,37 +80,37 @@ class PhysicalPostalAddress(
@AttributeOverride(name = "additionalNamePrefix", column = Column(name = "phy_additional_name_prefix"))
@AttributeOverride(name = "nameSuffix", column = Column(name = "phy_name_suffix"))
@AttributeOverride(name = "additionalNameSuffix", column = Column(name = "phy_additional_name_suffix"))
val street: Street?,
var street: Street?,

// specific for PhysicalPostalAddress

/**
* A separate postal code for a company, also known as postcode, PIN or ZIP Code
*/
@Column(name = "phy_company_postcode")
val companyPostalCode: String?,
var companyPostalCode: String?,

/**
* The practice of designating an area for industrial development
*/
@Column(name = "phy_industrial_zone")
val industrialZone: String?,
var industrialZone: String?,

/**
* Describes a specific building within the address
*/
@Column(name = "phy_building")
val building: String?,
var building: String?,

/**
* Describes the floor/level the delivery shall take place
*/
@Column(name = "phy_floor")
val floor: String?,
var floor: String?,

/**
* Describes the door/room/suite on the respective floor the delivery shall take place
*/
@Column(name = "phy_door")
val door: String?
var door: String?
)
Original file line number Diff line number Diff line change
Expand Up @@ -36,43 +36,43 @@ class BusinessPartner(
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "business_partners_name_parts", joinColumns = [JoinColumn(name = "business_partner_id")])
@OrderColumn(name = "name_parts_order")
var nameParts: MutableList<String> = mutableListOf(),
val nameParts: MutableList<String> = mutableListOf(),

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "business_partners_roles", joinColumns = [JoinColumn(name = "business_partner_id")])
@Enumerated(EnumType.STRING)
@Column(name = "role_name")
var roles: SortedSet<BusinessPartnerRole> = sortedSetOf(),
val roles: SortedSet<BusinessPartnerRole> = sortedSetOf(),

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "business_partners_identifiers", joinColumns = [JoinColumn(name = "business_partner_id")])
var identifiers: SortedSet<Identifier> = sortedSetOf(),
val identifiers: SortedSet<Identifier> = sortedSetOf(),

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "business_partners_states", joinColumns = [JoinColumn(name = "business_partner_id")])
var states: SortedSet<State> = sortedSetOf(),
val states: SortedSet<State> = sortedSetOf(),

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "business_partners_classifications", joinColumns = [JoinColumn(name = "business_partner_id")])
var classifications: SortedSet<Classification> = sortedSetOf(),
val classifications: SortedSet<Classification> = sortedSetOf(),

@Column(name = "short_name")
var shortName: String?,
var shortName: String? = null,

@Column(name = "legal_form")
var legalForm: String?,
var legalForm: String? = null,

@Column(name = "is_owner")
var isOwner: Boolean,
var isOwner: Boolean = false,

@Column(name = "bpnl")
var bpnL: String?,
var bpnL: String? = null,

@Column(name = "bpns")
var bpnS: String?,
var bpnS: String? = null,

@Column(name = "bpna")
var bpnA: String?,
var bpnA: String? = null,

@OneToOne(cascade = [CascadeType.ALL], orphanRemoval = true)
@JoinColumn(name = "postal_address_id", unique = true)
Expand All @@ -83,10 +83,10 @@ class BusinessPartner(
var stage: StageType,

@Column(name = "parent_id")
var parentId: String?,
var parentId: String? = null,

@Column(name = "parent_type")
@Enumerated(EnumType.STRING)
var parentType: BusinessPartnerType?
var parentType: BusinessPartnerType? = null

) : BaseEntity()
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ data class Classification(

@Column(name = "type")
@Enumerated(EnumType.STRING)
val type: ClassificationType,
var type: ClassificationType,

@Column(name = "code")
var code: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ class PostalAddress(

@Column(name = "address_type")
@Enumerated(EnumType.STRING)
var addressType: AddressType?,
var addressType: AddressType? = null,

@Embedded
var physicalPostalAddress: PhysicalPostalAddress?,
var physicalPostalAddress: PhysicalPostalAddress? = null,

@Embedded
var alternativePostalAddress: AlternativePostalAddress?
var alternativePostalAddress: AlternativePostalAddress? = null

) : BaseEntity()
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ data class State(

@Column(name = "type", nullable = false)
@Enumerated(EnumType.STRING)
val type: BusinessStateType,
var type: BusinessStateType,

@Column(name = "description")
var description: String?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2021,2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/

package org.eclipse.tractusx.bpdm.gate.exception

import org.eclipse.tractusx.bpdm.common.model.StageType
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ResponseStatus

@ResponseStatus(HttpStatus.BAD_REQUEST)
class BpdmMissingStageException(
externalIds: Collection<String>,
stageType: StageType
) : RuntimeException("Business Partner Stage $stageType does not exist for business partner with external identifiers: ${externalIds.joinToString()}.")
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

package org.eclipse.tractusx.bpdm.gate.service

import org.eclipse.tractusx.bpdm.common.dto.*
import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerIdentifierDto
import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerStateDto
import org.eclipse.tractusx.bpdm.common.dto.ClassificationDto
import org.eclipse.tractusx.bpdm.common.dto.GeoCoordinateDto
import org.eclipse.tractusx.bpdm.common.exception.BpdmNullMappingException
import org.eclipse.tractusx.bpdm.common.model.StageType
import org.eclipse.tractusx.bpdm.common.util.replace
import org.eclipse.tractusx.bpdm.gate.api.model.AlternativePostalAddressGateDto
import org.eclipse.tractusx.bpdm.gate.api.model.BusinessPartnerPostalAddressDto
import org.eclipse.tractusx.bpdm.gate.api.model.PhysicalPostalAddressGateDto
Expand Down Expand Up @@ -83,9 +85,9 @@ class BusinessPartnerMappings {
)
}

fun toBusinessPartner(dto: BusinessPartnerInputRequest, stage: StageType, parentId: String?, parentType: BusinessPartnerType?): BusinessPartner {
fun toBusinessPartnerInput(dto: BusinessPartnerInputRequest): BusinessPartner {
return BusinessPartner(
stage = stage,
stage = StageType.Input,
externalId = dto.externalId,
nameParts = dto.nameParts.toMutableList(),
roles = dto.roles.toSortedSet(),
Expand All @@ -99,32 +101,15 @@ class BusinessPartnerMappings {
bpnS = dto.bpnS,
bpnA = dto.bpnA,
postalAddress = toPostalAddress(dto.postalAddress),
parentId = parentId,
parentType = parentType,
parentId = null,
parentType = null,
)
}

fun updateBusinessPartner(entity: BusinessPartner, dto: BusinessPartnerInputRequest, parentId: String?, parentType: BusinessPartnerType?) {
entity.nameParts.replace(dto.nameParts)
entity.roles.replace(dto.roles)
entity.identifiers.replace(dto.identifiers.map(::toIdentifier))
entity.states.replace(dto.states.map(::toState))
entity.classifications.replace(dto.classifications.map(::toClassification))
entity.shortName = dto.shortName
entity.legalForm = dto.legalForm
entity.isOwner = dto.isOwner
entity.bpnL = dto.bpnL
entity.bpnS = dto.bpnS
entity.bpnA = dto.bpnA
entity.parentId = parentId
entity.parentType = parentType
updatePostalAddress(entity.postalAddress, dto.postalAddress)
}

//Output
fun toBusinessPartnerOutput(dto: BusinessPartnerOutputRequest, stage: StageType, parentId: String?, parentType: BusinessPartnerType?): BusinessPartner {
fun toBusinessPartnerOutput(dto: BusinessPartnerOutputRequest): BusinessPartner {
return BusinessPartner(
stage = stage,
stage = StageType.Output,
externalId = dto.externalId,
nameParts = dto.nameParts.toMutableList(),
roles = dto.roles.toSortedSet(),
Expand All @@ -137,29 +122,12 @@ class BusinessPartnerMappings {
bpnL = dto.bpnL,
bpnS = dto.bpnS,
bpnA = dto.bpnA,
parentId = parentId,
parentType = parentType,
parentId = null,
parentType = null,
postalAddress = toPostalAddress(dto.postalAddress)
)
}

fun updateBusinessPartnerOutput(entity: BusinessPartner, dto: BusinessPartnerOutputRequest, parentId: String?, parentType: BusinessPartnerType?) {
entity.nameParts.replace(dto.nameParts)
entity.roles.replace(dto.roles)
entity.identifiers.replace(dto.identifiers.map(::toIdentifier))
entity.states.replace(dto.states.map(::toState))
entity.classifications.replace(dto.classifications.map(::toClassification))
entity.shortName = dto.shortName
entity.legalForm = dto.legalForm
entity.isOwner = dto.isOwner
entity.bpnL = dto.bpnL
entity.bpnS = dto.bpnS
entity.bpnA = dto.bpnA
entity.parentId = parentId
entity.parentType = parentType
updatePostalAddress(entity.postalAddress, dto.postalAddress)
}

private fun toPostalAddressDto(entity: PostalAddress) =
BusinessPartnerPostalAddressDto(
addressType = entity.addressType,
Expand All @@ -174,12 +142,6 @@ class BusinessPartnerMappings {
alternativePostalAddress = normalize(dto.alternativePostalAddress)?.let(::toAlternativePostalAddress)
)

private fun updatePostalAddress(entity: PostalAddress, dto: BusinessPartnerPostalAddressDto) {
entity.addressType = dto.addressType
entity.physicalPostalAddress = normalize(dto.physicalPostalAddress)?.let(::toPhysicalPostalAddress)
entity.alternativePostalAddress = normalize(dto.alternativePostalAddress)?.let(::toAlternativePostalAddress)
}

private fun toPhysicalPostalAddressDto(entity: PhysicalPostalAddress) =
PhysicalPostalAddressGateDto(
geographicCoordinates = entity.geographicCoordinates?.let(::toGeoCoordinateDto),
Expand Down
Loading

0 comments on commit a1ab2e3

Please sign in to comment.