Skip to content

Commit

Permalink
Merge pull request #516 from catenax-ng/feat/cleaning_service/Create_…
Browse files Browse the repository at this point in the history
…cleaning_result

Feat: Implement Cleaning Logic on Reserve Task
  • Loading branch information
nicoprow authored Oct 18, 2023
2 parents 4e7ca38 + 96bc9a7 commit 599e98c
Show file tree
Hide file tree
Showing 10 changed files with 969 additions and 1 deletion.
16 changes: 16 additions & 0 deletions bpdm-cleaning-service-dummy/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@
</exclusions>
</dependency>

<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ninja-squad</groupId>
<artifactId>springmockk</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
import org.springframework.boot.runApplication
import org.springframework.scheduling.annotation.EnableScheduling

@SpringBootApplication(exclude=[DataSourceAutoConfiguration::class])
@ConfigurationPropertiesScan
@EnableScheduling
class Application

fun main(args: Array<String>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*******************************************************************************
* 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.cleaning.config


import org.eclipse.tractusx.orchestrator.api.client.OrchestrationApiClient
import org.eclipse.tractusx.orchestrator.api.client.OrchestrationApiClientImpl
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction
import org.springframework.web.reactive.function.client.WebClient
import java.util.function.Consumer


@Configuration
class ClientsConfig {


@Bean
@ConditionalOnProperty(
value = ["bpdm.orchestrator.security-enabled"],
havingValue = "false",
matchIfMissing = true
)
fun orchestratorClientNoAuth(poolConfigProperties: OrchestratorConfigProperties): OrchestrationApiClient {
val url = poolConfigProperties.baseUrl
return OrchestrationApiClientImpl { webClientBuilder(url).build() }
}


@Bean
@ConditionalOnProperty(
value = ["bpdm.orchestrator.security-enabled"],
havingValue = "true"
)
fun orchestratorClientWithAuth(
poolConfigProperties: OrchestratorConfigProperties,
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientService: OAuth2AuthorizedClientService
): OrchestrationApiClient {
val url = poolConfigProperties.baseUrl
val clientRegistrationId = poolConfigProperties.oauth2ClientRegistration
?: throw IllegalArgumentException("bpdm.orchestrator.oauth2-client-registration is required if bpdm.orchestrator.security-enabled is set")
return OrchestrationApiClientImpl {
webClientBuilder(url)
.apply(oauth2Configuration(clientRegistrationRepository, authorizedClientService, clientRegistrationId))
.build()
}
}


private fun webClientBuilder(url: String) =
WebClient.builder()
.baseUrl(url)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)

private fun oauth2Configuration(
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientService: OAuth2AuthorizedClientService,
clientRegistrationId: String
): Consumer<WebClient.Builder> {
val authorizedClientManager = authorizedClientManager(clientRegistrationRepository, authorizedClientService)
val oauth = ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager)
oauth.setDefaultClientRegistrationId(clientRegistrationId)
return oauth.oauth2Configuration()
}

private fun authorizedClientManager(
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientService: OAuth2AuthorizedClientService
): OAuth2AuthorizedClientManager {
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials().build()
val authorizedClientManager = AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}

}
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.cleaning.config

import org.springframework.boot.context.properties.ConfigurationProperties


@ConfigurationProperties(prefix = "bpdm.orchestrator")
data class OrchestratorConfigProperties(
val baseUrl: String = "http://localhost:8085/",
val securityEnabled: Boolean = false,
val oauth2ClientRegistration: String?
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*******************************************************************************
* 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.cleaning.service


import mu.KotlinLogging
import org.eclipse.tractusx.bpdm.common.dto.AddressType
import org.eclipse.tractusx.orchestrator.api.client.OrchestrationApiClient
import org.eclipse.tractusx.orchestrator.api.model.*
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service
import java.util.*

@Service
class CleaningServiceDummy(
private val orchestrationApiClient: OrchestrationApiClient,

) {

private val logger = KotlinLogging.logger { }


@Scheduled(cron = "\${cleaningService.pollingCron:-}", zone = "UTC")
fun pollForCleaningTasks() {
try {
logger.info { "Starting polling for cleaning tasks from Orchestrator..." }

// Step 1: Fetch and reserve the next cleaning request
val cleaningRequest = orchestrationApiClient.goldenRecordTasks
.reserveTasksForStep(TaskStepReservationRequest(amount = 10, TaskStep.CleanAndSync))

val cleaningTasks = cleaningRequest.reservedTasks

logger.info { "${cleaningTasks.size} tasks found for cleaning. Proceeding with cleaning..." }

if (cleaningTasks.isNotEmpty()) {

val cleaningResults = cleaningTasks.map { reservedTask ->
// Step 2: Generate dummy cleaning results
processCleaningTask(reservedTask)
}

// Step 3: Send the cleaning result back to the Orchestrator
orchestrationApiClient.goldenRecordTasks.resolveStepResults(TaskStepResultRequest(cleaningResults))
logger.info { "Cleaning tasks processing completed for this iteration." }
}
} catch (e: Exception) {
logger.error(e) { "Error while processing cleaning task" }
}
}

fun processCleaningTask(reservedTask: TaskStepReservationEntryDto): TaskStepResultEntryDto {
val genericBusinessPartner = reservedTask.businessPartner.generic

val addressPartner = createAddressRepresentation(genericBusinessPartner)

val addressType = genericBusinessPartner.postalAddress.addressType ?: AddressType.AdditionalAddress

val legalEntityDto = createLegalEntityRepresentation(addressPartner, addressType, genericBusinessPartner)

val siteDto = createSiteDtoIfNeeded(genericBusinessPartner, addressPartner)

val addressDto = shouldCreateAddress(addressType, addressPartner)

return TaskStepResultEntryDto(reservedTask.taskId, BusinessPartnerFullDto(genericBusinessPartner, legalEntityDto, siteDto, addressDto))
}

private fun shouldCreateAddress(
addressType: AddressType,
addressPartner: LogisticAddressDto
): LogisticAddressDto? {
val addressDto = if (addressType == AddressType.AdditionalAddress) {
addressPartner
} else {
null
}
return addressDto
}

fun createSiteDtoIfNeeded(businessPartner: BusinessPartnerGenericDto, addressPartner: LogisticAddressDto): SiteDto? {
if (!shouldCreateSite(businessPartner)) return null

val siteAddressReference = when (businessPartner.postalAddress.addressType) {
AddressType.SiteMainAddress, AddressType.LegalAndSiteMainAddress -> addressPartner.bpnAReference
else -> generateNewBpnRequestIdentifier()
}

val siteMainAddress = addressPartner.copy(bpnAReference = siteAddressReference)
return createSiteRepresentation(businessPartner, siteMainAddress)
}

fun createLegalEntityRepresentation(
addressPartner: LogisticAddressDto,
addressType: AddressType,
genericPartner: BusinessPartnerGenericDto
): LegalEntityDto {
val legalAddressBpnReference = if (addressType == AddressType.LegalAddress || addressType == AddressType.LegalAndSiteMainAddress) {
addressPartner.bpnAReference
} else {
generateNewBpnRequestIdentifier()
}

val legalAddress = addressPartner.copy(bpnAReference = legalAddressBpnReference)

val bpnReferenceDto = createBpnReference(genericPartner.bpnL)

return genericPartner.toLegalEntityDto(bpnReferenceDto, legalAddress)

}

fun createAddressRepresentation(genericPartner: BusinessPartnerGenericDto): LogisticAddressDto {
val bpnReferenceDto = createBpnReference(genericPartner.bpnA)
return genericPartner.toLogisticAddressDto(bpnReferenceDto)
}

fun createSiteRepresentation(genericPartner: BusinessPartnerGenericDto, siteAddressReference: LogisticAddressDto): SiteDto {
val legalName = genericPartner.nameParts.joinToString(" ")
val bpnReferenceDto = createBpnReference(genericPartner.bpnS)
return genericPartner.toSiteDto(bpnReferenceDto, legalName, siteAddressReference)
}

fun createBpnReference(bpn: String?): BpnReferenceDto {
return if (bpn != null) {
BpnReferenceDto(bpn, BpnReferenceType.Bpn)
} else {
// Generate a new UUID and create a BpnReferenceDto object if bpnL/bpnS/bpnA is null
generateNewBpnRequestIdentifier()
}
}

private fun generateNewBpnRequestIdentifier() = BpnReferenceDto(UUID.randomUUID().toString(), BpnReferenceType.BpnRequestIdentifier)

fun shouldCreateSite(genericPartner: BusinessPartnerGenericDto): Boolean {
return genericPartner.postalAddress.addressType == AddressType.SiteMainAddress ||
genericPartner.postalAddress.addressType == AddressType.LegalAndSiteMainAddress ||
genericPartner.bpnS != null
}


}
Loading

0 comments on commit 599e98c

Please sign in to comment.